@hlix/cli 0.7.0 → 0.7.2

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.
@@ -0,0 +1,446 @@
1
+ #!/usr/bin/env node
2
+ class e extends Error{code;details;constructor(j,O,T){super(O);if(this.name="CliError",this.code=j,T!==void 0)this.details=T}}var R=1,re=(j,O)=>({schemaVersion:1,command:j,data:O}),en=(j,O)=>({schemaVersion:1,command:j,error:O});function ne(j){return`${JSON.stringify(j,null,2)}
3
+ `}function ve(j){let O=Math.max(0,...j.map(([T])=>T.length));return j.map(([T,N])=>`${T.padEnd(O)} ${N}`).join(`
4
+ `)}function Ge(j,O){let T=j.map((H,F)=>Math.max(H.length,...O.map((M)=>(M[F]??"").length))),N=(H)=>H.map((F,M)=>F.padEnd(T[M])).join(" ").trimEnd();return[N(j),N(T.map((H)=>"-".repeat(H))),...O.map(N)].join(`
5
+ `)}import{statSync as Ha}from"node:fs";import{dirname as Ma,resolve as La}from"node:path";import{closeSync as Sr,constants as tn,existsSync as Ln,fsyncSync as fo,lstatSync as jr,mkdirSync as Ea,openSync as go,readFileSync as ho,renameSync as $a,statSync as yo,unlinkSync as wo,writeFileSync as xa}from"node:fs";import{homedir as Ca}from"node:os";import{dirname as Ia,join as Pr}from"node:path";function ze(j=process.env){let O=j.HLIX_CONFIG_HOME??j.XDG_CONFIG_HOME??Pr(Ca(),".config");return Pr(O,"hlix","credentials.json")}function vo(j=process.env){let O=j.HLIX_API_KEY;if(!O&&j.HLIX_SESSION_TOKEN)return{baseUrl:j.HLIX_BASE_URL??"https://server.hlix.ai",apiKey:"",sessionToken:j.HLIX_SESSION_TOKEN,...j.HLIX_WORKSPACE_ID?{organizationId:j.HLIX_WORKSPACE_ID}:{}};if(O)return{baseUrl:j.HLIX_BASE_URL??"https://server.hlix.ai",apiKey:O,...j.HLIX_WORKSPACE_ID?{organizationId:j.HLIX_WORKSPACE_ID}:{}};try{let T=JSON.parse(ho(ze(j),"utf8"));return T.apiKey&&T.baseUrl?T:null}catch{return null}}function bo(j=process.env){let O=ze(j);return Ln(O)?O:null}function Er(j=process.env){let O=ze(j);if(!Ln(O))return{path:O,removed:!1,reason:"absent"};let T=jr(O);if(T.isSymbolicLink()||!T.isFile())throw Error("Refusing to remove a credential path that is not a regular file.");let N=process.getuid?.();if(N!==void 0&&yo(O).uid!==N)throw Error("Refusing to remove a credential file owned by another user.");let H;try{H=JSON.parse(ho(O,"utf8"))}catch{H=null}let F=H;if(!F||typeof F.apiKey!=="string"||typeof F.baseUrl!=="string")throw Error(`Refusing to remove ${O}: it is not a credential written by this CLI.`);return wo(O),{path:O,removed:!0,reason:"removed"}}function ko(j,O=process.env){let T=ze(O),N=Ia(T);if(Ea(N,{recursive:!0,mode:448}),jr(N).isSymbolicLink())throw Error("Refusing to write credentials through a symlinked directory.");if(Ln(T)){let M=jr(T);if(M.isSymbolicLink()||!M.isFile())throw Error("Refusing to replace a credential path that is not a regular file.");let U=process.getuid?.();if(U!==void 0&&yo(T).uid!==U)throw Error("Refusing to replace a credential file owned by another user.")}let H=Pr(N,`.credentials.${process.pid}.${crypto.randomUUID()}.tmp`),F;try{F=go(H,tn.O_WRONLY|tn.O_CREAT|tn.O_EXCL|tn.O_NOFOLLOW,384),xa(F,`${JSON.stringify(j,null,2)}
6
+ `,"utf8"),fo(F),Sr(F),F=void 0,$a(H,T);let M=go(N,tn.O_RDONLY);try{try{fo(M)}catch(U){let L=U.code;if(L!=="EINVAL"&&L!=="ENOTSUP")throw U}}finally{Sr(M)}}catch(M){if(F!==void 0)Sr(F);if(Ln(H))wo(H);throw M}return T}import{appendFileSync as _a,constants as Un,existsSync as xr,lstatSync as Cr,mkdirSync as Ra,openSync as Aa,closeSync as So,fsyncSync as Oa,readFileSync as Ir,renameSync as Ta,unlinkSync as Na,writeFileSync as $r}from"node:fs";import{dirname as Fa,join as nn,resolve as Dn}from"node:path";function jo(j){if(!xr(j))return;let O=Cr(j);if(O.isSymbolicLink()||!O.isFile())throw Error(`Refusing to replace a non-regular Hlix file: ${j}`)}function Ke(j,O){let T=Fa(j);if(Ra(T,{recursive:!0,mode:448}),Cr(T).isSymbolicLink())throw Error(`Refusing to write through a symlinked Hlix directory: ${T}`);jo(j);let N=nn(T,`.hlix-${process.pid}-${crypto.randomUUID()}.tmp`),H;try{H=Aa(N,Un.O_WRONLY|Un.O_CREAT|Un.O_EXCL|Un.O_NOFOLLOW,384),$r(H,`${JSON.stringify(O,null,2)}
7
+ `,"utf8"),Oa(H),So(H),H=void 0,Ta(N,j)}catch(F){if(H!==void 0)So(H);if(xr(N))Na(N);throw F}}function rn(j){return nn(Dn(j),".hlix","config.json")}function Po(j){return nn(Dn(j),".hlix","state.json")}function at(j){try{let O=JSON.parse(Ir(rn(j),"utf8"));return O.schemaVersion===1&&O.workspaceId&&O.apiUrl?O:null}catch{return null}}function wt(j,O){Ke(rn(j),O);let T=nn(Dn(j),".hlix",".gitignore");if(!xr(T))$r(T,`state.json
8
+ import.json
9
+ import.bundle
10
+ `,{mode:420,flag:"wx"});jo(T);let N=Ir(T,"utf8").split(/\r?\n/),H=["import.json","import.bundle"].filter((M)=>!N.includes(M));if(H.length)_a(T,`
11
+ ${H.join(`
12
+ `)}
13
+ `);let F=nn(Dn(j),".hlixignore");if(!Cr(F,{throwIfNoEntry:!1}))$r(F,`# Additional project-local paths to exclude from Hlix snapshots.
14
+ `,{mode:420,flag:"wx"})}function ct(j,O){Ke(Po(j),{...O,snapshotOnly:O.snapshotOnly??s(j)?.snapshotOnly,includedPaths:O.includedPaths??s(j)?.includedPaths})}function s(j){try{let O=JSON.parse(Ir(Po(j),"utf8"));return O.schemaVersion===1&&O.revisionId&&O.generation>0?O:null}catch{return null}}var _r="https://server.hlix.ai";function u(j){if(!j.credential)return null;if(j.credentialSource==="session")return"session (desktop)";if(j.credentialSource==="env")return"environment (HLIX_API_KEY)";return`file (${j.credentialPath})`}function t(j){let O=La(j);for(;;){let T=at(O);if(T)return{root:O,config:T};let N=Ma(O);if(N===O)return null;O=N}}function $o(j){try{return Ha(j).isDirectory()}catch{return!1}}function Bn(j){if(typeof j!=="string")return;let O=j.trim();return O?O:void 0}var Eo=(j,O)=>j.replace(/\/+$/,"")===O.replace(/\/+$/,"");function r(j){let{env:O,flags:T,cwd:N}=j,H=t(N),F=vo(O),M=F?O.HLIX_API_KEY?"env":O.HLIX_SESSION_TOKEN?"session":"file":null,U=M==="file"?F:null,L=Bn(T["base-url"]),D=Bn(O.HLIX_BASE_URL),B=Bn(T.workspace),z=Bn(O.HLIX_WORKSPACE_ID),J=L??D??H?.config.apiUrl??U?.baseUrl??_r,K=L?"flag":D?"env":H?.config.apiUrl?"project":U?.baseUrl?"credential":"default",X=B??z??H?.config.workspaceId??U?.organizationId??null,W=B?"flag":z?"env":H?.config.workspaceId?"project":U?.organizationId?"credential":null;return{baseUrl:J,baseUrlSource:K,workspaceId:X,workspaceSource:W,credential:F,credentialSource:M,credentialPath:ze(O),binding:H,conflict:Ua(H,{flagBaseUrl:L,envBaseUrl:D,flagWorkspace:B,envWorkspace:z})}}function Ua(j,O){if(!j)return null;let T=`${j.root} is bound to`,N="Drop the override, or point --cwd at a folder bound to it.";if(O.flagWorkspace&&O.flagWorkspace!==j.config.workspaceId)return`${T} workspace ${j.config.workspaceId}, but --workspace names ${O.flagWorkspace}. ${N}`;if(O.envWorkspace&&O.envWorkspace!==j.config.workspaceId)return`${T} workspace ${j.config.workspaceId}, but HLIX_WORKSPACE_ID names ${O.envWorkspace}. ${N}`;if(O.flagBaseUrl&&!Eo(O.flagBaseUrl,j.config.apiUrl))return`${T} ${j.config.apiUrl}, but --base-url names ${O.flagBaseUrl}. ${N}`;if(O.envBaseUrl&&!Eo(O.envBaseUrl,j.config.apiUrl))return`${T} ${j.config.apiUrl}, but HLIX_BASE_URL names ${O.envBaseUrl}. ${N}`;return null}import{resolve as Qa}from"node:path";import{parseArgs as ec}from"node:util";import Da from"openapi-fetch";function Rr(j){return Da({baseUrl:j.baseUrl,headers:j.headers,fetch:j.fetch})}var Ot=(j)=>({kind:"apiKey",apiKey:j});var Ar=(j)=>({kind:"bearer",token:j});function Ba(j){switch(j.kind){case"apiKey":return{"x-api-key":j.apiKey};case"session":return{cookie:j.cookie};case"bearer":return{authorization:`Bearer ${j.token}`}}}function za(j){return j?{"X-Organization-Id":j}:{}}function xo(j,O){return{...Ba(j),...za(O)}}function Wa(j){if(typeof j!=="object"||j===null)return null;let{error:O}=j;return typeof O==="string"?O:null}class Ie extends Error{status;body;requestId;method;url;constructor(j,O){super(j);this.name=new.target.name,this.status=O.status,this.body=O.body,this.requestId=O.requestId??null,this.method=O.method,this.url=O.url}}class Tt extends Ie{issues;constructor(j,O,T){super(j,O);this.issues=T}}class sn extends Ie{}class on extends Ie{}class an extends Ie{}class Ve extends Ie{}class vt extends Ie{}class cn extends Ie{retryAfter;constructor(j,O,T){super(j,O);this.retryAfter=T}}class ln extends Ie{}class lt extends Ie{}class Ye extends Error{method;url;constructor(j,O){super(j,{cause:O.cause});this.name="HlixTransportError",this.method=O.method,this.url=O.url}}function Ja(j){if(typeof j!=="object"||j===null)return null;let O=j;if(O.success!==!1)return null;let T=O.error?.message;if(typeof T!=="string")return null;try{let N=JSON.parse(T);return Array.isArray(N)?N:[]}catch{return[]}}function qa(j){let O=j.get("retry-after");if(!O)return null;let T=Number(O);return Number.isFinite(T)&&T>=0?T:null}function Nt(j,O,T){let N={status:j.status,body:O,requestId:j.headers.get("x-request-id"),method:T.method,url:T.url},H=Wa(O),F=`${T.method} ${T.url} failed with ${j.status}`,M=Ja(O);if(M)return new Tt(`${T.method} ${T.url}: request body failed validation`,N,M);let U=H??F;switch(j.status){case 400:return new sn(U,N);case 401:return new on(U,N);case 403:return new an(U,N);case 404:return new Ve(U,N);case 409:return new vt(U,N);case 429:return new cn(U,N,qa(j.headers));case 501:return new ln(U,N);default:return j.status>=500?new lt(U,N):new Ie(U,N)}}var Co=new Set(["GET","HEAD","PUT","DELETE","OPTIONS","TRACE"]);function zn(j){return Co.has(j.toUpperCase())}var Ga=new Set([429,500,502,503,504]);function Ka(j){return Ga.has(j)}var Or={attempts:3,baseDelayMs:200,maxDelayMs:5000};function Tr(j,O,T,N=Math.random){if(T!==null)return Math.min(T*1000,O.maxDelayMs);let H=Math.min(O.baseDelayMs*2**j,O.maxDelayMs);return Math.round(N()*H)}function Nr(j){if(!zn(j.method))return!1;if(j.attempt+1>=j.policy.attempts)return!1;return j.status===null||Ka(j.status)}var Va=(j)=>new Promise((O)=>setTimeout(O,j));function Ya(j){let O=j.headers.get("retry-after");if(!O)return null;let T=Number(O);return Number.isFinite(T)&&T>=0?T:null}function Io(j){let{base:O,policy:T}=j,N=j.sleep??Va,H=j.random??Math.random;return async(F)=>{let M=F.method.toUpperCase(),U=zn(M)?F.clone():null;for(let L=0;;L+=1){let D=L===0?F:U.clone(),B;try{B=await O(D)}catch(z){if(!U||!Nr({method:M,attempt:L,policy:T,status:null}))throw new Ye(`${M} ${F.url}: ${z instanceof Error?z.message:String(z)}`,{method:M,url:F.url,cause:z});await N(Tr(L,T,null,H));continue}if(!Nr({method:M,attempt:L,policy:T,status:B.status}))return B;if(!U)return B;await N(Tr(L,T,Ya(B),H))}}}function se(j,O){if(j.response.ok)return j.data;throw Nt(j.response,j.error??j.data,O)}var dn=(j)=>typeof j==="string"?j:"";function Fr(j){let O;try{O=JSON.parse(j)}catch{return null}if(typeof O!=="object"||O===null)return null;let T=O;switch(T.type){case"idle":return{type:"idle"};case"done":return{type:"done"};case"active":return typeof T.runId==="string"?{type:"active",runId:T.runId}:{type:"active"};case"on_chat_model_stream":return{type:"on_chat_model_stream",delta:dn(T.delta)};case"reasoning":return{type:"reasoning",delta:dn(T.delta)};case"on_tool_start":return{type:"on_tool_start",name:dn(T.name),input:T.input};case"on_tool_end":return{type:"on_tool_end",name:dn(T.name),output:T.output};case"error":return{type:"error",message:dn(T.message)};default:return null}}var Hr=(j)=>j.type==="done"||j.type==="idle"||j.type==="error";var Xa=()=>({event:null,data:[],id:null,retry:null});function _o(j,O,T){switch(O){case"event":j.event=T;return;case"data":j.data.push(T);return;case"id":if(!T.includes("\x00"))j.id=T;return;case"retry":{if(/^\d+$/.test(T))j.retry=Number(T);return}default:return}}function Ao(j){let O=j.data.join(`
15
+ `),{event:T,id:N}=j;if(j.data=[],j.event=null,O==="")return null;return{event:T,data:O,id:N,retry:j.retry}}function Ro(j,O){if(O==="")return Ao(j);if(O.startsWith(":"))return null;let T=O.indexOf(":");if(T===-1)return _o(j,O,""),null;let N=O.slice(0,T),H=O.slice(T+1);if(H.startsWith(" "))H=H.slice(1);return _o(j,N,H),null}function Za(j){let O=[],T=0;for(let N=0;N<j.length;N+=1){let H=j[N];if(H!==`
16
+ `&&H!=="\r")continue;if(O.push(j.slice(T,N)),H==="\r"&&j[N+1]===`
17
+ `)N+=1;T=N+1}return{lines:O,rest:j.slice(T)}}async function*Mr(j,O){let T=j.getReader(),N=new TextDecoder,H=Xa(),F="",M=()=>void T.cancel().catch(()=>{});O?.addEventListener("abort",M,{once:!0});try{for(;;){let{done:L,value:D}=await T.read();if(L)break;F+=N.decode(D,{stream:!0});let{lines:B,rest:z}=Za(F);F=z;for(let J of B){let K=Ro(H,J);if(K)yield K}if(O?.aborted)return}if(F+=N.decode(),F!==""){let L=Ro(H,F);if(L)yield L}let U=Ao(H);if(U)yield U}finally{O?.removeEventListener("abort",M),T.releaseLock()}}function Lr(j){let O;try{O=JSON.parse(j)}catch{return null}if(typeof O!=="object"||O===null)return null;let T=O;if(T.kind==="ready")return{kind:"ready"};if(T.kind==="workspace")return{kind:"workspace"};if(T.kind==="head"&&typeof T.revisionId==="string"&&typeof T.generation==="number")return{kind:"head",revisionId:T.revisionId,generation:T.generation};return null}function Oo(j){return j instanceof Ie&&j.status>=400&&j.status<500&&j.status!==408&&j.status!==429}var Wn={firstDelayMs:1000,maxDelayMs:30000};function Ft(j,O){return new Promise((T)=>{if(O?.aborted)return T();let N=setTimeout(H,j);function H(){clearTimeout(N),O?.removeEventListener("abort",H),T()}O?.addEventListener("abort",H,{once:!0})})}class Ht{raw;baseUrl;headers;fetcher;constructor(j){this.baseUrl=j.baseUrl.replace(/\/+$/,"");let O=xo(j.credential,j.organizationId),T=new Set(Object.keys(O).map((F)=>F.toLowerCase()));this.headers={...Object.fromEntries(Object.entries(j.headers??{}).filter(([F])=>!T.has(F.toLowerCase()))),...O};let N={...Or,...j.retry},H=j.fetch??((F)=>globalThis.fetch(F));this.fetcher=Io({base:H,policy:N}),this.raw=Rr({baseUrl:this.baseUrl,headers:this.headers,fetch:this.fetcher})}at(j,O){return{method:j,url:`${this.baseUrl}${O}`}}workspaces={list:async(j={})=>se(await this.raw.GET("/v1/api/workspaces",j),this.at("GET","/v1/api/workspaces"))};projects={list:async()=>se(await this.raw.GET("/v1/api/projects"),this.at("GET","/v1/api/projects")),get:async(j,O={})=>se(await this.raw.GET("/v1/api/projects/{id}",{...O,params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}`)),create:async(j)=>se(await this.raw.POST("/v1/api/projects",{body:j}),this.at("POST","/v1/api/projects")),delete:async(j)=>se(await this.raw.DELETE("/v1/api/projects/{id}",{params:{path:{id:j}}}),this.at("DELETE",`/v1/api/projects/${j}`)),start:async(j,O)=>se(await this.raw.POST("/v1/api/projects/{id}/start",{params:{path:{id:j}},body:O}),this.at("POST",`/v1/api/projects/${j}/start`)),refreshPreview:async(j)=>se(await this.raw.POST("/v1/api/projects/{id}/preview/refresh",{params:{path:{id:j}}}),this.at("POST",`/v1/api/projects/${j}/preview/refresh`)),stop:async(j)=>se(await this.raw.POST("/v1/api/projects/{id}/stop",{params:{path:{id:j}}}),this.at("POST",`/v1/api/projects/${j}/stop`)),status:async(j,O={})=>se(await this.raw.GET("/v1/api/projects/{id}/status",{...O,params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}/status`)),preview:async(j)=>se(await this.raw.GET("/v1/api/projects/{id}/preview",{params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}/preview`)),deliver:async(j)=>se(await this.raw.POST("/v1/api/projects/{id}/delivery",{params:{path:{id:j}}}),this.at("POST",`/v1/api/projects/${j}/delivery`)),connectRepo:async(j,O)=>{let T=await this.raw.POST("/v1/api/projects/{id}/repos/connect",{params:{path:{id:j}},body:O});return se(T,this.at("POST",`/v1/api/projects/${j}/repos/connect`))},attachGithubRepository:async(j,O)=>se(await this.raw.POST("/v1/api/projects/{id}/repos/github",{params:{path:{id:j}},body:{githubRepository:O}}),this.at("POST",`/v1/api/projects/${j}/repos/github`)),terminal:async(j)=>se(await this.raw.GET("/v1/api/projects/{id}/terminal",{params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}/terminal`)),observeAgent:(j,O,T)=>this.observeAgent(j,O,T),workspace:(j)=>({environment:async()=>se(await this.raw.GET("/v1/api/projects/{id}/environment",{params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}/environment`)),fs:async(O)=>se(await this.raw.POST("/v1/api/projects/{id}/workspace/fs",{params:{path:{id:j}},body:O}),this.at("POST",`/v1/api/projects/${j}/workspace/fs`)),exec:async(O)=>se(await this.raw.POST("/v1/api/projects/{id}/workspace/exec",{params:{path:{id:j}},body:O}),this.at("POST",`/v1/api/projects/${j}/workspace/exec`))})};secrets={listEntries:async(j)=>se(await this.raw.GET("/v1/api/secrets/project/{projectId}/entries",{params:{path:{projectId:j}}}),this.at("GET",`/v1/api/secrets/project/${j}/entries`)),upsertEntries:async(j,O)=>se(await this.raw.PUT("/v1/api/secrets/project/{projectId}/entries",{params:{path:{projectId:j}},body:O}),this.at("PUT",`/v1/api/secrets/project/${j}/entries`)),importFiles:async(j,O)=>se(await this.raw.PUT("/v1/api/secrets/project/{projectId}/files",{params:{path:{projectId:j}},body:{files:O}}),this.at("PUT",`/v1/api/secrets/project/${j}/files`)),deleteEntry:async(j,O,T)=>se(await this.raw.DELETE("/v1/api/secrets/project/{projectId}/entries/{key}",{params:{path:{projectId:j,key:O},...T===void 0?{}:{query:{source:T}}}}),this.at("DELETE",`/v1/api/secrets/project/${j}/entries/${encodeURIComponent(O)}`)),exportEntries:async(j,O={})=>{let T=`/v1/api/secrets/project/${j}/export`,N=`${this.baseUrl}${T}`,H=await this.fetcher(new Request(N,{method:"POST",headers:{...this.headers,"content-type":"application/json"},body:JSON.stringify({...O.source===void 0?{}:{source:O.source},...O.format===void 0?{}:{format:O.format}})}));if(!H.ok)throw Nt(H,await H.json().catch(()=>{return}),{method:"POST",url:N});return H.text()}};imports={create:async(j)=>{let O=await this.raw.POST("/v1/api/imports",{body:j});return se(O,this.at("POST","/v1/api/imports"))},get:async(j,O={})=>se(await this.raw.GET("/v1/api/imports/{id}",{signal:O.signal,params:{path:{id:j}}}),this.at("GET",`/v1/api/imports/${j}`)),finalize:async(j,O,T={})=>{let N=await this.raw.POST("/v1/api/imports/{id}/finalize",{signal:T.signal,params:{path:{id:j}},body:O});return se(N,this.at("POST",`/v1/api/imports/${j}/finalize`))},finalizeAndWait:async(j,O,T={})=>{let N=AbortSignal.timeout(T.timeoutMs??600000),H=T.signal?AbortSignal.any([T.signal,N]):N;try{return await this.imports.finalize(j,O,{signal:H})}catch(F){if(H.throwIfAborted(),!(F instanceof lt||F instanceof Ye||F instanceof vt))throw F}return this.imports.waitUntilReady(j,{...T,signal:H})},waitUntilReady:async(j,O={})=>{let T=AbortSignal.timeout(O.timeoutMs??600000),N=O.signal?AbortSignal.any([O.signal,T]):T;while(!0){N.throwIfAborted();try{let H=await this.imports.get(j,{signal:N});if(H.import.status==="ready")return H;if(H.import.status!=="finalizing")throw Error(`Import ${j} is ${H.import.status}: ${H.import.error??"rerun hlix import to resume this session"}`)}catch(H){if(N.throwIfAborted(),!(H instanceof lt||H instanceof Ye))throw H}await Ft(O.pollIntervalMs??2000,N)}},uploadBundle:async(j,O,T={})=>{let N=T.chunkSize??8388608;if(N<=0||N%262144!==0)throw Error("Import upload chunkSize must be a positive multiple of 256 KiB");let H=j.url.startsWith("/")?`${this.baseUrl}${j.url}`:j.url;if(j.kind==="hlix-stream"){let M=new Request(H,{method:"PUT",headers:{...this.headers,"content-type":"application/x-git-bundle","content-length":String(O.size)},body:O,signal:T.signal}),U=await this.fetcher(M);if(!U.ok)await this.throwUploadError(U,H);T.onProgress?.(O.size,O.size);return}let F=0;while(F<O.size){let M=Math.min(F+N,O.size),U=new Request(H,{method:"PUT",headers:{"content-type":"application/x-git-bundle","content-length":String(M-F),"content-range":`bytes ${F}-${M-1}/${O.size}`},body:O.slice(F,M),signal:T.signal}),L=await this.fetcher(U);if(L.status!==308&&!L.ok)await this.throwUploadError(L,H);let D=L.headers.get("range")?.match(/bytes=0-(\d+)/)?.[1];if(F=D?Number(D)+1:M,!Number.isSafeInteger(F)||F<M||F>O.size)throw Error("Import upload server returned an invalid acknowledged range");T.onProgress?.(F,O.size)}}};revisions={head:async(j,O={})=>se(await this.raw.GET("/v1/api/projects/{id}/revisions/head",{...O,params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}/revisions/head`)),protectedFiles:async(j)=>se(await this.raw.GET("/v1/api/projects/{id}/protected-files",{params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}/protected-files`)),createUpload:async(j,O)=>{let T=await this.raw.POST("/v1/api/projects/{id}/revisions/uploads",{params:{path:{id:j}},body:O});return se(T,this.at("POST",`/v1/api/projects/${j}/revisions/uploads`))},finalize:async(j,O,T)=>{let N=await this.raw.POST("/v1/api/projects/{id}/revisions/uploads/{uploadId}/finalize",{params:{path:{id:j,uploadId:O}},body:T});return se(N,this.at("POST",`/v1/api/projects/${j}/revisions/uploads/${O}/finalize`))},uploadBundle:async(j,O,T={})=>this.imports.uploadBundle(j,O,T),watch:(j,O)=>this.watchRevisions(j,O),downloadBundle:async(j,O)=>{let T=`/v1/api/projects/${j}/revisions/${O}/bundle`,N=new Request(`${this.baseUrl}${T}`,{method:"GET",headers:this.headers}),H=await this.fetcher(N);if(!H.ok)await this.throwUploadError(H,`${this.baseUrl}${T}`);return H.blob()}};resources={importSkill:async(j,O)=>se(await this.raw.POST("/v1/api/projects/{id}/resources/skill",{params:{path:{id:j}},body:O}),this.at("POST",`/v1/api/projects/${j}/resources/skill`)),importAgent:async(j,O)=>se(await this.raw.POST("/v1/api/projects/{id}/resources/agent",{params:{path:{id:j}},body:O}),this.at("POST",`/v1/api/projects/${j}/resources/agent`)),importMcp:async(j,O)=>se(await this.raw.POST("/v1/api/projects/{id}/resources/mcp",{params:{path:{id:j}},body:O}),this.at("POST",`/v1/api/projects/${j}/resources/mcp`))};async throwUploadError(j,O){let T=null;try{T=await j.json()}catch{T=await j.text().catch(()=>null)}throw Nt(j,T,{method:"PUT",url:O})}tasks={list:async(j)=>se(await this.raw.GET("/v1/api/tasks",{params:{query:j??{}}}),this.at("GET","/v1/api/tasks")),get:async(j)=>se(await this.raw.GET("/v1/api/tasks/{id}",{params:{path:{id:j}}}),this.at("GET",`/v1/api/tasks/${j}`)),create:async(j)=>se(await this.raw.POST("/v1/api/tasks",{body:j}),this.at("POST","/v1/api/tasks")),update:async(j,O)=>se(await this.raw.PATCH("/v1/api/tasks/{id}",{params:{path:{id:j}},body:O}),this.at("PATCH",`/v1/api/tasks/${j}`)),listComments:async(j)=>se(await this.raw.GET("/v1/api/tasks/{id}/comments",{params:{path:{id:j}}}),this.at("GET",`/v1/api/tasks/${j}/comments`)),addComment:async(j,O)=>se(await this.raw.POST("/v1/api/tasks/{id}/comments",{params:{path:{id:j}},body:O}),this.at("POST",`/v1/api/tasks/${j}/comments`)),review:async(j)=>se(await this.raw.GET("/v1/api/tasks/{id}/review",{params:{path:{id:j}}}),this.at("GET",`/v1/api/tasks/${j}/review`)),stream:(j,O)=>this.stream(`/v1/api/tasks/${j}/stream`,O)};modelConfig={setProjectHarness:async(j,O)=>se(await this.raw.PUT("/v1/api/model-config/harness/{projectId}",{params:{path:{projectId:j}},body:{harness:O}}),this.at("PUT",`/v1/api/model-config/harness/${j}`)),clearProjectHarness:async(j)=>se(await this.raw.DELETE("/v1/api/model-config/harness/{projectId}",{params:{path:{projectId:j}}}),this.at("DELETE",`/v1/api/model-config/harness/${j}`)),setHarness:async(j)=>se(await this.raw.PUT("/v1/api/model-config/harness",{body:{harness:j}}),this.at("PUT","/v1/api/model-config/harness")),clearHarness:async()=>se(await this.raw.DELETE("/v1/api/model-config/harness"),this.at("DELETE","/v1/api/model-config/harness")),resolvedHarness:async()=>se(await this.raw.GET("/v1/api/model-config/harness/resolved"),this.at("GET","/v1/api/model-config/harness/resolved")),resolvedProjectHarness:async(j)=>se(await this.raw.GET("/v1/api/model-config/harness/{projectId}/resolved",{params:{path:{projectId:j}}}),this.at("GET",`/v1/api/model-config/harness/${j}/resolved`))};ai={models:async(j,O)=>se(await this.raw.GET("/v1/api/ai/w/{workspaceId}/models",{params:{path:{workspaceId:j}},...O?.signal?{signal:O.signal}:{}}),this.at("GET",`/v1/api/ai/w/${j}/models`))};cycles={list:async(j)=>se(await this.raw.GET("/v1/api/cycles",{params:{query:j??{}}}),this.at("GET","/v1/api/cycles")),get:async(j)=>se(await this.raw.GET("/v1/api/cycles/{id}",{params:{path:{id:j}}}),this.at("GET",`/v1/api/cycles/${j}`)),propose:async(j)=>se(await this.raw.POST("/v1/api/cycles",{body:j}),this.at("POST","/v1/api/cycles")),stream:(j,O)=>this.stream(`/v1/api/cycles/${j}/stream`,O)};chat={send:async(j)=>se(await this.raw.POST("/v1/api/chat/turns",{body:j}),this.at("POST","/v1/api/chat/turns")),turn:async(j,O)=>se(await this.raw.GET("/v1/api/chat/turns/{turnId}",{params:{path:{turnId:j},query:O}}),this.at("GET",`/v1/api/chat/turns/${j}`))};pendingRequests={list:async(j)=>se(await this.raw.GET("/v1/api/pending-requests",{params:{query:j??{}}}),this.at("GET","/v1/api/pending-requests")),resolve:async(j,O)=>se(await this.raw.POST("/v1/api/pending-requests/{id}/resolve",{params:{path:{id:j}},body:O}),this.at("POST",`/v1/api/pending-requests/${j}/resolve`))};clientInvoices={list:async(j)=>se(await this.raw.GET("/v1/api/client-billing/invoices",{params:{query:j??{}}}),this.at("GET","/v1/api/client-billing/invoices")),get:async(j)=>se(await this.raw.GET("/v1/api/client-billing/invoices/{id}",{params:{path:{id:j}}}),this.at("GET",`/v1/api/client-billing/invoices/${j}`)),createDraft:async(j)=>se(await this.raw.POST("/v1/api/client-billing/invoices",{body:j}),this.at("POST","/v1/api/client-billing/invoices")),issue:async(j)=>se(await this.raw.POST("/v1/api/client-billing/invoices/{id}/issue",{params:{path:{id:j}},body:{}}),this.at("POST",`/v1/api/client-billing/invoices/${j}/issue`)),void:async(j,O)=>se(await this.raw.POST("/v1/api/client-billing/invoices/{id}/void",{params:{path:{id:j}},body:{reason:O}}),this.at("POST",`/v1/api/client-billing/invoices/${j}/void`)),pay:async(j)=>se(await this.raw.POST("/v1/api/client-billing/invoices/{id}/pay",{params:{path:{id:j}},body:{}}),this.at("POST",`/v1/api/client-billing/invoices/${j}/pay`)),paymentLink:async(j,O={})=>se(await this.raw.POST("/v1/api/client-billing/invoices/{id}/payment-link",{params:{path:{id:j}},body:O}),this.at("POST",`/v1/api/client-billing/invoices/${j}/payment-link`))};async*observeAgent(j,O,T){let N=`/v1/api/projects/${j}/agents/${O}/observe`;for await(let H of this.stream(N,T)){let F=Fr(H.data);if(!F)continue;if(yield F,Hr(F))return}}async*watchRevisions(j,O){let T=`/v1/api/projects/${j}/revisions/watch`,N=O?.signal,H=Wn.firstDelayMs;while(!N?.aborted){try{for await(let F of this.stream(T,O)){let M=Lr(F.data);if(!M)continue;if(M.kind==="ready")H=Wn.firstDelayMs;yield M}}catch(F){if(N?.aborted)return;if(Oo(F))throw F}await Ft(H,N),H=Math.min(H*2,Wn.maxDelayMs)}}async*stream(j,O){let T=`${this.baseUrl}${j}`,N=new Request(T,{headers:{...this.headers,accept:"text/event-stream"},signal:O?.signal}),H=await globalThis.fetch(N);if(!H.ok||!H.body){let F=null;try{F=await H.json()}catch{F=null}throw Nt(H,F,{method:"GET",url:T})}yield*Mr(H.body,O?.signal)}}function Ur(j){if(j instanceof e)return{code:j.code,status:null};if(j instanceof Tt)return{code:"invalid_request",status:400};if(j instanceof sn)return{code:"bad_request",status:400};if(j instanceof on)return{code:"unauthenticated",status:401};if(j instanceof an)return{code:"forbidden",status:403};if(j instanceof Ve)return{code:"not_found",status:404};if(j instanceof vt)return{code:"conflict",status:409};if(j instanceof cn)return{code:"rate_limited",status:429};if(j instanceof ln)return{code:"not_implemented",status:501};if(j instanceof lt)return{code:"server_error",status:j.status};if(j instanceof Ye)return{code:"unreachable",status:null};return{code:"unknown",status:null}}var Jn=(j)=>{if(j instanceof Tt&&j.issues.length>0){let O=j.issues.slice(0,5).map((N)=>{let H=N;return` - ${Array.isArray(H.path)&&H.path.length>0?`${H.path.join(".")}: `:""}${typeof H.message==="string"?H.message:JSON.stringify(N)}`}),T=j.issues.length-O.length;return`${j.message}
18
+ ${O.join(`
19
+ `)}${T>0?`
20
+ … ${T} more`:""}`}return j instanceof Error?j.message:String(j)};function n(j,O){let T=r({env:j,flags:O.flags,cwd:O.cwd});if(T.conflict)throw new e("workspace_mismatch",T.conflict);if(!T.credential)throw new e("unauthenticated","No credential. Run `hlix auth login`, or set HLIX_API_KEY for CI.");return new Ht({baseUrl:T.baseUrl,credential:T.credential.sessionToken?Ar(T.credential.sessionToken):Ot(T.credential.apiKey),...T.workspaceId?{organizationId:T.workspaceId}:{}})}function To(j){let O=Math.max(...j.map((N)=>N.name.length));return`hlix — the hlix control-plane CLI
21
+
22
+ Usage:
23
+ hlix <command> [options]
24
+
25
+ Commands:
26
+ ${[` hlix ${"".padEnd(O)} Open Hlix Code (interactive)`,...j.map((N)=>` hlix ${N.name.padEnd(O)} ${N.summary}`)].join(`
27
+ `)}
28
+
29
+ Options:
30
+ --json Machine-readable output (a versioned, stable contract)
31
+ --cwd <dir> Operate on another directory instead of the current one
32
+ --workspace <id> Workspace to act in, overriding the folder's binding
33
+ --base-url <url> API to talk to, overriding the folder's binding
34
+ --help Show this help
35
+ --version Show the installed CLI version
36
+
37
+ Hlix Code (hlix with no command):
38
+ --sandbox <choice> cloud, docker or local; --local is short for local
39
+ --docker-image <r> image the docker sandbox runs in
40
+ --harness <name> which coder does the work
41
+ --project <id> project to act in, when this folder is not bound
42
+ -p "<prompt>" one turn, print the answer, exit
43
+ --json with -p: one JSON object per event instead of prose
44
+ --allow-writes with -p: let the turn change files and run commands
45
+ --yolo approve every tool call for the whole session
46
+
47
+ A command targets the workspace named by, in order: an explicit flag, the
48
+ HLIX_* environment, the nearest .hlix/config.json, then the stored credential.
49
+ Run \`hlix status\` to see which one applied.
50
+ `}function Fo(j,O){let T=[...Array(O.length+1).keys()];for(let N=1;N<=j.length;N+=1){let H=[N];for(let F=1;F<=O.length;F+=1)H[F]=Math.min(T[F]+1,H[F-1]+1,T[F-1]+(j[N-1]===O[F-1]?0:1));T=H}return T[O.length]}function tc(j,O,T){let N=/Unknown option '--([^'=]+)/.exec(T)?.[1];if(!N)return T;let H=O.findIndex((L)=>L.startsWith("-")),F=H===-1?O:O.slice(0,H),M=new Set(["json","help","version","cwd","workspace","base-url",...qn(j,F)?.command.options??[]]),U=null;for(let L of M){let D=Fo(N,L);if(D<=2&&(!U||D<U.distance))U={name:L,distance:D}}return U?`${T}
51
+ Did you mean --${U.name}?`:T}function No(j,O){let T=new Set;for(let F of j)T.add(F.name),T.add(F.name.split(" ")[0]);let N=null;for(let F of T){let M=Fo(O,F);if(M<=2&&(!N||M<N.distance))N={name:F,distance:M}}if(!N)return null;if(j.some((F)=>F.name===N.name))return N.name;let H=j.filter((F)=>F.name.startsWith(`${N.name} `)).sort((F,M)=>F.name.length-M.name.length)[0];return H?H.name:N.name}function qn(j,O){for(let T of[...j].sort((N,H)=>H.name.length-N.name.length)){let N=T.name.split(" ");if(N.every((H,F)=>O[F]===H))return{command:T,rest:O.slice(N.length)}}return null}function nc(j,O,T){let N=tc(j,O,T);if(!/^Unknown option '/.test(T))return N;let H=N.replace(/\. To specify a positional argument[\s\S]*?after '--'[^\n]*/,"."),F=qn(j,O.filter((M)=>!M.startsWith("-")));return F?`${H}
52
+
53
+ ${F.command.usage}`:H}async function a(j,O,T){if(O.some((G)=>G==="--api-key"||G.startsWith("--api-key=")))return T.stderr("error: API keys are never accepted as command-line arguments. Run `hlix auth login` and use the hidden prompt.\n"),2;let N;try{N=ec({args:O,allowPositionals:!0,strict:!0,options:{json:{type:"boolean"},help:{type:"boolean"},version:{type:"boolean"},cwd:{type:"string"},"base-url":{type:"string"},workspace:{type:"string"},"dry-run":{type:"boolean"},"no-connect-origin":{type:"boolean"},attach:{type:"boolean"},print:{type:"boolean"},web:{type:"boolean"},"env-file":{type:"string"},include:{type:"string"},history:{type:"string"},name:{type:"string"},stack:{type:"string"},status:{type:"string"},project:{type:"string"},yes:{type:"boolean"},global:{type:"boolean"},org:{type:"boolean"},title:{type:"string"},description:{type:"string"},force:{type:"boolean"},runtime:{type:"string"},duty:{type:"string"},profile:{type:"string"},server:{type:"string"},"allow-stdio":{type:"boolean"},source:{type:"string"},format:{type:"string"},out:{type:"string"},"from-stdin":{type:"boolean"},once:{type:"boolean"}}})}catch(G){let oe=O.includes("--json"),ue=nc(j,O,Jn(G));if(T.onFailure?.({code:"invalid_usage",message:ue,status:null}),oe)T.stdout(ne(en("cli",{code:"invalid_usage",message:ue,status:null})));else T.stderr(`${ue}
54
+ `);return 2}let H=N.values.json===!0,F=N.positionals;if(N.values.version===!0){let{version:G}=await import("./package-844qvsxr.js");return T.stdout(`${G}
55
+ `),0}if(F.length===0||N.values.help===!0){let G=qn(j,F);return T.stdout(G?`${G.command.usage}
56
+ `:To(j)),F.length===0&&N.values.help!==!0?1:0}let M=qn(j,F);if(!M){let G=F.join(" "),oe=No(j,G)??No(j,F[0]),ue=oe?`Unknown command: ${G}
57
+ Did you mean \`hlix ${oe}\`?`:`Unknown command: ${G}`;if(T.onFailure?.({code:"unknown_command",message:ue,status:null}),H)T.stdout(ne(en(G,{code:"unknown_command",message:ue,status:null})));else T.stderr(`${ue}
58
+
59
+ ${To(j)}`);return 2}let U=new Set(["json","help","version","cwd","workspace","base-url"]),L=new Set(M.command.options??[]),D=Object.entries(N.values).filter(([G,oe])=>oe!==void 0&&!U.has(G)&&!L.has(G)).map(([G])=>`--${G}`),B=M.command.args??{min:0,max:0},z=M.rest.length<B.min?{code:"missing_argument",message:M.command.usage.split(`
60
+ `)[0]}:M.rest.length>B.max?{code:"invalid_usage",message:M.command.usage.split(`
61
+ `)[0]}:null,J=typeof N.values.cwd==="string"?N.values.cwd:void 0,K=Qa(J??"."),X=J!==void 0&&!$o(K)?{code:"invalid_usage",message:`--cwd is not a directory: ${K}`}:null,W=D.length>0?{code:"invalid_usage",message:`Unsupported option for ${M.command.name}: ${D.join(", ")}`}:X??z;if(W){if(T.onFailure?.({...W,status:null}),H)T.stdout(ne(en(M.command.name,{...W,status:null})));else{let G=M.command.usage.startsWith(W.message)?M.command.usage:`${W.message}
62
+
63
+ ${M.command.usage}`;T.stderr(`error: ${G}
64
+ `)}return 2}let V=N.values,Q={...T,args:M.rest,json:H,flags:V,cwd:K,requireClient:(G)=>n(T.env,{cwd:G??K,flags:V})};try{return await M.command.run(Q)}catch(G){let{code:oe,status:ue}=Ur(G);if(T.onFailure?.({code:oe,message:Jn(G),status:ue,...G instanceof e&&G.details!==void 0?{details:G.details}:{}}),H)T.stdout(ne(en(M.command.name,{code:oe,message:Jn(G),status:ue})));else if(T.stderr(`error: ${Jn(G)}
65
+ `),process.env.HLIX_DEBUG&&G instanceof Error&&G.stack)T.stderr(`${G.stack}
66
+ `);return oe==="unauthenticated"||oe==="forbidden"?3:1}}import{readFileSync as rc}from"node:fs";import{homedir as sc}from"node:os";import{join as oc}from"node:path";var Ho=20000;function p(j){if(j===void 0)return;let O=typeof j==="number"?j:Number(j.trim());return Number.isInteger(O)&&O>=Ho?O:void 0}var l=["cloud","docker","local"],ic={"claude-code":!0,codex:!0,"cursor-agent":!0,hlix:!0},o=Object.keys(ic),m="hlix",Mo={dockerImage:"docker sandbox only",harness:"local and docker sandboxes only",memoryTokens:"all sandboxes",model:"local and docker sandboxes only",sandbox:"all sandboxes",yolo:"all sandboxes"},Mt=["dockerImage","harness","memoryTokens","model","sandbox","yolo"],Dr=["projectId","workspaceId","apiUrl"];function Br(j=process.env){return oc(j.HLIX_CONFIG_HOME??sc(),".hlix","config.json")}function Lo(j=process.env){try{let O=JSON.parse(rc(Br(j),"utf8"));return O.schemaVersion===1?O:null}catch{return null}}function g(j,O=process.env){let T=Lo(O),N=t(j),H=N?.root??null,F=N?.config??null,M={},U={},L=(D)=>{let B=F?.[D],z=T?.[D];if(B!==void 0)M[D]=B,U[D]="project";else if(z!==void 0)M[D]=z,U[D]="global"};for(let D of Mt)L(D);for(let D of Dr){let B=F?.[D];if(B!==void 0)M[D]=B,U[D]="project"}return{merged:M,sources:U,global:T,project:F,paths:{global:Br(O),project:H?rn(H):null}}}function Uo(j){return[...Mt,...Dr].map((T)=>({key:T,value:j.merged[T]??null,source:j.sources[T]??"default"}))}function ac(j,O){if(j==="sandbox"&&!l.includes(O))return`sandbox must be one of ${l.join(", ")}; got "${O}".`;if(j==="harness"&&!o.includes(O))return`harness must be one of ${o.join(", ")}; got "${O}".`;if(j==="model"&&O.trim()==="")return"model must not be empty.";if(j==="memoryTokens"&&p(O)===void 0)return`memoryTokens must be a whole number of tokens, at least ${Ho}; got "${O}".`;if(j==="dockerImage"&&O.trim()==="")return"dockerImage must not be empty.";if(j==="yolo"&&S(O)===void 0)return`yolo must be true or false; got "${O}".`;return null}function S(j){if(j===void 0)return;let O=j.trim().toLowerCase();if(["true","1","yes","on"].includes(O))return!0;if(["false","0","no","off"].includes(O))return!1;return}function zr(j){if(Mt.includes(j))return j;let O=Dr.includes(j);throw new e("invalid_usage",O?`${j} is written by \`hlix init\` and \`hlix import\`, not by \`hlix config set\`.`:`Unknown setting: ${j}. Known settings: ${Mt.join(", ")}.`)}function Do(j,O){let T=ac(j,O);if(T)throw new e("invalid_usage",T);return O}function h(j){if(j.scope==="global"){let N=Br(j.env),H=Lo(j.env)??{schemaVersion:1};return Ke(N,{...H,[j.key]:j.value}),N}let O=t(j.cwd);if(!O)throw new e("not_initialized","This folder is not bound to hlix. Run `hlix init` here, or set it machine-wide with --global.");let T=rn(O.root);return Ke(T,{...O.config,[j.key]:j.value}),T}import{createHash as cc}from"node:crypto";import{mkdirSync as lc,readdirSync as Go,readFileSync as dc,rmSync as pc,statSync as Ko,writeFileSync as uc}from"node:fs";import{homedir as mc,tmpdir as fc}from"node:os";import{basename as Vo,isAbsolute as gc,join as me,relative as hc}from"node:path";var i=(j=process.env)=>j.HOME??j.USERPROFILE??mc();function Ae(j){try{if(!Ko(j).isFile())return null;return dc(j,"utf8")}catch{return null}}function yc(j){try{return Ko(j).isDirectory()}catch{return!1}}function Lt(j,O){try{return Go(j,{withFileTypes:!0}).filter((T)=>T.isFile()&&T.name.endsWith(O)).map((T)=>me(j,T.name)).sort()}catch{return[]}}function wc(j){try{return Go(j,{withFileTypes:!0}).filter((O)=>O.isDirectory()||O.isSymbolicLink()).map((O)=>me(j,O.name)).sort()}catch{return[]}}function Jr(j){let O=j.replace(/^\uFEFF/,""),T=O.indexOf(`
67
+ `);if(!O.startsWith("---")||T===-1)return{fields:{},body:O.trim()};let N=O.indexOf(`
68
+ ---`,T);if(N===-1)return{fields:{},body:O.trim()};let H={};for(let M of O.slice(T+1,N).split(`
69
+ `)){let U=/^([A-Za-z_][\w-]*)\s*:\s*(.*)$/.exec(M);if(!U)continue;H[U[1]]=U[2].trim().replace(/^["']|["']$/g,"")}let F=O.indexOf(`
70
+ `,N+1);return{fields:H,body:F===-1?"":O.slice(F+1).trim()}}function vc(j){let O=j.trimStart(),T=/^"((?:[^"\\]|\\.)*)"/.exec(O)??/^'([^']*)'/.exec(O);if(T)return T[1].replace(/\\"/g,'"').replace(/\\n/g,`
71
+ `);if(O.startsWith("["))return[...O.matchAll(/"((?:[^"\\]|\\.)*)"|'([^']*)'/g)].map((H)=>H[1]??H[2]??"");if(O.startsWith("{")){let H={};for(let F of O.matchAll(/([A-Za-z0-9_.-]+)\s*=\s*"((?:[^"\\]|\\.)*)"/g))H[F[1]]=F[2].replace(/\\"/g,'"');return H}let N=/^[^\s#]+/.exec(O)?.[0];if(N===void 0)return;if(N==="true"||N==="false")return N==="true";if(/^-?\d+(\.\d+)?$/.test(N))return Number(N);return N}function Yo(j){let O={"":{}},T="",N=j.split(`
72
+ `);for(let H=0;H<N.length;H+=1){let M=N[H].trim();if(!M||M.startsWith("#"))continue;let U=/^\[\[?([^\]]+)\]\]?$/.exec(M);if(U){T=U[1].trim(),O[T]??={};continue}let L=/^([A-Za-z0-9_.-]+|"[^"]+")\s*=\s*(.*)$/.exec(M);if(!L)continue;let D=L[1].replace(/^"|"$/g,""),B=L[2];if(B.startsWith('"""')){let J=[],K=B.slice(3);if(K.includes('"""'))J.push(K.slice(0,K.indexOf('"""')));else{if(K)J.push(K);while(H+1<N.length){H+=1;let X=N[H],W=X.indexOf('"""');if(W===-1){J.push(X);continue}J.push(X.slice(0,W));break}}O[T][D]=J.join(`
73
+ `).replace(/^\n/,"");continue}let z=vc(B);if(z!==void 0)O[T][D]=z}return O}function Wr(j,O){return j.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g,(T,N,H)=>{let F=O[N];return F!==void 0&&F!==""?F:H??""})}var Bo=(j,O)=>{let T={};for(let[N,H]of Object.entries(j))if(typeof H==="string")T[N]=Wr(H,O);return T},bc=[{relative:"GEMINI.md",source:"gemini"},{relative:me(".gemini","GEMINI.md"),source:"gemini"},{relative:".cursorrules",source:"cursor"},{relative:".windsurfrules",source:"windsurf"},{relative:me(".github","copilot-instructions.md"),source:"copilot"}],kc=[{relative:me(".gemini","GEMINI.md"),source:"gemini"}],Sc=[{relative:me(".cursor","rules"),source:"cursor",extension:".mdc"},{relative:me(".windsurf","rules"),source:"windsurf",extension:".md"}];function jc(j,O){let T=me(j,".clinerules"),N=yc(T)?Lt(T,".md"):[T],H=[];for(let F of N){let M=Ae(F)?.trim();if(M)H.push({path:F,source:"cline",scope:O,content:M})}return H}function Pc(j,O,T){let{fields:N,body:H}=Jr(O);if(N.alwaysApply==="false")return{path:j,source:"cursor",scope:T,reason:"alwaysApply: false"};if(!H)return{path:j,source:"cursor",scope:T,reason:"no rule body"};let F=N.globs?.replace(/^\[|\]$/g,"").trim();return{path:j,source:"cursor",scope:T,content:H,...F?{note:`Applies to: ${F}`}:{}}}var Ec=["AGENTS.md","CLAUDE.md"],Xo=["",".claude"],E=["commands"];function $c(j,O){let T=[],N=new Set;for(let H of[...Xo,O])for(let F of Ec){let M=me(j,H,F),U=Ae(M)?.trim();if(!U||N.has(U))continue;N.add(U),T.push({path:M,content:U})}return T}function zo(j,O){return $c(j,O).map((T)=>T.content)}var f=["AGENTS.md","CLAUDE.md","GEMINI.md"];function qr(j,O){for(let T of f)for(let N of[...Xo,O]){let H=me(j,N,T),F=Ae(H)?.trim();if(F)return{path:H,content:F}}return null}var Gr=(j=process.env)=>me(j.HLIX_CONFIG_HOME??me(i(j),".hlix"),"AGENTS.md");function y(j){let O=j.env??process.env,T=Gr(O),N=Ae(T)?.trim();return{global:N?{path:T,content:N}:null,project:qr(j.cwd,j.configDir)}}var Wo=(j)=>{let O=Math.round(j.length/4);return O>=1000?`${(O/1000).toFixed(1)}k tokens`:`${O} tokens`};function C(j,O,T=process.env){let N=[...j.global?[Qo(j.global.path,T)]:[],...j.project?[un(j.project.path,O)]:[]];return N.length===0?"":`rules: ${N.join(" + ")}`}function w(j,O,T=process.env,N=[]){let H=(F,M,U)=>M?`${F.padEnd(8)} ${U(M.path)} (${Wo(M.content)})`:`${F.padEnd(8)} none`;return[H("user",j.global,(F)=>Qo(F,T)),H("project",j.project,(F)=>un(F,O)),...N.map((F)=>`${"nested".padEnd(8)} ${un(F.path,O)} (${Wo(F.content)})`),"","User rules go first, the project's after, so the project wins a conflict.",N.length===0?"A subdirectory's own rules file is added when the agent first works in it.":"A nested file was added when the agent first touched a path under it.","Edit them with `hlix rules --edit` (this project) or `hlix rules --edit --global`."].join(`
74
+ `)}var Jo=[{dir:".claude",source:"claude",harnessReads:!0},{dir:".agents",source:"agents",harnessReads:!0},{dir:".hlix",source:"hlix",harnessReads:!0},{dir:".codex",source:"codex",harnessReads:!1}],xc=[{relative:me(".cursor","commands"),source:"cursor"},{relative:me(".codex","prompts"),source:"codex"}],Cc=[{relative:me(".cursor","mcp.json"),source:"cursor",key:"mcpServers",format:"json"},{relative:me(".windsurf","mcp.json"),source:"windsurf",key:"mcpServers",format:"json"},{relative:me(".gemini","settings.json"),source:"gemini",key:"mcpServers",format:"json"},{relative:me(".vscode","mcp.json"),source:"vscode",key:"servers",format:"json"},{relative:me(".codex","config.toml"),source:"codex",key:"mcp_servers",format:"toml"},{relative:".mcp.json",source:"claude",key:"mcpServers",format:"json"}];function Zo(j){return[...Cc,{relative:me(j,"mcp.json"),source:"hlix",key:"mcpServers",format:"json"}]}var Ic="found, not loaded (machine-wide; enable per project by copying into .hlix/mcp.json)",_c=(j)=>Zo(j).filter((O)=>O.source!=="vscode");function Rc(j,O){if(!j||typeof j!=="object"||Array.isArray(j))return{reason:"not an object"};let T=j;if(T.enabled===!1||T.disabled===!0)return{reason:"disabled"};let N=typeof T.command==="string"&&T.command!=="",H=typeof T.url==="string"&&T.url!=="";if(N&&H)return{reason:'has both "command" and "url"'};if(N){let z=Array.isArray(T.args)?T.args.filter((K)=>typeof K==="string"):void 0,J=T.env&&typeof T.env==="object"&&!Array.isArray(T.env)?Bo(T.env,O):void 0;return{config:{command:T.command,...z&&z.length>0?{args:z}:{},...J&&Object.keys(J).length>0?{env:J}:{}}}}if(!H)return{reason:'missing "command" or "url"'};let F=T.headers??T.http_headers,M=F&&typeof F==="object"&&!Array.isArray(F)?Bo(F,O):{},U=T.bearer_token_env_var;if(typeof U==="string"&&/^[A-Za-z_][A-Za-z0-9_]*$/.test(U)&&!Object.keys(M).some((z)=>z.toLowerCase()==="authorization"))M.Authorization=`Bearer ${Wr(`\${${U}}`,O)}`;let L=Object.entries(M).find(([z])=>z.toLowerCase()==="authorization")?.[1]?.trim(),D=L&&!/^Bearer$/i.test(L)&&!L.includes("${"),B=T.oauth===!0||T.oauth&&typeof T.oauth==="object"||typeof U==="string"&&!O[U];return{config:{url:Wr(T.url,O),...B&&!D?{needsSignIn:!0}:{},...Object.keys(M).length>0?{headers:M}:{}}}}function qo(j,O,T,N){let H=Ae(j),F=[],M=[];if(H===null)return{servers:F,skipped:M};let U=[];if(O.format==="toml"){let L=Yo(H);U=Object.entries(L).filter(([D])=>D.startsWith(`${O.key}.`)).map(([D,B])=>[D.slice(O.key.length+1),B])}else try{let D=JSON.parse(H)?.[O.key];if(D&&typeof D==="object"&&!Array.isArray(D))U=Object.entries(D)}catch{return M.push({path:j,source:O.source,scope:T,reason:"not valid JSON"}),{servers:F,skipped:M}}for(let[L,D]of U){let B=Rc(D,N);if("reason"in B){M.push({path:j,source:O.source,scope:T,reason:`${L}: ${B.reason}`});continue}F.push({path:j,source:O.source,scope:T,name:L,config:B.config})}return{servers:F,skipped:M}}function Ac(j,O,T){let{fields:N,body:H}=Jr(O);if(!H)return{path:j,source:"claude",scope:T,reason:"no instructions"};let F=N.tools?.replace(/^\[|\]$/g,"").split(",").map((M)=>M.trim()).filter(Boolean);return{path:j,source:"claude",scope:T,name:N.name||Vo(j,".md"),description:N.description??"",instructions:H,...F&&F.length>0&&F[0]!=="*"?{tools:F}:{},...N.model?{model:N.model}:{}}}function Oc(j){let O=Yo(j)[""]??{},T=typeof O.prompt==="string"?O.prompt.trim():"";if(!T)return null;return{description:typeof O.description==="string"?O.description:"",body:T}}function b(j,O,T={}){let N=T.configDir??".hlix",H=T.env??process.env,F={instructions:[],skills:[],commands:[],generatedCommands:[],mcpServers:[],subagents:[],skipped:[]},M=(X)=>{if("reason"in X)F.skipped.push(X);else F.instructions.push(X)};for(let X of bc){let W=me(j,X.relative),V=Ae(W)?.trim();if(V)F.instructions.push({path:W,source:X.source,scope:"project",content:V})}for(let X of Sc)for(let W of Lt(me(j,X.relative),X.extension)){let V=Ae(W);if(V===null)continue;if(X.source==="cursor"){M(Pc(W,V,"project"));continue}let{body:Q}=Jr(V);if(Q)F.instructions.push({path:W,source:X.source,scope:"project",content:Q})}for(let X of jc(j,"project"))M(X);let U=zo(j,N),L=me(j,".codex","AGENTS.md"),D=Ae(L)?.trim();if(D&&U.includes(D))F.skipped.push({path:L,source:"codex",scope:"project",reason:"same content as the project's AGENTS.md"});else if(D)F.instructions.push({path:L,source:"codex",scope:"project",content:D});for(let X of kc){let W=me(O,X.relative),V=Ae(W)?.trim();if(V)F.instructions.push({path:W,source:X.source,scope:"global",content:V})}let B=me(O,".codex","AGENTS.md"),z=Ae(B)?.trim(),J=zo(O,N);if(z&&J.includes(z))F.skipped.push({path:B,source:"codex",scope:"global",reason:"same content as the machine's AGENTS.md"});else if(z)F.instructions.push({path:B,source:"codex",scope:"global",content:z});for(let[X,W]of[[j,"project"],[O,"global"]])for(let V of Jo){let Q=me(X,V.dir===".hlix"?N:V.dir,"skills");if(!wc(Q).some((oe)=>Ae(me(oe,"SKILL.md"))!==null))continue;F.skills.push({path:Q,source:V.source,scope:W,harnessReads:V.harnessReads})}for(let[X,W]of[[j,"project"],[O,"global"]]){for(let V of Jo){if(!V.harnessReads)continue;let Q=me(X,V.dir,"commands");if(Lt(Q,".md").length===0)continue;F.commands.push({path:Q,source:V.source,scope:W,harnessReads:!0})}for(let V of xc){let Q=me(X,V.relative);if(Lt(Q,".md").length===0)continue;F.commands.push({path:Q,source:V.source,scope:W})}for(let V of Lt(me(X,".gemini","commands"),".toml")){let Q=Ae(V),G=Q===null?null:Oc(Q);if(!G){F.skipped.push({path:V,source:"gemini",scope:W,reason:"no prompt field"});continue}F.generatedCommands.push({path:V,source:"gemini",scope:W,name:Vo(V,".toml"),body:`---
75
+ description: ${G.description}
76
+ ---
77
+
78
+ ${G.body}
79
+ `})}}for(let X of Zo(N)){let W=qo(me(j,X.relative),X,"project",H);F.skipped.push(...W.skipped);for(let V of W.servers){let Q=F.mcpServers.findIndex((G)=>G.name===V.name);if(Q===-1)F.mcpServers.push(V);else F.mcpServers[Q]=V}}for(let X of _c(N)){let W=qo(me(O,X.relative),X,"global",H);for(let V of W.servers)F.skipped.push({path:V.path,source:V.source,scope:"global",reason:`${V.name}: ${Ic}`})}let K=[{dir:me(".claude","agents"),source:"claude"},{dir:me(N,"agents"),source:"hlix"}];for(let[X,W]of[[j,"project"],[O,"global"]])for(let V of K.flatMap((Q)=>Lt(me(X,Q.dir),".md"))){let Q=Ae(V);if(Q===null)continue;let G=Ac(V,Q,W);if("reason"in G)F.skipped.push(G);else if(F.subagents.some((oe)=>oe.name===G.name))F.skipped.push({path:V,source:"claude",scope:W,reason:`a project agent already claims the name ${G.name}`});else F.subagents.push(G)}return F}function I(j,O){if(j.length===0)return null;let T=me(fc(),"hlix-standards-commands",cc("sha256").update(O).digest("hex").slice(0,16));try{pc(T,{recursive:!0,force:!0}),lc(T,{recursive:!0});for(let N of j)uc(me(T,`${N.name}.md`),N.body,"utf8");return T}catch{return null}}var Tc=60000,un=(j,O)=>{let T=hc(O,j);return!T||T.startsWith("..")||gc(T)?j:T},Qo=(j,O=process.env)=>{let T=O.HLIX_CONFIG_HOME;if(T&&j.startsWith(`${T}/`))return`~/.hlix/${j.slice(T.length+1)}`;let N=i(O);return N&&j.startsWith(`${N}/`)?`~/${j.slice(N.length+1)}`:j};function _(j,O,T=Tc){if(j.length===0)return"";let N=["# Project standards from other agent tools","","These files were written for other coding agents working in this same","project. Treat them as the project's instructions and follow them."].join(`
80
+ `),H=[],F=N.length,M=!1;for(let L of j){let D=`# From ${un(L.path,O)} (${L.source})`,B=L.note?`${D}
81
+ ${L.note}`:D,z=T-F-B.length-4;if(z<=0){M=!0;break}let J=L.content.length<=z?L.content:`${L.content.slice(0,z)}
82
+ [truncated]`;if(J.length<L.content.length)M=!0;H.push(`${B}
83
+
84
+ ${J}`),F+=B.length+J.length+4}let U=M?`
85
+
86
+ [The standards block reached its ${T}-character cap; some rules above are cut short or omitted.]`:"";return`${N}
87
+
88
+ ${H.join(`
89
+
90
+ `)}${U}`}var pn=(j,O,T)=>`${j} ${j===1?O:T}`;function P(j){let O=[];if(j.instructions.length>0)O.push(pn(j.instructions.length,"instruction file","instruction files"));if(j.skills.length>0)O.push(pn(j.skills.length,"skill directory","skill directories"));let T=j.commands.length+j.generatedCommands.length;if(T>0)O.push(pn(T,"command source","command sources"));if(j.mcpServers.length>0)O.push(pn(j.mcpServers.length,"mcp server","mcp servers"));if(j.subagents.length>0)O.push(pn(j.subagents.length,"subagent","subagents"));if(O.length===0)return"";let N=[...new Set([...j.instructions,...j.skills,...j.commands,...j.generatedCommands,...j.mcpServers,...j.subagents].map((H)=>H.source))].sort();return`standards: ${O.join(" · ")} (${N.join(", ")})`}function ei(j,O){let T=[],N=(F,M)=>{if(M.length===0)return;T.push(F,...M.map((U)=>` ${U}`),"")},H=(F)=>`${F.source}${F.scope==="global"?" (global)":""} ${un(F.path,O)}`;if(N("Instructions",j.instructions.map((F)=>`${H(F)}${F.note?` — ${F.note}`:""}`)),N("Skills",j.skills.map((F)=>`${H(F)}${F.harnessReads?" — already read by the harness":""}`)),N("Commands",[...j.commands.map((F)=>`${H(F)}${F.harnessReads?" — already read by the harness":""}`),...j.generatedCommands.map((F)=>`${H(F)} → /${F.name}`)]),N("MCP servers",j.mcpServers.map((F)=>`${H(F)} → ${F.name} (${"command"in F.config?"stdio":"http"})`)),N("Subagents",j.subagents.map((F)=>`${H(F)} → ${F.name}`)),N("Skipped",j.skipped.map((F)=>`${H(F)} — ${F.reason}`)),T.length===0)return`No standards from other agent tools were found in this folder.
91
+ `;return`${T.join(`
92
+ `).trimEnd()}
93
+ `}import{accessSync as Nc,constants as Fc,mkdirSync as Hc,readFileSync as Mc,realpathSync as Lc,statSync as ni,writeFileSync as Uc}from"node:fs";import{homedir as Dc}from"node:os";import{basename as Bc,dirname as ti,join as Ut}from"node:path";var zc={homebrew:"Homebrew",npm:"npm",installer:"installer",unknown:"unknown origin"},ri=(j)=>j.HOME||Dc();function Vr(j){return Ut(j.XDG_DATA_HOME||Ut(ri(j),".local","share"),"hlix","hlix")}function si(j){try{return Lc(j)}catch{return null}}function Wc(j){try{let O=JSON.parse(Mc(Ut(Vr(j),"install.json"),"utf8"));if(typeof O.path==="string")return O.path}catch{}return Ut(ri(j),".local","bin","hlix")}function Jc(j,O){if(/\/Cellar\/hlix\//.test(j))return"homebrew";if(/\/node_modules\/@hlix\/cli\//.test(j))return"npm";if(si(Wc(O))===j)return"installer";return"unknown"}function Kr(j,O){let T=si(j);if(!T)return null;try{if(!ni(T).isFile())return null;Nc(T,Fc.X_OK)}catch{return null}return{path:j,realPath:T,channel:Jc(T,O)}}function qc(j){let O=[];for(let T of(j.PATH??"").split(":")){if(!T)continue;let N=Kr(Ut(T,"hlix"),j);if(N&&!O.some((H)=>H.realPath===N.realPath))O.push(N)}return O}function Yr(j,O=process.execPath){if(j.HLIX_SELF)return Kr(j.HLIX_SELF,j);if(/^(node|bun)(\.exe)?$/.test(Bc(O)))return null;return Kr(O,j)}function Xr(j){switch(j.channel){case"homebrew":return"brew uninstall hlix";case"npm":return"npm uninstall -g @hlix/cli";case"installer":return`${j.path} uninstall`;case"unknown":return`rm ${j.path}`}}var Gn=(j)=>`${j.path} (${zc[j.channel]})`;function Zr(j,O=process.execPath){let T=Yr(j,O),N=qc(j);if(T&&!N.some((U)=>U.realPath===T.realPath))N.push(T);if(N.length<2)return{running:T,copies:N,duplicate:null};let[H,...F]=N,M=`${N.length} copies of hlix are installed: ${Gn(H)} runs, ${F.map(Gn).join(" and ")} ${F.length===1?"does":"do"} not. Keep one: ${F.map(Xr).join(" && ")}`;return{running:T,copies:N,duplicate:M}}var Gc=86400000;function A(j,O=Date.now(),T=process.execPath){let{duplicate:N}=Zr(j,T);if(!N)return null;let H=Ut(ti(ze(j)),"duplicate-notice");try{if(O-ni(H).mtimeMs<Gc)return null}catch{}try{Hc(ti(H),{recursive:!0}),Uc(H,`${N}
94
+ `)}catch{}return N}async function Kc(j,O,T){let N=O.map((U)=>U.id);if(T){if(!N.includes(T))throw new e("workspace_mismatch",O.length===0?`This key belongs to a user who is not a member of any workspace, including ${T}.`:`This key cannot act in workspace ${T}. Available: ${N.join(", ")}.`);return T}if(O.length===0)throw new e("workspace_required","This key belongs to a user who is not a member of any workspace. Create or join one first.");let H=O[0];if(H&&O.length===1)return j.stderr(`Using your only workspace: ${H.name} (${H.id})
95
+ `),H.id;if(j.json||!j.promptChoice)throw new e("missing_argument",`--workspace is required here: this key can act in ${O.length} workspaces. Pass one of: ${N.join(", ")}.`);let F=Math.max(...O.map((U)=>U.name.length));j.stderr(`${O.map((U,L)=>` ${L+1}) ${U.name.padEnd(F)} ${U.slug} ${U.role} ${U.id}`).join(`
96
+ `)}
97
+ `);let M=await j.promptChoice(`Workspace [1-${O.length}]: `,O.length);return N[M]}var Qr={name:"auth login",summary:"Verify and store a credential for this machine",usage:["Usage: hlix auth login [--workspace <id>] [--base-url <url>]",""," --base-url Defaults to https://server.hlix.ai"," --workspace Workspace (organization) id to act in. Optional: the key's"," own workspaces are listed after it is read, and the only"," one is taken automatically.","","The API key is read from a hidden prompt and never accepted as an argument.","For CI, set HLIX_API_KEY and HLIX_WORKSPACE_ID in the environment."].join(`
98
+ `),supportsJson:!0,options:["base-url","workspace"],async run(j){let O=typeof j.flags.workspace==="string"?j.flags.workspace:j.env.HLIX_WORKSPACE_ID,T=j.env.HLIX_API_KEY??await j.readSecret?.("Hlix API key: ")??"";if(!T)throw new e("missing_credential","No API key entered. Run from a terminal or set HLIX_API_KEY for CI.");let N=typeof j.flags["base-url"]==="string"?j.flags["base-url"]:j.env.HLIX_BASE_URL??_r,H=new URL(N),F=H.hostname==="localhost"||H.hostname==="127.0.0.1"||H.hostname==="::1";if(H.protocol!=="https:"&&!(H.protocol==="http:"&&F))throw new e("invalid_base_url","--base-url must use HTTPS (HTTP is allowed only for localhost).");let M=new Ht({baseUrl:N,credential:Ot(T),retry:{attempts:1}}),U=await Kc(j,await M.workspaces.list(),O);await new Ht({baseUrl:N,credential:Ot(T),organizationId:U,retry:{attempts:1}}).projects.list();let D=ko({baseUrl:N,apiKey:T,organizationId:U},j.env);if(j.json)j.stdout(ne(re(Qr.name,{baseUrl:N,organizationId:U,credentialPath:D})));else j.stdout(`Signed in to ${N}
99
+ Credential stored at ${D}
100
+ `);return 0}},es={name:"auth status",summary:"Show which credential is in use, where it came from, and whether it works",usage:["Usage: hlix auth status [--json]","","Names the SOURCE of the credential — the stored file, HLIX_API_KEY, or the","desktop app's own session when hlix was opened from its Terminal tab — and","verifies it against the API. The credential itself is never printed, not even","a prefix: machine output gets piped into logs."].join(`
101
+ `),supportsJson:!0,async run(j){let O=r({env:j.env,flags:j.flags,cwd:j.cwd});if(O.conflict)throw new e("workspace_mismatch",O.conflict);if(!O.credential)throw new e("unauthenticated","No credential. Run `hlix auth login`, or set HLIX_API_KEY for CI.");try{await j.requireClient().projects.list()}catch(N){throw j.stderr(`credential from ${O.credentialSource}, workspace ${O.workspaceId??"none"}, api ${O.baseUrl}
102
+ `),N}let T={credentialSource:O.credentialSource,credentialPath:O.credentialSource==="file"?O.credentialPath:null,baseUrl:O.baseUrl,baseUrlSource:O.baseUrlSource,workspaceId:O.workspaceId,workspaceSource:O.workspaceSource,valid:!0};if(j.json)return j.stdout(ne(re(es.name,T))),0;return j.stdout(`${ve([["credential",u(O)??"none"],["api",`${O.baseUrl} (from ${O.baseUrlSource})`],["workspace",O.workspaceId?`${O.workspaceId} (from ${O.workspaceSource})`:"none"],["status","valid"]])}
103
+ `),0}},Dt={name:"auth logout",summary:"Remove the stored credential from this machine",usage:["Usage: hlix auth logout [--yes] [--json]","","Removes ~/.config/hlix/credentials.json after confirming. A credential","supplied through HLIX_API_KEY is not removed — unset it in the shell that","set it — and neither is the desktop app's own session; sign out in the app."].join(`
104
+ `),supportsJson:!0,options:["yes"],async run(j){let O=r({env:j.env,flags:j.flags,cwd:j.cwd});if(O.credentialSource==="env"||O.credentialSource==="session"){let N=O.credentialSource==="session",H=N?"session":"environment",F=N?"This session belongs to the Hlix desktop app; sign out there to end it.":"HLIX_API_KEY is set in this environment; unset it there to sign out.",M=bo(j.env);if(!M){let L={removed:!1,reason:H,path:null};if(j.json)j.stdout(ne(re(Dt.name,L)));else j.stdout(`${F}
105
+ `);return 0}if(j.flags.yes!==!0){let L={removed:!1,reason:H,path:M};if(j.json)j.stdout(ne(re(Dt.name,L)));else j.stdout(`${F}
106
+ A stored credential also exists at ${M} — repeat with --yes to remove it.
107
+ `);return 0}let U=Er(j.env);if(j.json)j.stdout(ne(re(Dt.name,U)));else j.stdout(`Removed ${U.path}
108
+ ${N?"The desktop app's session is still in use; sign out there to finish.":"HLIX_API_KEY is still set in this environment; unset it there to finish signing out."}
109
+ `);return 0}if(j.flags.yes!==!0&&O.credential){if(j.json||!j.confirm)throw new e("approval_required","Removing the stored credential needs approval. Repeat with `--yes`.");if(!await j.confirm(`Remove the stored credential at ${O.credentialPath}? Signing back in needs the API key again.`))throw new e("cancelled","Logout cancelled.")}let T=Er(j.env);if(j.json)j.stdout(ne(re(Dt.name,T)));else j.stdout(T.removed?`Removed ${T.path}
110
+ `:`No stored credential at ${T.path}
111
+ `);return 0}};var oi=Mt.join(" | "),ts={name:"config list",summary:"Show every setting in effect and which file supplied it",usage:["Usage: hlix config list [--cwd <dir>] [--json]","","Merges the machine-wide file with this folder's, per key, and names the","source of each value: project, global, or default (no file names it)."].join(`
112
+ `),supportsJson:!0,async run(j){let O=g(j.cwd,j.env),T=Uo(O);if(j.json)return j.stdout(ne(re(ts.name,{settings:T,paths:O.paths}))),0;return j.stdout(`${Ge(["setting","value","source","applies to"],T.map((N)=>[N.key,N.value??"-",N.source,Mo[N.key]??"this folder's binding"]))}
113
+ `),j.stdout(`
114
+ global ${O.paths.global}
115
+ `),j.stdout(`project ${O.paths.project??"- (this folder is not bound to hlix)"}
116
+ `),0}},ns={name:"config get",summary:"Print one setting's effective value",usage:[`Usage: hlix config get <${oi}> [--cwd <dir>] [--json]`,"","Prints the value the cascade resolves for one key, or exits 1 when no","file names it."].join(`
117
+ `),supportsJson:!0,args:{min:1,max:1},async run(j){let O=zr(j.args[0]),T=g(j.cwd,j.env),N=T.merged[O]??null,H=T.sources[O]??"default";if(j.json)return j.stdout(ne(re(ns.name,{key:O,value:N,source:H}))),N===null?1:0;if(N===null)return j.stderr(`${O} is not set. Set it with \`hlix config set ${O} <value>\`.
118
+ `),1;return j.stdout(`${N}
119
+ `),0}},rs={name:"config set",summary:"Set one setting for this folder, or for the machine with --global",usage:[`Usage: hlix config set <${oi}> <value> [--global] [--cwd <dir>] [--json]`,"","Writes this folder's .hlix/config.json, or the machine-wide file with","--global. Other keys in the file are left untouched. The binding keys","(projectId, workspaceId, apiUrl) are written by init/import and are","refused here."].join(`
120
+ `),supportsJson:!0,options:["global"],args:{min:2,max:2},async run(j){let O=zr(j.args[0]),T=Do(O,j.args[1]),N=j.flags.global===!0?"global":"project",H=h({key:O,value:T,scope:N,cwd:j.cwd,env:j.env});if(j.json)return j.stdout(ne(re(rs.name,{key:O,value:T,scope:N,path:H}))),0;return j.stdout(`${O} = ${T} (${N}: ${H})
121
+ `),0}};function bt(j,O){if(typeof j!=="object"||j===null)return"";let T=j[O];return T===null||T===void 0?"":String(T)}var ss={name:"projects list",summary:"List the projects in your workspace",usage:"Usage: hlix projects list [--json]",supportsJson:!0,async run(j){let O=await j.requireClient().projects.list();if(j.json)return j.stdout(ne(re(ss.name,O))),0;let T=Array.isArray(O)?O:[];if(T.length===0)return j.stdout(`No projects.
122
+ `),0;return j.stdout(`${Ge(["ID","NAME","STACK"],T.map((N)=>[bt(N,"id"),bt(N,"name"),bt(N,"stack")]))}
123
+ `),0}},os={name:"projects get",summary:"Show one project, defaulting to the one this folder is bound to",usage:["Usage: hlix projects get [project-id] [--json]","","With no id, the project this folder is bound to is used."].join(`
124
+ `),supportsJson:!0,args:{min:0,max:1},async run(j){let O=j.args[0]??t(j.cwd)?.config.projectId;if(!O)throw new e("missing_argument","A project id is required, or run this inside a folder bound to a project.");let T=await j.requireClient().projects.get(O);if(j.json)return j.stdout(ne(re(os.name,T))),0;let N=T.repos;return j.stdout(`${ve([["id",bt(T,"id")],["name",bt(T,"name")],["stack",bt(T,"stack")],["status",bt(T,"status")],["repos",Array.isArray(N)?String(N.length):""]].filter(([,H])=>H!==""))}
125
+ `),0}},is={name:"projects delete",summary:"Delete a project from your workspace",usage:"Usage: hlix projects delete <id|name> [--yes] [--json]",supportsJson:!0,options:["yes"],args:{min:1,max:1},async run(j){let O=j.requireClient(),T=j.args[0],N=await O.projects.list(),H=N.find((D)=>D.id===T),F=H?[H]:N.filter((D)=>D.name===T);if(F.length===0)throw new e("not_found",`No project named or identified by "${T}".`);if(F.length>1)throw new e("invalid_usage",`More than one project is named "${T}". Use its ID.`);let M=F[0],U=`Delete project "${M.name}"?`;if(j.stderr(`${U}
126
+ `),j.flags.yes!==!0){if(t(j.cwd)?.config.projectId===M.id)throw new e("approval_required","This folder is bound to that project. Pass --yes to delete it.");if(j.json||!j.confirm)throw new e("approval_required","Project deletion requires --yes when not interactive.");if(!await j.confirm(U))throw new e("cancelled","Project deletion cancelled.")}let L=await O.projects.delete(M.id);if(j.json)j.stdout(ne(re(is.name,L)));else j.stdout(`Deleted project "${M.name}".
127
+ `);return 0}};function as(j,O){let T=j.args[0];if(!T)throw new e("missing_argument",`A ${O} id is required.`);return T}function ii(j,O){let T=j.flags[O];return typeof T==="string"&&T.trim()?T.trim():void 0}function He(j,O){if(typeof j!=="object"||j===null)return"";let T=j[O];return T===null||T===void 0?"":String(T)}var cs={name:"tasks list",summary:"List tasks, defaulting to the project this folder is bound to",usage:["Usage: hlix tasks list [--project <id>] [--status <status>] [--json]","","With no --project, a folder bound to a project lists that project's tasks;","anywhere else it lists the workspace's tasks."].join(`
128
+ `),supportsJson:!0,options:["project","status"],async run(j){let O=ii(j,"project")??t(j.cwd)?.config.projectId,T=ii(j,"status"),N=await j.requireClient().tasks.list({...O?{projectId:O}:{},...T?{status:T}:{}});if(j.json)return j.stdout(ne(re(cs.name,N))),0;let H=Array.isArray(N)?N:[];if(H.length===0)return j.stdout(`No tasks.
129
+ `),0;return j.stdout(`${Ge(["ID","STATUS","TITLE"],H.map((F)=>[He(F,"id"),He(F,"status"),He(F,"title")||He(F,"description").split(`
130
+ `)[0]||""]))}
131
+ `),0}},ls={name:"tasks get",summary:"Show one task",usage:"Usage: hlix tasks get <task-id> [--json]",supportsJson:!0,args:{min:1,max:1},async run(j){let O=as(j,"task"),T=await j.requireClient().tasks.get(O);if(j.json)return j.stdout(ne(re(ls.name,T))),0;return j.stdout(`${ve([["id",He(T,"id")],["status",He(T,"status")],["title",He(T,"title")],["project",He(T,"projectId")],["description",He(T,"description")]])}
132
+ `),0}},ds={name:"tasks review",summary:"Show the verified review evidence for a task",usage:"Usage: hlix tasks review <task-id> [--json]",supportsJson:!0,args:{min:1,max:1},async run(j){let O=as(j,"task"),T=await j.requireClient().tasks.review(O);if(j.json)return j.stdout(ne(re(ds.name,T))),0;return j.stdout(`${JSON.stringify(T,null,2)}
133
+ `),0}},ps={name:"tasks watch",summary:"Stream a task's status changes until it finishes",usage:["Usage: hlix tasks watch <task-id> [--json]","","Streams the task's server-sent status frames and exits when the task","reaches a terminal status or the server closes the stream.","","With --json, each frame is printed as one envelope per line (JSONL) so a","consumer can read them as they arrive."].join(`
134
+ `),supportsJson:!0,args:{min:1,max:1},async run(j){let O=as(j,"task"),T=j.requireClient();for await(let N of T.tasks.stream(O)){let H;try{H=JSON.parse(N.data)}catch{H=N.data}if(j.json)j.stdout(`${JSON.stringify(re(ps.name,H))}
135
+ `);else{let F=He(H,"status"),M=He(H,"error");j.stdout(M?`error: ${M}
136
+ `:`${F||N.data}
137
+ `)}}return 0}};import{realpath as xd}from"node:fs/promises";import{resolve as Cd}from"node:path";import{parse as hl}from"jsonc-parser";import{parse as yl}from"smol-toml";import{parse as wl}from"yaml";var Vn={install:null,previewCommand:null,previewPort:null,verifyCommand:null,packageManager:null};var Vc=[["next",3000],["nuxt",3000],["@remix-run/dev",5173],["@sveltejs/kit",5173],["astro",4321],["@angular/cli",4200],["gatsby",8000],["react-scripts",3000],["vite",5173]],Yc=["vite","next","webpack","react-scripts","@rsbuild/core","parcel"],mn=8080,Kn=8000,Xc=String.raw`import http.server as h, urllib.parse as u, sys, os, re, io
138
+ B = (sys.argv[2] if len(sys.argv) > 2 else "").rstrip("/")
139
+ D = os.path.abspath(sys.argv[3] if len(sys.argv) > 3 and sys.argv[3] else ".")
140
+ P = int(os.environ.get("PORT") or ${mn})
141
+ L = re.compile(rb"((?:src|href|action|poster)\s*=\s*[\"'])/(?!/)" + (rb"(?!" + re.escape(B[1:].encode()) + rb"(?:/|[\"']))" if B else b""))
142
+ class H(h.SimpleHTTPRequestHandler):
143
+ def __init__(s, *a, **k):
144
+ super().__init__(*a, directory=D, **k)
145
+ def send_head(s):
146
+ raw = u.urlsplit(s.path).path
147
+ if B and (raw == B or raw.startswith(B + "/")):
148
+ s.path = s.path[len(B):] or "/"
149
+ p = u.unquote(u.urlsplit(s.path).path).replace(chr(92), "/")
150
+ if any(x.startswith(".") for x in p.split("/")):
151
+ s.send_error(404)
152
+ return None
153
+ f = s.translate_path(s.path)
154
+ if os.path.isdir(f) and p.endswith("/"):
155
+ f = os.path.join(f, "index.html")
156
+ elif not os.path.exists(f) and "." not in p.rsplit("/", 1)[-1]:
157
+ f = f + ".html" if os.path.isfile(f + ".html") else os.path.join(D, "index.html")
158
+ if not (f.endswith((".html", ".htm")) and os.path.isfile(f)):
159
+ return super().send_head()
160
+ with open(f, "rb") as fh:
161
+ body = fh.read()
162
+ if B:
163
+ body = L.sub(lambda m: m.group(1) + B.encode() + b"/", body)
164
+ s.send_response(200)
165
+ s.send_header("Content-Type", "text/html; charset=utf-8")
166
+ s.send_header("Content-Length", str(len(body)))
167
+ s.end_headers()
168
+ return io.BytesIO(body)
169
+ def list_directory(s, path):
170
+ s.send_error(404)
171
+ return None
172
+ h.ThreadingHTTPServer(("", P), H).serve_forever()
173
+ `;function Xn(j="."){return`python3 -c 'import base64,sys;exec(base64.b64decode(sys.argv[1]))' ${fn(Xc)} "$PREVIEW_PUBLIC_PATH" ${j}`}var di="HLIX_PREVIEW_FAILURE";function Yn(j){return`{ echo "${di}=${j}"; exit 1; }`}var Zc=`const handler = {
174
+ get(target, key) {
175
+ if (key === 'then' || key === 'prototype' || key === '$$typeof') return undefined
176
+ if (key === '__esModule') return false
177
+ if (key === Symbol.toPrimitive) return () => ''
178
+ if (key === 'displayName' || key === 'name') return 'Unavailable'
179
+ return stub
180
+ },
181
+ apply(target, self, args) {
182
+ const props = args[0]
183
+ return props !== null && typeof props === 'object' && !Array.isArray(props) ? null : stub
184
+ },
185
+ }
186
+ const stub = new Proxy(function Unavailable() {}, handler)
187
+ module.exports = stub
188
+ `,Qc=`const path = require('path')
189
+ const loaded = __CONFIG__
190
+ const dir = path.join(__dirname, 'hlix-web')
191
+ // React Native Web's own names, as imported directly and as Expo rewrites them.
192
+ const WEB_ROOT = new Set(['react-native', 'react-native-web', 'react-native-web/dist/index'])
193
+ function withNativeStubs(config) {
194
+ const upstream = config.resolver.resolveRequest
195
+ config.resolver.resolveRequest = (context, moduleName, platform) => {
196
+ if (platform === 'web' && !context.originModulePath.startsWith(dir)) {
197
+ if (WEB_ROOT.has(moduleName)) return { type: 'sourceFile', filePath: path.join(dir, 'react-native.js') }
198
+ if (moduleName.startsWith('react-native/Libraries/')) return { type: 'sourceFile', filePath: path.join(dir, 'native-stub.js') }
199
+ }
200
+ return (upstream || context.resolveRequest)(context, moduleName, platform)
201
+ }
202
+ return config
203
+ }
204
+ module.exports = typeof loaded === 'function'
205
+ ? async (...args) => withNativeStubs(await loaded(...args))
206
+ : loaded && typeof loaded.then === 'function' ? loaded.then(withNativeStubs) : withNativeStubs(loaded)
207
+ `,el=[[86,57],[85,56],[83,55],[81,54],[79,53],[76,52],[74,51]],tl=String.raw`const fs = require("fs"), cp = require("child_process")
208
+ const [base, pm] = process.argv.slice(-2)
209
+ // No preview path: not the preview's own copy. Prepared already: a restart.
210
+ if (!base || fs.existsSync("hlix-web/native-stub.js")) process.exit(0)
211
+ const fail = (code, why) => { console.error("hlix: " + why); console.log("${di}=" + code); process.exit(1) }
212
+ const run = (cmd, args) => {
213
+ const res = cp.spawnSync(cmd, args, { stdio: "inherit", env: { ...process.env, CI: "1", EXPO_NO_TELEMETRY: "1" } })
214
+ if (res.status !== 0) fail("packages_unavailable", "could not install " + args.join(" "))
215
+ }
216
+ const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"))
217
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies }
218
+ const bare = !("expo" in deps)
219
+ // npm refuses a React Native major change over peer ranges; the others only warn.
220
+ const peers = pm === "npm" ? ["--", "--legacy-peer-deps"] : []
221
+ if (bare) {
222
+ const minor = Number((String(deps["react-native"] || "").match(/0\.(\d+)/) || [])[1] || 0)
223
+ const sdk = (${JSON.stringify(el)}).find(([m]) => minor >= m)
224
+ if (!sdk) fail("react_native_too_old", "React Native 0." + minor + " is older than any release with web support")
225
+ const add = { npm: ["install", "--legacy-peer-deps", "--no-audit", "--no-fund"], pnpm: ["add"], yarn: ["add"], bun: ["add"] }[pm] || ["install"]
226
+ run(pm, [...add, "expo@~" + sdk[1] + ".0.0"])
227
+ }
228
+ const missing = ["react-dom", "react-native-web", "@expo/metro-runtime", "babel-preset-expo"].filter((name) => !(name in deps))
229
+ if (missing.length) run("npx", ["expo", "install", ...missing, ...peers])
230
+ if (bare) {
231
+ run("npx", ["expo", "install", "--fix", ...peers])
232
+ fs.mkdirSync("hlix-web", { recursive: true })
233
+ fs.writeFileSync("hlix-web/entry.js", "import 'expo'\nimport { AppRegistry } from 'react-native'\nimport '../index'\nconst rootTag = document.getElementById('root') || document.body.appendChild(document.createElement('div'))\nAppRegistry.runApplication(AppRegistry.getAppKeys()[0], { rootTag })\n")
234
+ const next = JSON.parse(fs.readFileSync("package.json", "utf8"))
235
+ next.main = "hlix-web/entry.js"
236
+ fs.writeFileSync("package.json", JSON.stringify(next, null, 2))
237
+ for (const file of ["babel.config.js", ".babelrc", ".babelrc.js", "babel.config.cjs"]) {
238
+ if (!fs.existsSync(file)) continue
239
+ fs.writeFileSync(file, fs.readFileSync(file, "utf8").replace(/module:(?:@react-native\/babel-preset|metro-react-native-babel-preset)/g, "babel-preset-expo"))
240
+ }
241
+ }
242
+ fs.mkdirSync("hlix-web", { recursive: true })
243
+ fs.writeFileSync("hlix-web/native-stub.js", ${JSON.stringify(Zc)})
244
+ fs.writeFileSync("hlix-web/react-native.js", "const web = require('react-native-web/dist/index')\nconst stub = require('./native-stub')\nmodule.exports = new Proxy(web, { get: (target, key) => (key in target ? target[key] : stub) })\n")
245
+ const own = ["metro.config.js", "metro.config.cjs"].find((file) => fs.existsSync(file))
246
+ let config = "require('expo/metro-config').getDefaultConfig(__dirname)"
247
+ if (own && !bare && /expo/.test(fs.readFileSync(own, "utf8"))) {
248
+ // Beside the original, so its own __dirname still names the project.
249
+ fs.renameSync(own, "metro.config.hlix-original.js")
250
+ config = "require('./metro.config.hlix-original.js')"
251
+ }
252
+ if (own) fs.rmSync(own, { force: true })
253
+ fs.writeFileSync("metro.config.js", ${JSON.stringify(Qc)}.replace("__CONFIG__", config))
254
+ `,nl=String.raw`const fs = require("fs")
255
+ const base = (process.argv[process.argv.length - 1] || "").replace(/\/+$/, "")
256
+ if (!base) process.exit(0)
257
+ const dynamic = ["app.config.ts", "app.config.js"].filter((file) => fs.existsSync(file))
258
+ if (dynamic.length || fs.existsSync("app.json")) {
259
+ const json = dynamic.length ? { expo: require("expo/config").getConfig(process.cwd()).exp } : JSON.parse(fs.readFileSync("app.json", "utf8"))
260
+ const expo = json.expo || json
261
+ expo.experiments = { ...expo.experiments, baseUrl: base }
262
+ fs.writeFileSync("app.json", JSON.stringify(json, null, 2))
263
+ for (const file of dynamic) fs.rmSync(file)
264
+ }
265
+ `,rl=String.raw`import json, os, shutil, sys, tarfile, tempfile, urllib.request
266
+ root = sys.argv[1]
267
+ base = "https://storage.googleapis.com/flutter_infra_release/releases"
268
+ index = json.load(urllib.request.urlopen(base + "/releases_linux.json", timeout=60))
269
+ stable = index["current_release"]["stable"]
270
+ release = next(r for r in index["releases"] if r["hash"] == stable)
271
+ tmp = tempfile.mkdtemp(dir=root)
272
+ archive = os.path.join(tmp, "flutter.tar.xz")
273
+ with urllib.request.urlopen(base + "/" + release["archive"], timeout=600) as src, open(archive, "wb") as out:
274
+ shutil.copyfileobj(src, out)
275
+ with tarfile.open(archive) as tar:
276
+ tar.extractall(tmp, filter="tar")
277
+ os.remove(archive)
278
+ os.rename(os.path.join(tmp, "flutter"), os.path.join(root, "sdk"))
279
+ shutil.rmtree(tmp, ignore_errors=True)
280
+ print("hlix: Flutter " + release["version"] + " installed")
281
+ `,sl=String.raw`import sys, zipfile
282
+ args = [a for a in sys.argv[1:] if a not in ("-o", "-q")]
283
+ dest = args[args.index("-d") + 1] if "-d" in args else "."
284
+ zipfile.ZipFile(args[0]).extractall(dest)
285
+ `;function ai(j,O){return`python3 -c 'import base64,sys;exec(base64.b64decode(sys.argv[1]))' ${fn(j)} ${O}`}function ol(){return['mkdir -p "$HOME/.cache/hlix-flutter"/bin',`{ [ -x "$HOME/.cache/hlix-flutter"/sdk/bin/flutter ] || { echo "hlix: installing the Flutter SDK (first run only)"; ${ai(rl,'"$HOME/.cache/hlix-flutter"')}; } || ${Yn("flutter_sdk_unavailable")}; }`,`{ command -v unzip >/dev/null 2>&1 || { printf '#!/bin/sh\\n%s "$@"\\n' ${al(ai(sl,""))} > "$HOME/.cache/hlix-flutter"/bin/unzip && chmod +x "$HOME/.cache/hlix-flutter"/bin/unzip; }; }`,'PATH="$HOME/.cache/hlix-flutter"/sdk/bin:"$HOME/.cache/hlix-flutter"/bin:$PATH',"export PATH","{ flutter config --no-analytics >/dev/null 2>&1 || true; }",`{ flutter pub get || ${Yn("packages_unavailable")}; }`,`{ flutter run -d web-server --web-hostname 0.0.0.0 --web-port "$PORT" </dev/null || { echo "hlix: the dev server stopped; serving a web build instead"; flutter build web --base-href "$PREVIEW_PUBLIC_PATH/" && ${Xn("build/web")}; } || ${Yn("web_build_failed")}; }`].join(" && ")}function il(j){let O=`printf %s ${fn(tl)} | base64 -d | node - "$PREVIEW_PUBLIC_PATH" ${j}`,T=`CI=1 npx expo export --platform web --output-dir dist && ${Xn("dist")}`;return`${O} && ${pi(nl,"PREVIEW_PUBLIC_PATH")} && { BROWSER=none EXPO_NO_TELEMETRY=1 npx expo start --no-dev --port "$PORT" </dev/null || { echo "hlix: the dev server stopped; serving a web build instead"; ${T}; } || ${Yn("web_build_failed")}; }`}function al(j){return`'${j.replace(/'/g,"'\\''")}'`}var cl=String.raw`const fs = require("fs")
286
+ const base = (process.argv[process.argv.length - 1] || "").replace(/\/+$/, "")
287
+ if (!base) process.exit(0)
288
+ const file = ["next.config.ts", "next.config.mts", "next.config.mjs", "next.config.js", "next.config.cjs"].find((name) => fs.existsSync(name))
289
+ const wrap = (name) => "(async (...args) => { const c = typeof " + name + " === \"function\" ? await " + name + "(...args) : await " + name + "; return { ...c, basePath: " + JSON.stringify(base) + " } })"
290
+ if (!file) {
291
+ fs.writeFileSync("next.config.mjs", "export default { basePath: " + JSON.stringify(base) + " }\n")
292
+ process.exit(0)
293
+ }
294
+ let text = fs.readFileSync(file, "utf8")
295
+ if (text.includes("__hlixPreviewConfig")) process.exit(0)
296
+ if (/\bexport\s+default\b/.test(text)) {
297
+ text = text.replace(/\bexport\s+default\b/, "const __hlixPreviewConfig =") + "\nexport default " + wrap("__hlixPreviewConfig") + "\n"
298
+ } else if (/\bmodule\.exports\s*=/.test(text)) {
299
+ text += "\nconst __hlixPreviewConfig = module.exports\nmodule.exports = " + wrap("__hlixPreviewConfig") + "\n"
300
+ } else {
301
+ process.exit(0)
302
+ }
303
+ fs.writeFileSync(file, text)
304
+ `,ll=String.raw`import os, re, sys
305
+ hosts = [h for h in (sys.argv[2] if len(sys.argv) > 2 else "").split(",") if h]
306
+ if not hosts:
307
+ sys.exit(0)
308
+ match = re.search(r"DJANGO_SETTINGS_MODULE['\"]\s*,\s*['\"]([\w.]+)['\"]", open("manage.py").read())
309
+ if not match:
310
+ sys.exit(0)
311
+ module = match.group(1).replace(".", "/")
312
+ path = module + ".py" if os.path.isfile(module + ".py") else os.path.join(module, "__init__.py")
313
+ if not os.path.isfile(path) or "# hlix preview hosts" in open(path).read():
314
+ sys.exit(0)
315
+ with open(path, "a") as f:
316
+ f.write("\n# hlix preview hosts\nALLOWED_HOSTS = list(globals().get('ALLOWED_HOSTS') or ['.localhost', '127.0.0.1', '[::1]']) + %r\n" % hosts)
317
+ `;function pi(j,O){return`printf %s ${fn(j)} | base64 -d | node - "$${O}"`}var dl=["test","typecheck","check","lint"],pl=["dev","start","serve","preview"];function ms(j){if(!j)return{};try{let O=JSON.parse(j);return O&&typeof O==="object"?O:{}}catch{return{}}}function ul(j){return{...dt(j.dependencies)?j.dependencies:{},...dt(j.devDependencies)?j.devDependencies:{}}}function ml(j){if(!new Set(j.rootFiles).has("pubspec.yaml"))return!1;let O=j.configFiles?.["pubspec.yaml"];return O===void 0||/^\s+sdk:\s*flutter\s*$/m.test(O)}function ui(j){let O=new Set(j.rootFiles),T=ms(j.packageJson),N=typeof T.packageManager==="string"?T.packageManager.split("@")[0]:"",H=N==="bun"||O.has("bun.lock")||O.has("bun.lockb")?"bun":N==="pnpm"||O.has("pnpm-lock.yaml")?"pnpm":N==="yarn"||O.has("yarn.lock")?"yarn":N==="npm"||O.has("package.json")?"npm":null,F=O.has("index.html");if(!H){if(ml(j))return{...Vn,previewCommand:ol(),previewPort:mn,mobile:!0};let D=gl(O,j.configFiles??{});if(D)return D;return F?{...Vn,previewCommand:Xn(),previewPort:mn}:Vn}let M=mi(T,O,H),U={install:`${H} install`,verifyCommand:M.verifyCommand,packageManager:H},L=M.webApp?null:fl(j.workspacePackages??[],H)[0]??null;if(L){let D=(B)=>`cd ${L.dir} && ${B}`;return{...U,previewCommand:D(L.previewCommand),previewPort:L.previewPort,verifyCommand:U.verifyCommand??(L.verifyCommand?D(L.verifyCommand):null),...L.mobile?{mobile:!0}:{}}}return{...U,previewCommand:M.previewCommand,previewPort:M.previewPort,...M.mobile?{mobile:!0}:{}}}function mi(j,O,T,N){let H=dt(j.scripts)?j.scripts:{},F=(G)=>`${T} run ${G}`,M=(G,oe)=>`${F(G)}${T==="npm"?" --":""} ${oe}`,U=pl.find((G)=>typeof H[G]==="string"),L=dl.find((G)=>typeof H[G]==="string"&&!/no test specified/i.test(String(H[G]))&&!/(?:^|\s)(?:--watch(?:All)?|-w)(?:\s|=|$)/.test(String(H[G]))),D=L?F(L):null,B=ul(j),z={previewCommand:null,previewPort:null,verifyCommand:D,webApp:!1,mobile:!1,explicitPort:!1};if("expo"in B||"react-native"in B&&!Yc.some((G)=>(G in B)))return{previewCommand:il(T),previewPort:N??mn,verifyCommand:D,webApp:!0,mobile:!0,explicitPort:!1};let J=Vc.find(([G])=>(G in B)),K=U?li(String(H[U]))??J?.[1]??null:null;if(!U&&!J&&O.has("index.html"))return{...z,previewCommand:Xn(),previewPort:N??mn};if(!U)return z;let X=String(H[U]).trim(),W=N!=null?` --port ${N}`:"",V=W?M(U,W.trim()):F(U),Q=X.split("&&").map((G)=>G.trim());if(Q.length>1&&Q.every((G)=>/^vite(?:\s|$)/.test(G))&&!("@sveltejs/kit"in B)){let G={npm:"npx",bun:"bunx",pnpm:"pnpm exec",yarn:"yarn exec"}[T];V=Q.map((oe,ue)=>`${G} ${oe} --base "$PREVIEW_BASE_PATH/"${ue===Q.length-1?W:""}`).join(" && ")}else if(/^vite(?:\s+(?:dev|serve|preview))?(?:\s|$)/.test(X)&&!/&&|;|\|/.test(X)&&!("@sveltejs/kit"in B))V=M(U,`--base "$PREVIEW_BASE_PATH/"${W}`);else if(/^astro\s+(?:dev|preview)(?:\s|$)/.test(X))V=M(U,`--base "$PREVIEW_BASE_PATH"${W}`);else if(/^next\s+(?:dev|start)(?:\s|$)/.test(X))V=`${pi(cl,"PREVIEW_BASE_PATH")} && ${V}`;else if(/^nuxt\s+(?:dev|preview|start)(?:\s|$)/.test(X))V=`NUXT_APP_BASE_URL="$PREVIEW_BASE_PATH/" ${V}`;return{previewCommand:V,previewPort:N??K,verifyCommand:D,webApp:Boolean(J),mobile:!1,explicitPort:li(X)!=null}}var ci=["web","app","frontend","site","www","client","dashboard"];function fl(j,O){let T=j.filter((H)=>us(H.dir)).map((H)=>{let F=ms(H.packageJson),M=new Set(H.rootFiles??[]);return{dir:H.dir,pkg:F,files:M,...mi(F,M,O)}}).filter((H)=>H.webApp&&H.previewCommand&&H.previewPort!=null),N=(H)=>{let F=ci.indexOf(H.split("/").at(-1)??"");return F<0?ci.length:F};return T.sort((H,F)=>Number(H.mobile)-Number(F.mobile)||Number(!H.dir.startsWith("apps/"))-Number(!F.dir.startsWith("apps/"))||N(H.dir)-N(F.dir)||(H.dir<F.dir?-1:H.dir>F.dir?1:0))}function us(j){return/^[A-Za-z0-9._@-]+(?:\/[A-Za-z0-9._@-]+)*$/.test(j)&&!j.split("/").some((O)=>O===".."||O===".")}function fi(j){let O=ms(j.packageJson),T=Array.isArray(O.workspaces)?O.workspaces:dt(O.workspaces)&&Array.isArray(O.workspaces.packages)?O.workspaces.packages:[],N=j.configFiles?.["pnpm-workspace.yaml"]??"";for(let U of N.split(/\r?\n/)){let L=U.match(/^\s*-\s*["']?([^"'#\s]+)["']?/);if(L)T.push(L[1])}let H=T.filter((U)=>typeof U==="string"&&!U.startsWith("!"));if(H.length===0&&new Set(j.rootFiles).has("turbo.json"))H.push("apps/*","packages/*");let F=new Set,M=new Set;for(let U of H){let L=U.replace(/^\.\//,"").replace(/\/$/,"");if(/^[^*]+\/\*$/.test(L)&&us(L.slice(0,-2)))F.add(L.slice(0,-2));else if(!L.includes("*")&&us(L))M.add(L)}return{parents:[...F].sort(),packages:[...M].sort()}}function gl(j,O){let T=`${O["requirements.txt"]??""}
318
+ ${O["pyproject.toml"]??""}`.toLowerCase(),N=(B)=>new RegExp(`(^|[\\s"'\\[,])${B}\\b`,"m").test(T),H=j.has("requirements.txt")?'"$V/bin/pip" install -q -r requirements.txt':j.has("pyproject.toml")?'"$V/bin/pip" install -q .':null,F=(B,z="")=>H?`V="$HOME/.cache/hlix-venvs/$(cat requirements.txt pyproject.toml 2>/dev/null | cksum | cut -d " " -f1)"; { [ -f "$V/.ready" ] || { rm -rf "$V" && python3 -m venv "$V" && ${H}${z} && touch "$V/.ready"; }; } && "$V/bin/python" ${B}`:null,M=N("pytest")?F("-m pytest",' && "$V/bin/pip" install -q pytest'):null,L=["main.py","app.py","server.py","api.py"].find((B)=>j.has(B))?.replace(/\.py$/,""),D=(B,z=M)=>({...Vn,previewCommand:B,previewPort:Kn,verifyCommand:z});if(j.has("manage.py")){let B=`python3 -c 'import base64,sys;exec(base64.b64decode(sys.argv[1]))' ${fn(ll)} "$PREVIEW_ALLOWED_HOSTS"`;return D(`${B} && python3 manage.py runserver 0.0.0.0:${Kn}`,M??(N("django")?F("manage.py test"):null))}if(L&&N("fastapi"))return D(`python3 -m uvicorn ${L}:app --host 0.0.0.0 --port ${Kn} --root-path "$PREVIEW_PUBLIC_PATH"`);if(L&&N("flask"))return D(`python3 -m flask --app ${L} run --host 0.0.0.0 --port ${Kn}`);return null}function fn(j){return btoa(j)}function li(j){let O=j.match(/(?:--port(?:=|\s+)|-p\s+|\bPORT=)(\d{2,5})\b/),T=O?Number(O[1]):NaN;return Number.isInteger(T)&&T>0&&T<=65535?T:null}function dt(j){return Boolean(j)&&typeof j==="object"&&!Array.isArray(j)}function gi(j){let O=new Set(j.rootFiles),T=new Set;if(O.has("package.json")){for(let H of["coverage",".cache"])T.add(H);if(["package-lock.json","pnpm-lock.yaml","yarn.lock","bun.lock","bun.lockb"].some((H)=>O.has(H)))T.add("node_modules")}if(O.has("Cargo.toml"))T.add("target");if(["pyproject.toml","requirements.txt","setup.py"].some((H)=>O.has(H)))T.add("__pycache__");if(O.has("composer.json")&&O.has("composer.lock"))T.add("vendor");for(let H of fs({...j,rootFiles:O}))T.add(H);return[...T].sort()}function We(j,O,T){let N=(j.match(/"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`|\/\*[\s\S]*?\*\/|\/\/[^\n]*|[A-Za-z_$][\w$]*|[^\s]/g)??[]).filter((L)=>!L.startsWith("//")&&!L.startsWith("/*"));if(N[0]!=="{"){let L=N.findIndex((B,z)=>B==="export"&&N[z+1]==="default"),D=N.findIndex((B,z)=>B==="module"&&N.slice(z+1,z+4).join("")===".exports=");if(L<0&&D<0)return null;if(N=N.slice(L>=0?L+2:D+4),["defineConfig","defineNuxtConfig"].includes(N[0]??"")&&N[1]==="(")N=N.slice(2);if(N[0]!=="{")return null}if(N.some((L,D)=>L==="."&&N[D+1]==="."&&N[D+2]==="."))return null;let H=(L="")=>L.replace(/^["']|["']$/g,""),F=[],M,U=0;for(let L=0;L<N.length;L++){let D=N[L];if(D==="{")F.push(N[L-1]===":"?H(N[L-2]):"");if(D==="}")F.pop();if(!F.length)break;if(D==="["&&["{",","].includes(N[L-1]??""))return null;if(O&&F.length===1&&H(D)===O){if(N[L+1]!==":"||N[L+2]!=="{"||++U>1)return null}if(H(D)===T&&(O?F.length===2&&F.at(-1)===O:F.length===1)&&N[L+1]!==":")return null;if(H(D)!==T||N[L+1]!==":"||(O?F.length!==2||F.at(-1)!==O:F.length!==1))continue;let B=N[L+2]??"";if(M!==void 0||!/^["'`][^\\$]*["'`]$/.test(B)||![",","}"].includes(N[L+3]??""))return null;M=B.slice(1,-1)}return M}function fs(j){let O={};try{let J=JSON.parse(j.packageJson??"{}");if(dt(J))O=J}catch{}let T={...dt(O.dependencies)?O.dependencies:{},...dt(O.devDependencies)?O.devDependencies:{}},N=dt(O.scripts)?Object.entries(O.scripts).filter((J)=>typeof J[1]==="string"):[],H=(J,K=J)=>(J in T)||N.some(([,X])=>new RegExp(`(?:^|[;&|\\s])${K}(?:\\s|$)`).test(X)),F=j.configFiles??{},M=new Set,U=(J)=>{if(typeof J!=="string")return null;let K=J.replace(/^\.\//,"").replace(/\/$/,"");return K&&!K.startsWith("/")&&!/[\\:*?\[\]#!$`"'\r\n]/.test(K)&&!K.split("/").some((X)=>!X||[".","..",".git",".hlix"].includes(X))?K:null},L=(J)=>{let K=U(J);if(K)M.add(K)},D=(J,K)=>{let X=N.filter(([G,oe])=>/(?:^|:)build(?:$|:)/.test(G)||new RegExp(`\\b${J} build\\b`).test(oe)),W=X.filter(([,G])=>new RegExp(`(?:^|\\s)${J}(?:\\s|$)`).test(G));if(!W.length&&(X.length||O.workspaces!==void 0))return null;if(X.some((G)=>!W.includes(G)&&/--(?:out|dist|root|config|project)|\s-[dpc]\b/.test(G[1])))return null;let V,Q=!1;for(let[,G]of W){if(/[$`\\;|<>\n]/.test(G)||/(?:^|\s)(?:cd|pushd|popd)\s/.test(G))return null;for(let oe of G.split("&&")){let ue=oe.match(/"[^"\n]*"|'[^'\n]*'|[^\s]+/g)??[];if(ue.some((te)=>/["']/.test(te)&&!/^(?:"[^"\n]*"|'[^'\n]*')$/.test(te)))return null;let ae=ue.map((te)=>te.replace(/^["']|["']$/g,"")),ee=ae.indexOf(J);if(ee<0)continue;if(ee!==0&&!(ee===1&&["npx","bunx"].includes(ae[0])))return null;let Y=ae.slice(ee+1);if(Y[0]==="build")Y.shift();let q;for(let te=0;te<Y.length;te++){let[de,...fe]=Y[te].split("="),ge=fe.length?fe.join("="):void 0;if(!K.includes(de)||q!==void 0)return null;let je=ge??Y[++te],he=U(je);if(!he)return null;q=he}if(Q&&q!==V)return null;Q=!0,V=q}}return V},B=(J)=>{let K=[...new Set([...j.rootFiles,...Object.keys(F)])].filter((X)=>X.startsWith(`${J}.config.`)||J==="turbo"&&X==="turbo.json");if(!K.length)return"{}";return K.length===1?F[K[0]]??null:null},z=(J,K,X,W,V,Q,G)=>{let oe=B(J),ue=D(J,V);if(oe===null||ue===null)return;let ae=Q?We(oe,null,Q):void 0,ee=We(oe,K,X);if(ae===null||ee===null)return;let Y=ae===void 0||ae==="."||ae==="./"?"":U(ae);if(Y===null)return;let te=U(ue??ee??W);if(!te)return;L(Y?`${Y}/${te}`:te);for(let de of G??[])L(Y?`${Y}/${de}`:de)};if(H("vite"))z("vite","build","outDir","dist",["--outDir","--out-dir"],"root");if(H("next")){let J=B("next"),K=J===null?null:We(J,null,"output");if(J!==null&&(K===void 0||K==="standalone"||K==="export"&&We(J,null,"distDir")===void 0))z("next",null,"distDir",".next",[],void 0,K==="export"?["out"]:[])}if(H("astro"))z("astro",null,"outDir","dist",["--outDir","--out-dir"],"root");if(H("nuxt")){let J=B("nuxt");if(J!==null&&We(J,null,"nitro")===void 0&&We(J,null,"extends")===void 0)z("nuxt",null,"buildDir",".nuxt",[],"rootDir",[".output"])}if(H("turbo"))z("turbo",null,"cacheDir",".turbo",["--cache-dir"]);if(H("webpack")){let J=B("webpack");if(J!==null&&We(J,null,"context")===void 0)z("webpack","output","path","dist",["--output-path"])}if(H("rollup"))z("rollup","output","dir",void 0,["--dir","-d"]);if(H("parcel")||H("parcel-bundler","parcel")){let J=D("parcel",["--dist-dir"]);if(J!==null&&O.targets===void 0&&!["main","module","browser"].some((K)=>typeof O[K]==="string"))L(J??"dist")}if(H("react-scripts")&&D("react-scripts",[])!==null)L("build");if(H("typescript","tsc")){let J=D("tsc",["--outDir"]),K=Object.keys(F).filter((X)=>/^tsconfig(?:\.[^/]*)?\.json$/.test(X));if(J!==null&&K.length===1&&K[0]==="tsconfig.json"){let X=F["tsconfig.json"];if(We(X,null,"extends")===void 0&&We(X,null,"references")===void 0){let W=We(X,"compilerOptions","outDir");if(W!==null)L(J??W)}}}if(gs(F)){L("build"),L("dist");for(let J of j.rootFiles)if(J.endsWith(".egg-info"))L(J)}return[...M].sort()}function gs(j){let O=(j["pyproject.toml"]??"").split(/^\[build-system\]\s*$/m)[1]?.split(/^\[/m)[0]??"";return/^build-backend\s*=\s*["'][^"']+["']/m.test(O)||/(?:from\s+(?:setuptools|distutils.core)\s+import\s+.*\bsetup\b|(?:setuptools|distutils.core)\.setup\s*\()/.test(j["setup.py"]??"")}var Pe=(j)=>j&&typeof j==="object"&&!Array.isArray(j)?j:{},Bt=(j)=>Array.isArray(j)?j.filter((O)=>typeof O==="string"):[];function hi(j){let O=[];function T(Y,q="json"){let te=j.get(Y);if(!te)return{};try{if(q==="yaml")return Pe(wl(te,{maxAliasCount:50}));if(q==="toml")return Pe(yl(te));if(q==="jsonc"){let de=[],fe=hl(te,de,{allowTrailingComma:!0});if(de.length)throw Error("invalid JSONC");return Pe(fe)}return Pe(JSON.parse(te))}catch{return O.push(`Could not parse ${Y}`),{}}}let N=[...j.keys()].sort(),H=T("package.json"),F={packageJson:j.get("package.json")??null,rootFiles:N.filter((Y)=>!Y.includes("/")),configFiles:Object.fromEntries(["requirements.txt","pyproject.toml","pnpm-workspace.yaml"].flatMap((Y)=>j.get(Y)?[[Y,j.get(Y)]]:[]))},M=fi(F),U=N.flatMap((Y)=>{let q=Y.replace(/\/package\.json$/,""),te=q!==Y&&(M.packages.includes(q)||M.parents.some((fe)=>q.startsWith(`${fe}/`)&&!q.slice(fe.length+1).includes("/"))),de=j.get(Y);return te&&de?[{dir:q,packageJson:de}]:[]}),L=ui({...F,workspacePackages:U}),D=typeof H.packageManager==="string"?/^(npm|pnpm|yarn|bun)@(.+)$/.exec(H.packageManager):null,B=Object.create(null);for(let[Y,q]of Object.entries(Pe(H.engines)))if(typeof q==="string")B[Y]=q;if(D)B[D[1]]=D[2].split("+")[0];let z=T("composer.json"),J={...Pe(z["require-dev"]),...Pe(z.require)},K={...typeof J.php==="string"?{constraint:J.php}:{},extensions:Object.keys(J).filter((Y)=>Y.startsWith("ext-")).map((Y)=>Y.slice(4)).sort()};for(let[Y,q]of[[".nvmrc","node"],[".node-version","node"],[".python-version","python"],[".php-version","php"],[".bun-version","bun"]]){let te=j.get(Y)?.trim();if(te)B[q]=te}for(let Y of(j.get(".tool-versions")??"").split(/\r?\n/)){let[q,te]=Y.replace(/#.*/,"").trim().split(/\s+/);if(q&&te)B[q==="nodejs"?"node":q]=te}for(let Y of[".mise.toml","mise.toml"])for(let[q,te]of Object.entries(Pe(T(Y,"toml").tools)))if(typeof te==="string"||typeof te==="number")B[q]=String(te);else O.push(`Unsupported tool version for ${q} in ${Y}`);let X=[];for(let Y of N.filter((q)=>/(^|\/)package.json$/.test(q))){let q=Y==="package.json"?H:T(Y),te={...Pe(q.dependencies),...Pe(q.devDependencies)};for(let de of["nuxt","next","astro","@sveltejs/kit","vite"])if(de in te)X.push({path:Y,name:de})}for(let[Y,q]of[["yiisoft/yii2","yii2"],["laravel/framework","laravel"]])if(Y in J)X.push({path:"composer.json",name:q});let W=new Set,V=Object.create(null);function Q(Y,q){if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(Y))return;if(W.add(Y),/(?:^|_)HOST$/.test(Y)&&typeof q==="string"&&/^[a-zA-Z0-9_.-]+$/.test(q))V[Y]=q}for(let Y of N.filter((q)=>/(^|\/)\.env\.(example|sample|template)$/.test(q)))for(let q of(j.get(Y)??"").split(/\r?\n/)){let te=/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*(?:#.*)?$/.exec(q);if(te)Q(te[1],te[2].replace(/^['"]|['"]$/g,""))}let G=[],oe=[];for(let Y of N.filter((q)=>/(^|\/)(?:docker-compose|compose)(?:[.-][^/]*)?\.ya?ml$/.test(q)))for(let[q,te]of Object.entries(Pe(T(Y,"yaml").services))){let de=Pe(te),fe=typeof de.image==="string"?de.image:"",ge=fe.split("/").at(-1)?.split(/[:@]/)[0],je=ge==="mysql"||ge==="mariadb"?"mysql":ge==="postgres"?"postgres":ge==="redis"?"redis":null;if(je)G.push({file:Y,name:q,kind:je,image:fe});else if(ge!=="traefik"&&ge!=="nginx"&&ge!=="caddy")oe.push({file:Y,name:q});for(let[he,Se]of Object.entries(Pe(de.environment)))Q(he,Se);for(let he of Bt(de.environment)){let Se=he.indexOf("=");Q(Se<0?he:he.slice(0,Se),Se<0?null:he.slice(Se+1))}}let ue=N.find((Y)=>Y===".devcontainer/devcontainer.json")??N.find((Y)=>Y==="devcontainer.json"),ae;if(ue){let Y=T(ue,"jsonc");for(let q of[Y.containerEnv,Y.remoteEnv])for(let[te,de]of Object.entries(Pe(q)))Q(te,de);ae={...typeof Y.image==="string"?{image:Y.image}:{},services:[...typeof Y.service==="string"?[Y.service]:[],...Bt(Y.runServices)],ports:Array.isArray(Y.forwardPorts)?Y.forwardPorts.filter((q)=>Number.isInteger(q)&&Number(q)>0&&Number(q)<=65535):[],commands:[Y.onCreateCommand,Y.updateContentCommand,Y.postCreateCommand,Y.postStartCommand].filter((q)=>typeof q==="string")}}let ee=Bt(H.workspaces).length?Bt(H.workspaces):Bt(Pe(H.workspaces).packages);return ee.push(...Bt(T("pnpm-workspace.yaml","yaml").packages)),{language:j.has("package.json")?"typescript":j.has("pyproject.toml")||j.has("requirements.txt")?"python":j.has("go.mod")?"go":j.has("Cargo.toml")?"rust":j.has("composer.json")?"php":j.has("Gemfile")?"ruby":"other",commands:L,packageManager:D?{name:D[1],version:D[2]}:L.packageManager?{name:L.packageManager}:null,lockfiles:N.filter((Y)=>/(^|\/)(bun.lockb?|pnpm-lock.yaml|yarn.lock|package-lock.json|composer.lock|uv.lock|poetry.lock|Pipfile.lock|Cargo.lock|Gemfile.lock)$/.test(Y)),toolchain:B,php:K,workspaces:[...new Set(ee)].sort(),frameworks:X,turbo:j.has("turbo.json")||"turbo"in Pe(H.devDependencies)||"turbo"in Pe(H.dependencies),services:G,unsupportedServices:oe,envKeys:[...W].sort(),envHosts:V,...ae?{devcontainer:ae}:{},warnings:O}}import{createHash as jn}from"node:crypto";import{createReadStream as Rl}from"node:fs";import{lstat as Ni,mkdir as Al,readFile as kn,readdir as Ol,readlink as Tl,realpath as Fi,stat as Hi,writeFile as Nl}from"node:fs/promises";import{basename as St,dirname as Fl,join as Pn,relative as nr,resolve as rr,sep as Hl}from"node:path";import{execFile as Ml,spawnSync as Ll}from"node:child_process";import bn from"ignore";import{createReadStream as vl}from"node:fs";import{lstat as Jt,mkdtemp as bl,readFile as hs,readdir as er,rename as kl,rm as Sl,writeFile as jl}from"node:fs/promises";import{join as Oe}from"node:path";import yi from"ignore";function zt(j,O){if(Array.isArray(O))return O.some((T)=>zt(j,T));if(!O||j.split("/").some((T)=>T===".git"||T===".hlix"))return!1;return j===O||j.startsWith(`${O}/`)}function gn(j,O){if(typeof O!=="string")return O?.some((T)=>gn(j,T))??!1;return zt(j,O)||O.startsWith(`${j}/`)}function Zn(j,O,T,N){let H=new Map,F=j.length,M=0;for(let B of j){let z=B.path.indexOf("/"),J=z<0?B.path:B.path.slice(0,z+1),K=H.get(J)??{count:0,bytes:0,included:!1};K.count++,K.bytes+=B.size??0,K.included||=zt(B.path,N),H.set(J,K),M+=B.size??0}let U=M>T,L=[...H].sort(([B,z],[J,K])=>Number(z.included)-Number(K.included)||(U?K.bytes-z.bytes:K.count-z.count)||B.localeCompare(J)),D=[];for(let[B,z]of L){if(F<=O&&M<=T)break;D.push(B),F-=z.count,M-=z.bytes}return D}function Wt(j,O){return O.some((T)=>j===T||T.endsWith("/")&&j.startsWith(T))}function hn(j){return`upload limit; add /${j} to .hlixignore, or try --include ${j.replace(/\/$/,"")}`.slice(0,200)}function Qn(j){if(j.length<=5000)return j;return[...j.slice(0,4999),{path:j[4999].path,reason:`${j.length-4999} additional skipped paths (including this path); full list: hlix import --dry-run --json`}]}var bi="# --- managed by Hlix: safe to edit above/below, this block is regenerated ---",ys="# --- end managed by Hlix ---",tr=new Set(["agent-artifacts",".context",".claude/worktrees"]),Pl=/(?:^|\/)(?:Makefile|Dockerfile|Containerfile|Justfile|Rakefile|Gemfile)(?:\.[^/]*)?$/i,El=/\.(?:md|txt|json)$/i,wi=/(?:^|\n)\s*(?:\/\/|\/\*+|\*|#|<!--)\s*(?:@generated\b|generated by\b|do not edit\b)|(?:^|\n)\s*\/\/[#@]\s*sourceMappingURL=/i,vi=/\.(?:log(?:\.\d+)?|tmp|cache|pyc|tsbuildinfo|map)$/i;function yn(j){let O=[...j.matchAll(new RegExp(`^${bi}\\r?$`,"gm"))],T=[...j.matchAll(new RegExp(`^${ys}\\r?$`,"gm"))];if(!O.length&&!T.length)return{before:j,after:"",managed:""};if(O.length!==1||T.length!==1||T[0].index<O[0].index)return null;let N=O[0].index,F=T[0].index+ys.length,M=j.slice(F).match(/^\r?\n/)?.[0]??"";return{before:j.slice(0,N),after:j.slice(F+M.length),managed:j.slice(N,F)}}function ws(j){let O=yn(j);return(O?O.before+`
319
+ `+O.after:j).split(/\r?\n/).filter((T)=>T.startsWith("!")&&T.length>1).map((T)=>T.slice(1))}async function ki(j,O){let T=Oe(j,".hlixignore"),N="";try{let H=await Jt(T).catch((q)=>{if(q.code==="ENOENT")return null;throw q});if(H&&!H.isFile())return{warning:"Kept .hlixignore unchanged: managed rules require a regular file."};if(H)N=await hs(T,"utf8");let F=yn(N);if(!F)return{warning:"Kept .hlixignore unchanged: repair its managed-block markers before refreshing."};let M=ws(N),U=yi().add(M),L=[],D=[],B=yi(),z=new Set;for(let q of O.tracked){let te=q.split("/");while(te.length)z.add(te.join("/")),te.pop()}let J=0,K=0,X=()=>J<30000&&K<268435456,W=(q)=>z.has(q)||gn(q,O.includes)||M.some((te)=>{let de=te.replace(/^\//,"").split(/[?*[\\]/)[0];return!de||de.startsWith(`${q}/`)||U.ignores(`${q}/`)||U.ignores(q)}),V=async(q,te,de=!1)=>{if(O.signal?.throwIfAborted(),!X()||W(q)||O.protectedPath(q,te))return!1;J++;let fe=await Jt(Oe(j,q));if(fe.isSymbolicLink())return te;if(fe.isDirectory()){let he=(await er(Oe(j,q))).sort();for(let Se of he){if(Se===".git")continue;if(!await V(`${q}/${Se}`,te,de))return!1}return!0}if(!fe.isFile()||K+fe.size>268435456)return!1;let ge="",je="";for await(let he of vl(Oe(j,q),{encoding:"utf8",signal:O.signal})){if(K+=Buffer.byteLength(he),ge.length<4096)ge+=he.slice(0,4096-ge.length);let Se=je+he;if(O.protectedContent(q,Se))return!1;je=Se.slice(-4096)}return te||wi.test(ge)||wi.test(je)||!Pl.test(q)&&!/^#!|^<\?php/.test(ge)&&(de&&El.test(q)||vi.test(q))},Q=new Set,G=async(q,te=[],de=!1)=>{if(O.signal?.throwIfAborted(),!X())return;let fe=Oe(j,q),ge=await er(fe,{withFileTypes:!0}),je=async(pe)=>ge.find((be)=>be.name===pe)?.isFile()&&(await Jt(Oe(fe,pe))).size<1048576?hs(Oe(fe,pe),"utf8"):null,he=await je("package.json"),Se=await je("composer.json"),ye=!1,Pt=new Set;try{let pe=JSON.parse(await je("composer.lock")??"null");ye=Array.isArray(pe?.packages);for(let le of[...pe?.packages??[],...pe?.["packages-dev"]??[]]){if(typeof le.name==="string")Pt.add(le.name);if(le.dist?.type==="path")ye=!1}}catch{}try{let pe=JSON.parse(he??"{}"),le=Array.isArray(pe.workspaces)?pe.workspaces:pe.workspaces?.packages;for(let be of Array.isArray(le)?le:[]){if(typeof be!=="string"||be.startsWith("!"))continue;let gt=(q?`${q}/`:"")+be.replace(/^\.\//,"");D.push(gt),B.add(gt)}}catch{}let Et=[he,Se].filter(Boolean).join(`
320
+ `),st={};for(let pe of ge){if(!/^(?:(?:vite|next|nuxt|astro|webpack|rollup)\.config\.[cm]?[jt]s|tsconfig(?:\.[^/]*)?\.json|turbo\.json|pyproject\.toml|setup\.py)$/.test(pe.name))continue;let le=await je(pe.name);if(le!==null)st[pe.name]=le}let $t={packageJson:he,rootFiles:ge.map((pe)=>pe.name),configFiles:st};de||=gs(st);let Tn=gi($t);for(let pe of fs($t))Q.add(q?`${q}/${pe}`:pe);let ft=new Set([...Tn,...te]);for(let pe of ge.sort((le,be)=>le.name<be.name?-1:le.name>be.name?1:0)){if([".git",".hlix",".hlixignore"].includes(pe.name)||pe.isSymbolicLink())continue;let le=q?`${q}/${pe.name}`:pe.name;if(/[\n\r\\*?[\]!#]/.test(le)||le.endsWith(" "))continue;if(J++,!X())return;if(pe.isDirectory()){let be=await Jt(Oe(j,le,".git")).then(()=>O.isRepository(le),()=>!1),gt=tr.has(le)||[...tr].some((Te)=>le.startsWith(`${Te}/`)),Nn=O.gitIgnored.directories.some((Te)=>`${le}/`.startsWith(Te)),ht=B.ignores(`${le}/`)||D.some((Te)=>Te.split(/[?*[\\]/)[0].startsWith(`${le}/`))||Et.includes(pe.name)||/(?:^|\/)(?:src|lib|apps|packages|tests|resources|public)(?:\/|$)/.test(le),xt=be&&(gt||Nn)&&!ht;if(pe.name==="vendor"&&ye)for(let Te of await er(Oe(j,le),{withFileTypes:!0})){if(["autoload.php","composer","bin"].includes(Te.name))continue;if(!Te.isDirectory()){ye=!1;break}for(let Yt of await er(Oe(j,le,Te.name)))if(!Pt.has(`${Te.name}/${Yt}`))ye=!1}let ot=Tn.includes(pe.name)&&(pe.name==="node_modules"||pe.name==="vendor"&&ye&&!/"type"\s*:\s*"path"/.test(Se??"")),Fn=Q.has(le)||de&&pe.name.endsWith(".egg-info");if(((pe.name==="node_modules"||pe.name==="vendor"?ot:ft.has(pe.name))||tr.has(le)&&!ht||["logs","runtime","tmp"].includes(pe.name)||xt||Fn)&&!W(le)&&await V(le,ot||xt||Fn,ft.has(pe.name)||tr.has(le))){L.push(`/${le}/`);continue}if(!be&&!["node_modules","vendor"].includes(pe.name))await G(le,ft.has("__pycache__")?["__pycache__"]:[],de)}else if(pe.isFile()&&(vi.test(pe.name)||(await Jt(Oe(j,le))).size>O.maxFileBytes)&&!W(le)&&await V(le,!1))L.push(`/${le}`)}};await G("");let oe=N.includes(`\r
321
+ `)?`\r
322
+ `:`
323
+ `,ue=[bi,...L.sort(),ys,""].join(oe),ee=F.before+(F.before&&!F.before.endsWith(`
324
+ `)?oe:"")+ue+F.after;if(O.write!==!1&&ee!==N){let q=await bl(Oe(j,".hlixignore-"));try{let te=Oe(q,"rules");await jl(te,ee,{mode:H?.mode??420});let de=await Jt(T).catch((fe)=>{if(fe.code==="ENOENT")return null;throw fe});if(de?!de.isFile()||de.ino!==H?.ino||de.dev!==H?.dev||await hs(T,"utf8")!==N:H!==null)return{warning:"Kept .hlixignore unchanged: it changed while generated paths were being checked."};await kl(te,T)}finally{await Sl(q,{recursive:!0,force:!0})}}let Y=L.every((q)=>q.endsWith("/"))?"generated folders":"generated paths";return{rules:L,report:`Hlix ignored ${L.length} ${Y} — see .hlixignore`}}catch(H){return O.signal?.throwIfAborted(),{warning:`Kept .hlixignore unchanged: could not safely refresh generated paths (${H.code??"unreadable"}).`}}}import{readFile as xl}from"node:fs/promises";import{join as Cl}from"node:path";function $l(j){let O=j.trim();if(!O||/^[|>[{]/.test(O))return null;let T=O.match(/^(["'])([\s\S]*)\1$/);if(!T&&/^["']/.test(O))return null;return(T?T[2].trim():O.replace(/(?:^|\s)#.*$/,"").trim())||null}function Si(j){let O=j.split(/\r?\n/),T=O.findIndex((M)=>/^tasks:\s*(?:#.*)?$/.test(M));if(T===-1)return{tasks:[],partial:/^tasks:\s*\S/m.test(j)};let N=[],H=!1,F=-1;for(let M of O.slice(T+1)){if(!M.trim()||/^\s*#/.test(M))continue;let U=M.length-M.trimStart().length,L=M.match(/^(\s*-(?:\s+|$))(.*)$/);if(L){if(F!==-1&&U>=F)continue;if(N.push({}),F=L[2]?L[1].length:-1,!L[2])continue}else if(U===0)break;else if(N.length===0)continue;else if(F===-1)F=U;else if(U!==F)continue;let D=(L?L[2]:M.trim()).match(/^([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/);if(!D)continue;let B=D[1];if(B!=="name"&&B!=="before"&&B!=="init"&&B!=="command")continue;let z=$l(D[2]);if(z===null)H=!0;else N[N.length-1][B]=z}return{tasks:N,partial:H}}async function kt(j,O){try{return await xl(Cl(j,...O.split("/")),"utf8")}catch(T){if(T.code==="ENOENT")return null;throw T}}function ji(j){try{let O=j.replace(/(^|[^:\\])\/\/.*$/gm,"$1").replace(/\/\*[\s\S]*?\*\//g,"").replace(/,\s*([}\]])/g,"$1");return JSON.parse(O)}catch{return null}}function pt(j){if(typeof j==="string"&&j.trim())return[j.trim()];if(Array.isArray(j))return j.flatMap(pt);if(j&&typeof j==="object")return Object.values(j).flatMap(pt);return[]}function vs(j){if(!j||typeof j!=="object")return[];return Object.keys(j).filter((O)=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(O))}function Il(j,O){let T=new Set,N=[/\bprocess\.env\.([A-Za-z_][A-Za-z0-9_]*)/g,/\bimport\.meta\.env\.([A-Za-z_][A-Za-z0-9_]*)/g,/\bos\.(?:getenv|environ\.get)\(\s*["']([A-Za-z_][A-Za-z0-9_]*)/g,/\bos\.Getenv\(\s*["']([A-Za-z_][A-Za-z0-9_]*)/g,/\bENV\[\s*["']([A-Za-z_][A-Za-z0-9_]*)/g];if(O)N.push(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::[-?][^}]*)?\}/g);for(let H of N)for(let F of j.matchAll(H))T.add(F[1]);return[...T]}function _l(j,O){if(j.has("bun.lock")||j.has("bun.lockb")||O?.startsWith("bun@"))return"bun install";if(j.has("pnpm-lock.yaml")||O?.startsWith("pnpm@"))return"pnpm install";if(j.has("yarn.lock")||O?.startsWith("yarn@"))return"yarn install";if(j.has("package.json"))return"npm install";return null}function Pi(j){let O=typeof j==="number"?j:Number(j);return Number.isInteger(O)&&O>0&&O<=65535?O:null}function Fe(j,O,T){if(!j.some((N)=>N.path===O&&N.kind===T))j.push({path:O,kind:T})}async function Ei(j,O,T){let N=[],H=[],F=[],M=[],U=new Map,L=new Set,D=new Set,B=[],z={},J=null,K=0,X=await kt(j,".cursor/environment.json");if(X){Fe(N,".cursor/environment.json","cursor");let ee=ji(X);if(!ee)B.push("Could not parse .cursor/environment.json; it remains quarantined.");else{H.push(...pt(ee.install));let Y=pt(ee.start);if(Y[0])J=Y[0];if(Array.isArray(ee.terminals))for(let q of ee.terminals){if(!q||typeof q!=="object")continue;let te=q;if(typeof te.command!=="string"||!te.command.trim())continue;M.push({name:typeof te.name==="string"&&te.name.trim()?te.name.trim():"Terminal",command:te.command.trim(),...typeof te.cwd==="string"&&te.cwd.trim()?{cwd:te.cwd.trim()}:{}})}}}let W=O.has(".devcontainer/devcontainer.json")?".devcontainer/devcontainer.json":O.has("devcontainer.json")?"devcontainer.json":null;if(W){Fe(N,W,"devcontainer");let ee=ji(T.get(W)??await kt(j,W)??"");if(!ee)B.push(`Could not parse ${W}; it remains quarantined.`);else{H.push(...pt(ee.onCreateCommand),...pt(ee.updateContentCommand),...pt(ee.postCreateCommand));let Y=pt(ee.postStartCommand);if(!J&&Y[0])J=Y[0];for(let q of vs(ee.secrets))L.add(q);for(let q of[...vs(ee.containerEnv),...vs(ee.remoteEnv)])L.add(q);if(Array.isArray(ee.forwardPorts))for(let q of ee.forwardPorts){let te=Pi(q);if(te)U.set(te,{port:te,visibility:"private"})}}}if(O.has(".gitpod.yml")){Fe(N,".gitpod.yml","gitpod");let ee=T.get(".gitpod.yml")??await kt(j,".gitpod.yml");if(ee===null)B.push("Could not read .gitpod.yml; its task commands were not imported.");else{let Y=Si(ee);K=Y.tasks.filter((q)=>q.before).length;for(let q of Y.tasks){if(q.before)H.push(q.before);if(q.init)H.push(q.init);if(!q.command)continue;if(!J)J=q.command;else M.push({name:q.name??"Terminal",command:q.command})}if(Y.partial)B.push("Some .gitpod.yml task values are not plain `key: value` scalars and were not imported; review .gitpod.yml before approving cloud setup.")}}for(let ee of["Dockerfile","docker-compose.yml","docker-compose.yaml","compose.yml","compose.yaml"])if(O.has(ee))Fe(N,ee,"docker");for(let ee of["project.toml","nixpacks.toml","railpack.json","Aptfile"])if(O.has(ee))Fe(N,ee,"buildpack");for(let ee of["fly.toml","railway.json","render.yaml","vercel.json","netlify.toml"])if(O.has(ee))Fe(N,ee,"platform");let V=T.get("package.json")??await kt(j,"package.json");if(V){Fe(N,"package.json","package");try{let ee=JSON.parse(V);if(ee.engines?.node)z.node=ee.engines.node;let Y=_l(O,ee.packageManager);if(Y&&H.length===K)H.push(Y);if(ee.scripts?.build&&F.length===0)F.push(`${ee.packageManager?.split("@")[0]??(O.has("bun.lock")?"bun":"npm")} run build`);let q=ee.scripts?.dev?`${O.has("bun.lock")?"bun":"npm"} run dev`:null,te=ee.scripts?.start?`${O.has("bun.lock")?"bun":"npm"} run start`:q;if(!J&&te)J=te}catch{B.push("Could not parse package.json for environment discovery.")}}if(O.has("uv.lock"))H.push("uv sync --frozen");else if(O.has("poetry.lock"))H.push("poetry install --no-interaction");else if(O.has("requirements.txt"))H.push("python -m pip install -r requirements.txt");if(O.has("go.mod"))H.push("go mod download");if(O.has("Procfile")){Fe(N,"Procfile","procfile");let Y=(T.get("Procfile")??"").split(/\r?\n/).find((q)=>/^web\s*:/.test(q));if(Y)J=Y.replace(/^web\s*:\s*/,"").trim()||J}let Q=[[".node-version","node"],[".nvmrc","node"],[".python-version","python"]];for(let[ee,Y]of Q){let q=(T.get(ee)??await kt(j,ee))?.trim();if(q)z[Y]=q,Fe(N,ee,"tool-version")}let G=T.get(".tool-versions")??await kt(j,".tool-versions");if(G){Fe(N,".tool-versions","tool-version");for(let ee of G.split(/\r?\n/)){let[Y,q]=ee.trim().split(/\s+/,2);if(!q)continue;if(Y==="nodejs")z.node=q;else if(Y==="python")z.python=q;else if(Y==="bun")z.bun=q}}let oe=T.get("mise.toml")??await kt(j,"mise.toml");if(oe){Fe(N,"mise.toml","tool-version");for(let ee of oe.matchAll(/^\s*(node|python|bun)\s*=\s*["']([^"']+)["']/gm))z[ee[1]]=ee[2]}for(let[ee,Y]of T){let q=/(?:^|\/)(?:Dockerfile|Procfile)$/i.test(ee)||/\.(?:jsonc?|ya?ml|toml|ini|conf|config|env|sh|bash|zsh|fish)$/i.test(ee);for(let te of Il(Y,q))D.add(te);for(let te of Y.matchAll(/(?:--port(?:=|\s+)|PORT\s*=\s*)(\d{2,5})/g)){let de=Pi(te[1]);if(de)U.set(de,{port:de,visibility:"private"})}}if(N.length===0&&O.size>0)Fe(N,"repository","detected");let ue=(ee)=>[...new Set(ee.filter(Boolean))],ae=N.length+H.length+(J?1:0);return{sources:N.sort((ee,Y)=>ee.path.localeCompare(Y.path)),toolchain:z,install:ue(H),build:ue(F),start:J,terminals:M,ports:[...U.values()].sort((ee,Y)=>ee.port-Y.port),requiredSecretKeys:[...L].sort(),observedSecretKeys:[...D].sort(),confidence:ae>=4?"high":ae>=2?"medium":"low",warnings:B}}var $i=2;var Mi=300000,Ul=25000,xi=52428800,Dl=524288000,Sn=1e4,Bl="Potential secrets exist in Git history",zl="Never delete .git folders or files to get past this; use .hlixignore instead.",sr=1048576,wn=20971520,Li=[".git/",".hlix/","node_modules/",".next/",".turbo/",".cache/","dist/","build/","coverage/","__pycache__/",".venv/","venv/","target/",".DS_Store"],Wl=bn().add(Li);function Ui(j,O){return!zt(j,O)&&Wl.ignores(j)}var js="Required project environment value was not found locally: ",Jl=/(^|\/)\.env\.(example|sample|template)$/i,ql=/(^|\/)\.env(?:\.[^/]+)?$/i,Gl=/(^|\/)(?:\.envrc|\.netrc|\.npmrc|\.pypirc|credentials(?:\.[^/]+)?(?:\.json|\.toml)?|service-account[^/]*\.json|firebase-adminsdk[^/]*\.json|application_default_credentials\.json|\.docker\/config\.json|\.cargo\/credentials(?:\.toml)?|\.gem\/credentials|\.bundle\/config|(?:pip|pypi)\.conf|\.aws\/credentials|[^/]+\.(?:pem|key|p12|pfx)|[^/]*\.(?:auto\.)?tfvars(?:\.json)?|application[^/]*\.(?:properties|ya?ml)|(?:local|keystore|gradle|secrets?)\.properties|appsettings[^/]*\.json|local\.settings\.json|config\/database\.ya?ml|wrangler\.toml|fly\.toml|serverless\.ya?ml|(?:credentials|secrets?)[^/]*\.(?:json|ya?ml|toml|ini|conf|cfg))$/i,Kl=/\.(?:example|sample|template)$/i,Vl=/(^|\/)\.(?:npmrc|yarnrc(?:\.yml)?|pypirc)$/i,Yl=/(?:^|\/)(?:__tests__|tests?|fixtures)\/|\.(?:test|spec)\.[^/]+$|\.snap$/i,Xl=/\.(?:md|mdx|txt|rst)$/i,Zl=/fake|dummy|example|placeholder|unused|changeme|xxxx|redacted|your[_-]|<[^>]*>/i,Ql=/^(.)\1+$/,ed=/RegExp\(/,Ps="BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY|npm_[A-Za-z0-9]{30,}|gh[opusr]_[A-Za-z0-9_]{30,}|AKIA[0-9A-Z]{16}|xox[baprs]-[A-Za-z0-9-]{20,}",td=new RegExp(Ps,"g"),nd=/(^|\/)(?:\.mcp\.json|mcp\.json|claude_desktop_config\.json)$/i,rd=/(^|\/)(?:AGENTS\.md|CLAUDE\.md|\.cursorrules|\.github\/copilot-instructions\.md)$/i,sd=/(^|\/)(?:\.agents|\.claude)\/skills\//i,Ss=/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----|npm_[A-Za-z0-9]{30,}|gh[opusr]_[A-Za-z0-9_]{30,}|glpat-[A-Za-z0-9_-]{20,}|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{30,}|(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}|xox[baprs]-[A-Za-z0-9-]{20,}/,kf=new RegExp(Ss.source,"g"),Ci=/\.(?:json|ya?ml|toml|ini|conf|config)$/i,Ii=/(?:^|[,{\s])(?:["']?(?:api[_-]?key|access[_-]?token|auth(?:orization)?|client[_-]?secret|password|private[_-]?key|secret|token)["']?)\s*(?::|=)\s*["']?(?!\$\{|process\.env|import\.meta\.env|os\.(?:getenv|environ\.get)|<|replace|example|changeme)[A-Za-z0-9+/_=.:-]{12,}/im,vn=new Set(["HLIX_AGENT_RUN_ID","HLIX_API_KEY","HLIX_API_URL","HLIX_BASE_URL","HLIX_PROJECT_ID","HLIX_SESSION_TOKEN","HLIX_WORKSPACE_ID"]),bs="Your hlix credentials were left out of the project's secrets — the platform provides them.",ks=new Set(["CI","HOME","LANG","LOGNAME","NODE_ENV","OLDPWD","PATH","PORT","PWD","SHELL","SHLVL","TERM","TMPDIR","USER","_"]),od=100,_i=12;function id(j){let O=j.slice(0,_i).join(", "),T=j.length-_i;return j.length===1?`Observed environment reference has no local value: ${j[0]}`:`${j.length} observed environment references have no local value: ${O}${T>0?`, +${T} more`:""}`}var ad=250;function ut(j){return j.split(Hl).join("/")}function Xe(j){if(j>=1048576)return`${(j/1048576).toFixed(1)} MB`;if(j>=1024)return`${(j/1024).toFixed(1)} KB`;return`${j} bytes`}function Ri(j,O=5){return[...j].sort((T,N)=>N.size-T.size||T.path.localeCompare(N.path)).slice(0,O).map((T)=>`${T.path} (${Xe(T.size)})`).join(", ")}function cd(j,O=5){let T=new Map;for(let N of j){let H=N.indexOf("/"),F=H===-1?".":N.slice(0,H);T.set(F,(T.get(F)??0)+1)}return[...T].sort((N,H)=>H[1]-N[1]||N[0].localeCompare(H[0])).slice(0,O).map(([N,H])=>`${N}/ (${H} files)`).join(", ")}function Me(j,O,T=10485760){return Ll("git",["-C",j,...O],{encoding:"utf8",timeout:Mi,maxBuffer:T,stdio:["ignore","pipe","pipe"]})}function c(j,O,T={}){return new Promise((N)=>{Ml("git",["-C",j,...O],{encoding:"utf8",timeout:Mi,maxBuffer:T.maxBuffer??10485760,...T.signal?{signal:T.signal}:{}},(H,F)=>{let M=H?.code;N({status:H===null?0:typeof M==="number"?M:1,stdout:typeof F==="string"?F:""})})})}async function ld(j){let O=jn("sha256");for await(let T of Rl(j))O.update(T);return O.digest("hex")}function Ze(j){if(Array.isArray(j))return`[${j.map(Ze).join(",")}]`;if(j&&typeof j==="object")return`{${Object.entries(j).sort(([O],[T])=>O.localeCompare(T)).map(([O,T])=>`${JSON.stringify(O)}:${Ze(T)}`).join(",")}}`;return JSON.stringify(j)}function Di(j){let O={};for(let[T,N]of String(j).replace(/^\uFEFF/,"").split(/\r?\n/).entries()){let H=N.trim();if(!H||H.startsWith("#"))continue;let M=(H.startsWith("export ")?H.slice(7).trimStart():H).match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);if(!M)throw Error(`Invalid dotenv assignment on line ${T+1}`);let U=M[2]??"";if(U.startsWith('"')){if(!U.endsWith('"'))throw Error(`Unclosed dotenv quote on line ${T+1}`);U=U.slice(1,-1).replace(/\\n/g,`
325
+ `).replace(/\\r/g,"\r")}else if(U.startsWith("'")){if(!U.endsWith("'"))throw Error(`Unclosed dotenv quote on line ${T+1}`);U=U.slice(1,-1)}else U=U.replace(/\s+#.*$/,"").trimEnd();O[M[1]]=U}return O}function dd(j,O){return j.split(/(?<=\n)/).filter((T)=>{let N=T.trim(),F=(N.startsWith("export ")?N.slice(7).trimStart():N).match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=/)?.[1];return F===void 0||!O.has(F)}).join("")}function pd(j){let O=null;for(let T=0;T<j.length;T+=1){let N=j[T];if(N==="\\"&&O!=="single"){if(j[T+1]!=="$")return!0;T+=1;continue}if(N==="'"&&O!=="double"){O=O==="single"?null:"single";continue}if(N==='"'&&O!=="single"){O=O==="double"?null:"double";continue}if(O!=="single"&&(N==="$"||N==="`"))return!0;if(O===null&&(N==="<"||N===">")&&j[T+1]==="(")return!0}return O!==null}function ud(j){let O={},T=new Set,N=new Set;for(let H of String(j).replace(/^\uFEFF/,"").split(/\r?\n/)){let F=H.trim();if(!F||F.startsWith("#"))continue;let U=(F.startsWith("export ")?F.slice(7).trimStart():F).match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);if(!U)continue;let L=U[1],D=U[2]??"";if(T.add(L),pd(D)){delete O[L],N.add(L);continue}try{let z=Di(`${L}=${D}`)[L];if(z===void 0)throw Error("missing literal");O[L]=D.trimStart().startsWith("'")?z:z.replace(/\\\$/g,"$"),N.delete(L)}catch{delete O[L],N.add(L)}}return{values:O,keys:[...T].sort(),dynamicKeys:[...N].sort()}}async function md(j){let O=Me(j,["rev-parse","--show-toplevel"]);if(O.status!==0)return!1;try{return await Fi(O.stdout.trim())===j}catch{return!1}}function fd(j,O){if(!O)return new Set;let T=Me(j,["ls-files","-z"]);if(T.status!==0)throw Error("Could not enumerate tracked files.");return new Set(T.stdout.split("\x00").filter(Boolean).map(ut))}function gd(j,O){if(!O)return[];let T=Me(j,["config","--get-regexp","^remote\\..*\\.url$"]);if(T.status!==0)return[];let N=[];for(let H of T.stdout.split(`
326
+ `)){let F=H.trim();if(!F)continue;let M=/^remote\.(.*)\.url (.+)$/.exec(F);if(M)N.push({name:M[1],url:M[2]})}return N}function hd(j,O){if(!O)return{files:new Set,directories:[]};let T=Me(j,["ls-files","-z","--others","--ignored","--exclude-standard","--directory"]);if(T.status!==0)throw Error("Could not enumerate ignored files.");let N=new Set,H=[];for(let F of T.stdout.split("\x00").filter(Boolean)){let M=ut(F);if(M.endsWith("/"))H.push(M);else N.add(M)}return{files:N,directories:H}}async function Ai(j,O){let T=[],N=[],H=[],F="";for(let D of[".gitignore",".hlixignore"])try{let B=Pn(j,D),z=await Ni(B);if(D===".gitignore"&&z.isSymbolicLink()){N.push(D);continue}if(z.isFile()||z.isSymbolicLink())try{if(z.isSymbolicLink()&&!(await Hi(B)).isFile()){T.push(D);continue}let J=await kn(B,"utf8");if(D===".hlixignore")F=J;let K=D===".hlixignore"?yn(J):null;if(O&&K?.managed)J=J.replace(K.managed,O.join(`
327
+ `));H.push(J)}catch{T.push(D)}}catch(B){if(B.code!=="ENOENT")T.push(D)}let M=yn(F)?.managed??"",U=M?[".git/",".hlix/"]:Li,L=ws(F);return{hardMatcher:bn().add(L.length?[".git/",".hlix/"]:U),matcher:bn().add([...U,...H.flatMap((D)=>D.split(/\r?\n/))]),unignored:bn().add(L),managedMatcher:bn().add(O??M),hasManaged:Boolean(M),unreadable:T,symlinked:N}}function or(j){if(nd.test(j))return"mcp";if(sd.test(j))return"skill";if(rd.test(j))return"agent";return null}function ir(j){if(ql.test(j)&&!Jl.test(j))return"dotenv";if(Gl.test(j))return"credential";return null}function yd(j,O){if(O)return[ut(O)];let T=new Map([[".env",0],[".env.development",1],[".env.local",2],[".env.development.local",3]]),N=j.filter((H)=>T.has(St(H).toLocaleLowerCase("en-US"))).sort((H,F)=>H.slice(0,-St(H).length).localeCompare(F.slice(0,-St(F).length))||T.get(St(H).toLocaleLowerCase("en-US"))-T.get(St(F).toLocaleLowerCase("en-US")));return N.length>0?N:j.length===1?[...j]:[]}function wd(j,O){try{let T=JSON.parse(O);if(!T.mcpServers||typeof T.mcpServers!=="object")return[];return Object.entries(T.mcpServers).map(([N,H])=>{let F=H&&typeof H==="object"?H:{},M=F.type==="http"||F.type==="sse"||F.type==="stdio"?F.type:typeof F.command==="string"?"stdio":typeof F.url==="string"?"http":"unknown",U=F.env&&typeof F.env==="object"?F.env:{};return{sourcePath:j,name:N,transport:M,...typeof F.command==="string"?{command:F.command}:{},...Array.isArray(F.args)&&F.args.every((L)=>typeof L==="string")?{args:F.args}:{},...typeof F.url==="string"?{url:F.url}:{},envKeys:Object.keys(U).sort(),enabled:!1}})}catch{return[]}}function vd(j){let O=!1,T=!1;for(let N of j.split(/\r?\n/)){let H=N.trim();if(!H||H.startsWith("#")||H.startsWith(";")||H.startsWith("["))continue;let F=H.indexOf("=");if(F===-1)continue;let M=H.slice(0,F).trim().toLowerCase(),U=H.slice(F+1).trim().replace(/^["']|["']$/g,"");if(!U||/^\$(?:\{[^}]*\}|[A-Za-z_][A-Za-z0-9_]*)$/.test(U))continue;if(M.endsWith("_authtoken")||M.endsWith("_password"))return!0;if(M.endsWith("password"))T=!0;else if(M.endsWith("username"))O=!0}return O&&T}async function bd(j,O,T,N){if(Kl.test(T))return!1;if(!Vl.test(T))return!0;let H=await c(j,["show",`${O}:${T}`],{...N?{signal:N}:{}});return H.status===0&&vd(H.stdout)}function kd(j,O,T){let N=j.lastIndexOf("/",O),H=j.indexOf("/",T);return N!==-1&&H!==-1&&!/\s/.test(j.slice(N,O)+j.slice(T,H))}function Sd(j){if(Yl.test(j))return"test fixture";if(Xl.test(j))return"documentation or pattern definition";return null}function jd(j,O){let T=null;for(let N of j.split(/\r?\n/))for(let H of N.matchAll(O)){let F=H[0],M=H.index??0,U=ed.test(N)||kd(N,M,M+F.length)?"documentation or pattern definition":Zl.test(F)||Ql.test(F)?"placeholder value":null;if(U===null)return null;T??=U}return T}async function Pd(j,O,T,N){let H=Sd(T);if(H!==null)return H;let F=await c(j,["show",`${O}:${T}`],{...N?{signal:N}:{}});return F.status===0?jd(F.stdout,td):null}async function Oi(j,O,T){let N=[],H="unknown";for(let F of j.split(/\r?\n/)){if(F.startsWith("@@"))H=F.slice(2);else if(F.trim()){let M=ut(F.trim());if(await T(H,M))N.push({commit:H,path:M,reason:O})}if(N.length>=100)break}return N}async function Ti(j,O,T={}){if(!O)return{head:null,branch:null,refs:[],commitCount:0,complete:!0,findings:[],blockingFindings:[],waivedReasons:[]};let N=Me(j,["rev-parse","HEAD"]).stdout.trim()||null,H=Me(j,["symbolic-ref","--short","-q","HEAD"]),F=H.status===0?H.stdout.trim()||null:null,M=Number.parseInt(Me(j,["rev-list","--count","--all"]).stdout.trim(),10)||0,U=Me(j,["for-each-ref","--format=%(refname)%00%(objectname)","refs/heads","refs/tags"]),L=U.stdout.split(`
328
+ `).filter(Boolean).map((Q)=>{let[G,oe]=Q.split("\x00");return{name:G,oid:oe}}).filter(({name:Q,oid:G})=>/^refs\/(?:heads|tags)\/.+/.test(Q)&&/^[0-9a-f]{40,64}$/.test(G)).sort((Q,G)=>Q.name.localeCompare(G.name)),D=T.signal,B=D?{signal:D}:{};T.onProgress?.(`history: ${M} commit${M===1?"":"s"}…`);let z=["log","--all",`--max-count=${Sn}`,"--pretty=format:@@%H","--name-only"],J=await c(j,[...z,"--",".env",".env.*","*.pem","*.key",".npmrc","*.tfvars"],B),K=await c(j,["log","--all",`--max-count=${Sn}`,"-G",Ps,"--pretty=format:@@%H","--name-only"],B);D?.throwIfAborted();let X=new Map;for(let Q of[...await Oi(J.stdout,"sensitive-path",(G,oe)=>bd(j,G,oe,D)),...await Oi(K.stdout,"secret-pattern",async()=>!0)])X.set(`${Q.commit}:${Q.path}:${Q.reason}`,Q);let W=[...X.values()].slice(0,100),V=new Map;for(let Q of W){if(Q.reason!=="secret-pattern")continue;let G=await Pd(j,Q.commit,Q.path,D);if(G!==null)V.set(Q,G)}return T.onProgress?.(`history: ${M} commit${M===1?"":"s"} scanned`),{head:N,branch:F,refs:L,commitCount:M,complete:M<=Sn&&L.length<=1000&&U.status===0&&J.status===0&&K.status===0,findings:W,blockingFindings:W.filter((Q)=>!V.has(Q)),waivedReasons:[...V.values()]}}function Ed(j,O){let T=O?.XDG_CACHE_HOME??(O?.HOME?Pn(O.HOME,".cache"):null);if(!T)return null;return Pn(T,"hlix","history",`${jn("sha256").update(j).digest("hex")}.json`)}async function $d(j,O,T){let N=O?Ed(j,T.environment):null;if(!N)return Ti(j,O,T);let H=jn("sha256").update([Me(j,["for-each-ref","--format=%(refname)%00%(objectname)"]).stdout,Me(j,["rev-parse","HEAD"]).stdout,Me(j,["symbolic-ref","--short","-q","HEAD"]).stdout,Ps,String(Sn)].join("\x00")).digest("hex");try{let M=JSON.parse(await kn(N,"utf8"));if(M.key===H&&M.history)return T.onProgress?.(`history: ${M.history.commitCount} commits, unchanged since the last scan`),M.history}catch{}let F=await Ti(j,O,T);if(F.complete)try{await Al(Fl(N),{recursive:!0,mode:448}),await Nl(N,JSON.stringify({key:H,history:F}),{mode:384})}catch{}return F}async function Le(j,O={}){let T=await Fi(rr(j));if(!(await Hi(T)).isDirectory())throw Error("Import target must be a directory.");let N=await md(T),H=gd(T,N),F=fd(T,N),M=new Set(N?(await c(T,["ls-files","--stage","-z"])).stdout.split("\x00").filter((Z)=>Z.startsWith("160000 ")).map((Z)=>Z.slice(Z.indexOf("\t")+1)):[]),U=hd(T,N),L=[...new Set([...s(T)?.includedPaths??[],...O.include?[O.include]:[]].map((Z)=>Z.replace(/^\.\//,"").replace(/\/$/,"")))],D=await Ai(T),B=O.refreshIgnore||D.hasManaged?await ki(T,{write:O.refreshIgnore===!0,tracked:N?F:new Set((await c(T,["ls-files","-z"])).stdout.split("\x00").filter(Boolean)),includes:L,gitIgnored:U,signal:O.signal,maxFileBytes:O.maxFileBytes??xi,isRepository:async(Z)=>{let ie=await c(Pn(T,Z),["rev-parse","--show-toplevel"]);return ie.status===0&&rr(ie.stdout.trim())===rr(T,Z)},protectedPath:(Z,ie)=>Boolean(ir(Z)||!ie&&or(Z)),protectedContent:(Z,ie)=>Ss.test(ie)||Ci.test(Z)&&Ii.test(ie)}):void 0,{hardMatcher:z,matcher:J,unignored:K,managedMatcher:X,unreadable:W,symlinked:V}=B?await Ai(T,B.rules??[]):D,Q=W.length?`Upload left unchanged: cannot read ${W.join(", ")}; check the ignore file target and permissions before retrying.`:void 0,G=[],oe=[],ue=[],ae=[],ee=[],Y=[],q=[],te=[],de=O.envFile?ut(nr(T,rr(T,O.envFile))):void 0,fe=de!==void 0&&de!==""&&de!==".."&&!de.startsWith("../");if(O.envFile&&!fe)te.push(`Selected environment file must stay inside the project: ${O.envFile}`);let ge=new Map,je=new Map,he=new Map,Se=new Map,ye=B?.warning?[B.warning]:[],Pt=new Set,Et=[],st=[],$t=new Map,Tn=O.maxFiles??Ul,ft=O.maxFileBytes??xi,pe=O.maxTotalBytes??Dl,le=O.historyMode==="sanitize",be=0,gt=0,Nn=async(Z,ie=!1)=>{let ke=await Ol(Z,{withFileTypes:!0}).catch((Ce)=>{let _e=ut(nr(T,Z))||"repository";if(q.push({path:_e,reason:`Cannot read folder (${Ce.code??"unreadable"}); check read and search permissions`}),ye.push(`Cannot read folder ${_e}; check its read and search permissions. Existing cloud files are preserved.`),Z===T)Q="Upload left unchanged: cannot read the project folder; check its permissions.";return[]});ke.sort((Ce,_e)=>Ce.name.localeCompare(_e.name));for(let Ce of ke){if(O.signal?.throwIfAborted(),gt+=1,gt%ad===0)O.onProgress?.(`scanning … ${G.length} files`);let _e=Pn(Z,Ce.name),ce=ut(nr(T,_e));if(Ce.name===".git"){if(ce!==".git"&&!ie)Pt.add(ut(nr(T,Z)));continue}if(ce.length>1000||ce.includes("\\")||ce.includes("\x00")){ye.push(`Skipped a path that cannot be represented safely: ${ce.slice(0,350)}`);continue}try{let $e=await Ni(_e),Xt=Ce.isDirectory()?`${ce}/`:ce,uo=F.has(ce)&&!M.has(ce),Zt=!(zt(ce,L)||K.ignores(Xt))&&!uo&&(J.ignores(Xt)||U.files.has(ce)||U.directories.some((we)=>Xt.startsWith(we))),mo=!gn(ce,L)&&z.ignores(Xt);if(mo){if(ce!==".hlix")q.push({path:ce,reason:"built-in ignore"});continue}if(Zt&&X.ignores(Xt))q.push({path:ce,reason:"Hlix-managed ignore"});if($e.isSymbolicLink()){if(Zt)continue;if(oe.push({path:ce,target:await Tl(_e)}),or(ce)||ir(ce))ue.push(ce);continue}if(Ce.isDirectory()){if(mo)continue;if(M.has(ce)&&!Zt)Pt.add(ce);await Nn(_e,Zt);continue}let Ct=or(ce),It=ir(ce);if(Zt&&!Ct&&!It)continue;if(!Ce.isFile()){q.push({path:ce,reason:"non-regular-file"});continue}if($e.size>ft&&!Ct&&!It){q.push({path:ce,reason:hn(ce)});continue}if($e.size>ft){te.push(`File ${ce} is ${Xe($e.size)}, over the ${Xe(ft)} per-file limit. Exclude it with .hlixignore.`);continue}let Qt=await ld(_e);if(Ct){if($e.size>sr){te.push(`Protected configuration ${ce} is ${Xe($e.size)}, over the ${Xe(sr)} per-file limit. Move the large content out of it, or exclude it with .hlixignore.`);continue}let we=await kn(_e);if(be+=we.byteLength,st.push({path:ce,size:we.byteLength}),be>wn)continue;if(ee.push({path:ce,kind:Ct,size:$e.size,sha256:Qt}),Et.push({path:ce,kind:Ct,contentBase64:we.toString("base64")}),Ct==="mcp")Y.push(...wd(ce,we.toString("utf8")));continue}if(It){if($e.size>sr){te.push(`Protected file ${ce} is ${Xe($e.size)}, over the ${Xe(sr)} per-file limit. Move the large content out of it, or exclude it with .hlixignore.`);continue}let we=await kn(_e);if(be+=we.byteLength,st.push({path:ce,size:we.byteLength}),be>wn)continue;let yt=[],_t=new Set;if(It==="dotenv")try{let Mn=Di(we),Rt={};for(let[it,At]of Object.entries(Mn)){if(vn.has(it)){_t.add(it);continue}Rt[it]=At}ge.set(ce,Rt),yt=Object.keys(Rt).sort()}catch{te.push(`Could not parse environment file: ${ce}`)}else if(St(ce)===".envrc"){let Mn=ud(we),Rt={},it=new Set,At=[];for(let[Re,Pa]of Object.entries(Mn.values)){if(vn.has(Re)){_t.add(Re);continue}if(ks.has(Re)){ye.push(`Ignored ambient runtime assignment in ${ce}: ${Re}`);continue}it.add(Re),Rt[Re]=Pa}je.set(ce,Rt);for(let Re of Mn.dynamicKeys){if(vn.has(Re)){_t.add(Re);continue}if(ks.has(Re)){ye.push(`Ignored ambient runtime assignment in ${ce}: ${Re}`);continue}it.add(Re),At.push(Re)}if(he.set(ce,[...it].sort()),Se.set(ce,At.sort()),yt=[...it].sort(),At.length>0)ye.push(`Did not execute dynamic .envrc assignments; collect their resolved local values when available: ${At.join(", ")}`)}if(_t.size>0)ye.push(bs),we=Buffer.from(dd(we.toString("utf8"),_t),"utf8"),Qt=jn("sha256").update(we).digest("hex");ae.push({path:ce,kind:It,keys:yt,size:we.byteLength,sha256:Qt}),Et.push({path:ce,kind:It,contentBase64:we.toString("base64")});continue}if($e.size<=1048576){let we=await kn(_e),yt=we.toString("utf8");if($t.set(ce,yt),Ss.test(yt)||Ci.test(ce)&&Ii.test(yt)){if(be+=we.byteLength,st.push({path:ce,size:we.byteLength}),be>wn)continue;ae.push({path:ce,kind:"detected-content",keys:[],size:$e.size,sha256:Qt}),Et.push({path:ce,kind:"detected-content",contentBase64:we.toString("base64")});continue}}G.push({path:ce,size:$e.size,sha256:Qt,tracked:uo,executable:($e.mode&73)!==0})}catch($e){if(O.signal?.throwIfAborted(),ir(ce)||or(ce))throw $e;q.push({path:ce,reason:`Cannot read file (${$e.code??"unreadable"})`})}}};await Nn(T);let ht=Zn([...G,...oe],Math.max(0,Tn-ae.length-ee.length),pe,L);if(ht.length)G=G.filter((Z)=>!Wt(Z.path,ht)),oe=oe.filter((Z)=>!Wt(Z.path,ht)),q.push(...ht.map((Z)=>({path:Z.replace(/\/$/,""),reason:hn(Z)})));if(O.onProgress?.(`scanning … ${G.length} files`),O.onProgress?.(`secrets: ${ae.length+ee.length} files`),O.signal?.throwIfAborted(),ue.length>0){let Z=ue.slice(0,5).join(", "),ie=ue.length-5;ye.push(`Imported as symlinks, so no content was read or uploaded for them and the cloud recreates the link: ${Z}${ie>0?`, +${ie} more`:""}`)}for(let Z of V)ye.push(`Ignore file ${Z} is a symlink, so its rules were not applied. Replace it with a regular file inside the project.`);if(Q)ye.push(Q);if(be>wn)te.push(`Protected project files total ${Xe(be)}, over the ${Xe(wn)} limit. Largest: ${Ri(st)}. Move large assets out of skill and config folders, or add them to .hlixignore.`);if(ae.length>2000)te.push(`Project has ${ae.length} environment and credential files, over the 2000 limit. Largest: ${Ri(ae)}. Exclude the ones the cloud project does not need with .hlixignore.`);if(ee.length>5000)te.push(`Project has ${ee.length} agent, skill and MCP files, over the 5000 limit. Largest folders: ${cd(ee.map((Z)=>Z.path))}. Exclude the ones the cloud project does not need with .hlixignore.`);G.sort((Z,ie)=>Z.path.localeCompare(ie.path)),oe.sort((Z,ie)=>Z.path.localeCompare(ie.path)),ae.sort((Z,ie)=>Z.path.localeCompare(ie.path)),ee.sort((Z,ie)=>Z.path.localeCompare(ie.path)),Y.sort((Z,ie)=>`${Z.sourcePath}:${Z.name}`.localeCompare(`${ie.sourcePath}:${ie.name}`));let xt=yd([...ge.keys()].sort(),fe?de:void 0);if(O.envFile&&fe&&!ge.has(xt[0]))te.push(`Selected environment file was not found or is not a dotenv file: ${O.envFile}`);let ot=new Map;for(let[Z,ie]of ge)for(let ke of Object.keys(ie))ot.set(ke,[...ot.get(ke)??[],Z]);for(let[Z,ie]of he)for(let ke of ie)ot.set(ke,[...ot.get(ke)??[],Z]);let Fn=[...ot].filter(([,Z])=>Z.length>1).map(([Z,ie])=>({key:Z,paths:ie.sort()})).sort((Z,ie)=>Z.key.localeCompare(ie.key)),De={};for(let Z of xt)Object.assign(De,ge.get(Z)??{});let Te=[...je.keys()].sort((Z,ie)=>{if(Z===".envrc")return 1;if(ie===".envrc")return-1;return Z.localeCompare(ie)}),Yt=new Set;for(let Z of Te){let ie=new Set(Se.get(Z)??[]);for(let ke of he.get(Z)??[]){if(ie.has(ke)){delete De[ke],Yt.add(ke);continue}let Ce=je.get(Z)?.[ke];if(Ce!==void 0)De[ke]=Ce;Yt.delete(ke)}}for(let Z of Pt)ye.push(`${Z} has its own Git repository — uploaded as files, its history not included`);let ba=O.historyMode==="abort_on_findings"?"abort_on_findings":"preserve";if(le)ye.push("Git history omitted; uploading a snapshot of the current files.");let Ne=await $d(T,N,O);if(!Ne.complete)ye.push(`Git history scan exceeded ${Sn} commits or failed; history is preserved, but the findings may be incomplete.`);if(N&&!Ne.head)le=!0,ye.push("Git has no readable HEAD; uploading the current files as a snapshot.");let io=Ne.waivedReasons;for(let Z of[...new Set(io)].sort()){let ie=io.filter((Ce)=>Ce===Z).length,ke=ie===1;ye.push(`${ie} Git history finding${ke?"":"s"} did not block this import — ${Z}, not ${ke?"a real credential":"real credentials"}; --history preserve is not needed for ${ke?"it":"them"}.`)}if(Ne.blockingFindings.length>0){let Z=Ne.blockingFindings.length;ye.unshift([`${Bl} (${Z} finding${Z===1?"":"s"}${Z>5?", first 5 shown":""}); ${le?"history is omitted":"history is preserved"}:`,...Ne.blockingFindings.slice(0,5).map((ie)=>` ${ie.commit.slice(0,7)} ${ie.path} — ${ie.reason}`)," To exclude old commits, use --history sanitize; local Git history stays intact."].join(`
329
+ `))}let ao=new Set(G.map((Z)=>Z.path)),ka=await Ei(T,ao,$t),{observedSecretKeys:Sa,...Be}=ka;Be.warnings.unshift(...ye);let Hn=new Set(Be.requiredSecretKeys);for(let Z of Yt)Hn.add(Z);for(let Z of Y)for(let ie of Z.envKeys)Hn.add(ie);for(let Z of vn)if(Hn.delete(Z))Be.warnings.push(bs);Be.requiredSecretKeys=[...Hn].sort();for(let Z of Be.requiredSecretKeys){if(De[Z]!==void 0)continue;let ie=O.environment?.[Z];if(ie===void 0){te.push(`${js}${Z}`);continue}De[Z]=ie}let kr=[];for(let Z of Sa){if(vn.has(Z)){Be.warnings.push(bs);continue}if(ks.has(Z))continue;if(De[Z]!==void 0)continue;let ie=O.environment?.[Z];if(ie===void 0){kr.push(Z);continue}De[Z]=ie}if(kr.length>0)Be.warnings.push(id(kr.sort()));Be.warnings=[...new Set(Be.warnings.flatMap((Z)=>Z.split(`
330
+ `)))].map((Z)=>Z.slice(0,500)).slice(0,od);let co=hi(new Map([...ao].map((Z)=>[Z,$t.get(Z)??null]))),lo={schemaVersion:$i,rootName:O.rootName??St(T),stack:co.language,git:{detected:N&&!le,head:le?null:Ne.head,branch:le?null:Ne.branch,refs:le?[]:Ne.refs,commitCount:le?0:Ne.commitCount,historyScanComplete:Ne.complete,historyMode:ba},files:G,symlinks:oe,secretFiles:ae,activeEnvFiles:xt,secretKeys:Object.keys(De).sort(),envCollisions:Fn,quarantinedResources:ee,mcpServers:Y,historicalSecretFindings:Ne.blockingFindings,skipped:Qn(q),environment:Be,totals:{files:G.length,bytes:G.reduce((Z,ie)=>Z+ie.size,0)}},po=Ze(lo),ja=jn("sha256").update(po).digest("hex");return{root:T,includedPaths:L,ignoreReport:O.refreshIgnore?B?.report??B?.warning:void 0,uploadWarning:Q,stackFacts:co,manifest:lo,...q.length>5000?{skippedEntries:q}:{},manifestJson:po,manifestSha256:ja,secretValues:De,protectedFiles:Et.sort((Z,ie)=>Z.path.localeCompare(ie.path)),blocking:[...new Set(te)].map((Z)=>`${Z}
331
+ ${zl}`),blockingHistoryFindings:[],gitRemotes:H}}var Es={name:"init",summary:"Configure a local folder for Hlix",usage:["Usage: hlix init [folder] [--project <id>] [--json]","","Creates .hlix/config.json, .hlix/.gitignore, and .hlixignore.","Project configuration is safe to commit; local revision state is ignored.",""," --project <id> Bind the folder to an existing cloud project"," Then `hlix pull`, or `hlix push` if it has no files yet"].join(`
332
+ `),supportsJson:!0,options:["project"],args:{min:0,max:1},async run(j){if(j.args.length>1)throw Error("init accepts at most one folder.");let O=await xd(Cd(j.cwd,j.args[0]??".")),T=r({env:j.env,flags:j.flags,cwd:O});if(T.conflict)throw new e("workspace_mismatch",T.conflict);if(!T.workspaceId)throw Error("No workspace selected. Run `hlix auth login --workspace <id>` first.");let N=j.requireClient(O);await N.projects.list();let H=at(O),F=typeof j.flags.project==="string"?j.flags.project:void 0;if(F&&H?.projectId&&H.projectId!==F)throw new e("workspace_mismatch",`This folder is bound to project ${H.projectId}; refusing to rebind it to ${F}.`);if(F)await N.projects.get(F);let M={...H??{schemaVersion:1,workspaceId:T.workspaceId,apiUrl:T.baseUrl},...F?{projectId:F}:{}};wt(O,M);let U=await Le(O,{environment:j.env,refreshIgnore:!0}),L={root:O,config:M,ignoreReport:U.ignoreReport,scan:{files:U.manifest.totals.files,bytes:U.manifest.totals.bytes,secretFiles:U.manifest.secretFiles.map((D)=>D.path),quarantinedResources:U.manifest.quarantinedResources.map((D)=>D.path),blocking:U.blocking}};if(j.json)j.stdout(ne(re(Es.name,L)));else{if(U.ignoreReport)j.stdout(`${U.ignoreReport}
333
+ `);if(j.stdout(`Initialized ${O}
334
+ Project: ${M.projectId??"not imported yet"}
335
+ Workspace: ${M.workspaceId}
336
+ `),U.blocking.length)j.stdout(`
337
+ Review before import:
338
+ ${U.blocking.map((D)=>`- ${D}`).join(`
339
+ `)}
340
+ `)}return 0}};import{randomUUID as tp}from"node:crypto";import{constants as np,existsSync as ur,readFileSync as rp,rmSync as rt,rmdirSync as sp}from"node:fs";import{copyFile as op,readFile as ia,realpath as ip}from"node:fs/promises";import{basename as ap,join as xe,relative as As,resolve as pr}from"node:path";import{createHash as Id}from"node:crypto";import{constants as ar}from"node:fs";import{chmod as Bi,copyFile as _d,lstat as $s,mkdir as Rd,mkdtemp as Ad,open as Od,realpath as Td,rename as Nd,rm as jt,symlink as Fd,writeFile as Hd}from"node:fs/promises";import{tmpdir as Md}from"node:os";import{dirname as qi,join as Qe,relative as Ld,resolve as Ud,sep as zi}from"node:path";import{spawnSync as Dd}from"node:child_process";var Bd=300000;function cr(j){let O=j;if(typeof O==="string")try{O=JSON.parse(O)}catch{return{}}if(!O||typeof O!=="object")return{};let T=O,N=T.git&&typeof T.git==="object"?T.git:{},H=N.historyMode==="preserve"||N.historyMode==="abort_on_findings"?N.historyMode:void 0,F=typeof T.rootName==="string"&&T.rootName.trim()?T.rootName:void 0;return{historyMode:H,rootName:F}}function Gi(j,O){let T=j;if(typeof T==="string")try{T=JSON.parse(T)}catch{return[]}if(!T||typeof T!=="object")return[];let N=T[O];if(!Array.isArray(N))return[];return N.filter((H)=>!!H&&typeof H==="object")}function Ki(j){return Gi(j,"files").flatMap((O)=>typeof O.path==="string"&&typeof O.sha256==="string"?[{path:O.path,sha256:O.sha256}]:[])}function xs(j){return Gi(j,"symlinks").flatMap((O)=>typeof O.path==="string"&&typeof O.target==="string"?[{path:O.path,target:O.target}]:[])}function En(j,O){let T=Dd("git",["-C",j,...O],{encoding:"utf8",timeout:Bd,maxBuffer:52428800,stdio:["ignore","pipe","pipe"]});if(T.status!==0)throw Error(T.stderr.trim().split(`
341
+ `).at(-1)??"Git command failed");return T.stdout.trim()}function Wi(j){return Id("sha256").update(j).digest("hex")}async function qt(j,O,T){let N=await Td(j),H=Ud(N,...O.split("/"));if(H!==N&&!H.startsWith(N+zi))throw Error(`Protected path escapes the project: ${O}`);let F=Ld(N,qi(H)),M=N;for(let U of F.split(zi).filter(Boolean)){M=Qe(M,U);try{let L=await $s(M);if(L.isSymbolicLink()&&T){T.push(M);break}if(!L.isDirectory()||L.isSymbolicLink())throw Error(`Protected path crosses a non-directory: ${O}`)}catch(L){if(L.code!=="ENOENT")throw L;if(!T)await Rd(M,{mode:448})}}return H}async function Ji(j,O,T){let N=await qt(j,O);try{let M=await $s(N);if(!M.isFile()||M.isSymbolicLink())throw Error(`Refusing to replace non-regular protected file: ${O}`)}catch(M){if(M.code!=="ENOENT")throw M}let H=Qe(qi(N),`.hlix-pull-${crypto.randomUUID()}.tmp`),F=await Od(H,ar.O_WRONLY|ar.O_CREAT|ar.O_EXCL|ar.O_NOFOLLOW,384);try{await F.writeFile(T),await F.sync()}finally{await F.close()}try{await Nd(H,N)}catch(M){throw await jt(H,{force:!0}),M}}async function zd(j,O,T){let N=T.length,H=await qt(j,O,T);if(T.length>N)return;try{let F=await $s(H);if(F.isSymbolicLink()){T.push(H);return}if(!F.isFile())throw Error(`Refusing to replace non-regular project file: ${O}`)}catch(F){if(F.code!=="ENOENT")throw F}}async function lr(j,O,T,N,H){let F=await Ad(Qe(Md(),"hlix-pull-"));await Bi(F,448);let M=Qe(F,"project.bundle"),U=Qe(F,"checkout");try{let L=Buffer.from(await N.arrayBuffer());if(L.byteLength!==T.bundleSize||Wi(L)!==T.bundleSha256)throw Error("Downloaded revision bundle failed integrity verification.");if(await Hd(M,L,{mode:384}),En(F,["clone","--no-hardlinks","--branch","main",M,U]),En(U,["bundle","verify",M]),En(U,["rev-parse","HEAD"])!==T.commitSha)throw Error("Downloaded revision bundle does not match the cloud commit.");let D=T.manifest,B=new Map;for(let W of[...D.secretFiles,...D.quarantinedResources])B.set(W.path,W);if(H&&H.files.length!==B.size)throw Error("Cloud protected files do not match the revision manifest.");let z=new Map;for(let W of H?.files??[]){let V=B.get(W.path),Q=Buffer.from(W.contentBase64,"base64");if(Q.toString("base64").replace(/=+$/,"")!==W.contentBase64.replace(/=+$/,"")||!V||V.kind!==W.kind||Q.byteLength!==V.size||Wi(Q)!==V.sha256)throw Error(`Cloud protected file failed integrity verification: ${W.path}`);z.set(W.path,Q)}let J=xs(T.manifest),K=new Set([...D.files.map((W)=>W.path),...J.map((W)=>W.path),...O.manifest.secretFiles.map((W)=>W.path),...O.manifest.quarantinedResources.map((W)=>W.path),...z.keys()]),X=[];for(let W of[...K].sort())await zd(j,W,X);for(let[W,V]of z)await Ji(U,W,V);for(let W of[...new Set(X)].sort())await jt(W,{force:!0});if(O.manifest.git.detected){En(j,["fetch",M,"refs/heads/main"]),En(j,["reset","--hard","FETCH_HEAD"]);let W=new Set([...D.files.map((V)=>V.path),...J.map((V)=>V.path)]);for(let V of[...O.manifest.files,...O.manifest.symlinks])if(!W.has(V.path))await jt(Qe(j,...V.path.split("/")),{force:!0})}else{for(let W of[...O.manifest.files,...O.manifest.symlinks])await jt(Qe(j,...W.path.split("/")),{force:!0});for(let W of D.files){let V=await qt(j,W.path);await _d(Qe(U,...W.path.split("/")),V),await Bi(V,W.executable?493:420)}for(let W of J){let V=await qt(j,W.path);await jt(V,{force:!0}),await Fd(W.target,V)}}if(H){for(let W of[...O.manifest.secretFiles,...O.manifest.quarantinedResources])if(!z.has(W.path))await jt(Qe(j,...W.path.split("/")),{force:!0})}for(let[W,V]of z)await Ji(j,W,V)}finally{await jt(F,{recursive:!0,force:!0})}}function Ee(j){return new Map([...Ki(j).map((O)=>[O.path,`blob:${O.sha256}`]),...xs(j).map((O)=>[O.path,`link:${O.target}`])])}function Gt(j,O,T){let N=Ee(T.manifest),H=Ee(j.manifest),F=0,M=0;for(let[L,D]of H){let B=N.get(L);if(B===void 0)F+=1;else if(B!==D)M+=1}let U=0;for(let L of N.keys())if(!H.has(L))U+=1;return{localChanged:!O.manifestSha256||j.manifestSha256!==O.manifestSha256,cloudChanged:T.id!==O.revisionId||T.generation!==O.generation,local:{revisionId:O.revisionId,generation:O.generation},cloud:{revisionId:T.id,generation:T.generation,commitSha:T.commitSha},files:{local:H.size,cloud:N.size,localOnly:F,cloudOnly:U,differing:M}}}function Cs(j,O,T){let{localChanged:N,cloudChanged:H}=O;if(j==="push")return H?"conflict":N?"push":"none";if(j==="pull"){if(!H)return"none";return N&&!T?"conflict":"pull"}if(N&&H)return"conflict";return N?"push":H?"pull":"none"}function Is(j,O,T){return j==="pull"&&O.localChanged&&!T}var Wd={push:{push:"Would push the local changes as a new cloud revision.",pull:"",none:"Nothing to push — local matches the last synced revision.",conflict:"Would refuse: the cloud changed since this folder's base revision."},pull:{push:"",pull:"Would replace local files with the cloud revision.",none:"Nothing to pull — the cloud head is the local base revision.",conflict:"Would refuse: local files changed. Re-run with --force to replace them."},sync:{push:"Would push the local changes as a new cloud revision.",pull:"Would pull the cloud revision into this folder.",none:"Already in sync.",conflict:"Would refuse: local and cloud both changed since the last sync."}};function Jd(j,O,T){if(O==="push"&&T.cloud.generation===0)return`Would push ${T.files.local} files as revision 1 — this project has no cloud revision yet.`;return Wd[j][O]}function Vi(j,O,T,N){let H=T.files;return[`${j} --dry-run: ${Jd(j,O,T)}`,...N?["Requires --yes (or interactive approval) to execute."]:[],"",ve([["local",`generation ${T.local.generation} (${T.local.revisionId})${T.localChanged?" — modified":""}`],["cloud",`generation ${T.cloud.generation} (${T.cloud.revisionId})${T.cloudChanged?" — ahead":""}`],["files",`${H.local} local, ${H.cloud} cloud — ${H.localOnly} local-only, ${H.cloudOnly} cloud-only, ${H.differing} differing`]])].join(`
342
+ `)}var qd=new Set(["https:","http:","ssh:","git:"]);function Yi(j,O){if(!j.trim())return null;let N=O.replace(/^\/+/,"").replace(/\/+$/,"").replace(/\.git$/i,"").split("/").filter(Boolean);if(N.length!==2)return null;let[H,F]=N;return{host:j.toLowerCase(),owner:H,name:F}}function Xi(j){let O=j.trim();if(!O)return null;if(!/^[a-zA-Z][a-zA-Z\d+.-]*:\/\//.test(O)){let N=/^(?:[^@/\s]+@)?([^:/\s]+):(.+)$/.exec(O);return N?Yi(N[1],N[2]):null}let T;try{T=new URL(O)}catch{return null}if(!qd.has(T.protocol))return null;return Yi(T.hostname,T.pathname)}function Zi(j){return j.host==="github.com"}function Qi(j){let O=j.find((T)=>T.name==="origin");if(O)return O;return j.length===1?j[0]:void 0}import{createHash as ra}from"node:crypto";import{createReadStream as Gd}from"node:fs";import{chmod as _s,copyFile as Kd,lstat as ea,mkdir as Rs,mkdtemp as Vd,readdir as Yd,readlink as Xd,rm as dr,symlink as Zd}from"node:fs/promises";import{tmpdir as Qd}from"node:os";import{dirname as ta,join as et}from"node:path";import{spawnSync as $n}from"node:child_process";var xn=300000;function Je(j,O){let T=$n("git",["-C",j,...O],{encoding:"utf8",timeout:xn,maxBuffer:20971520,stdio:["ignore","pipe","pipe"]});if(T.status!==0){let N=T.stderr.trim().split(`
343
+ `).at(-1)??"git command failed";throw Error(N)}return T.stdout.trim()}async function na(j){let O=ra("sha256");for await(let T of Gd(j))O.update(T);return O.digest("hex")}async function ep(j){for(let O of await Yd(j)){if(O===".git")continue;await dr(et(j,O),{recursive:!0,force:!0})}}async function Cn(j,O={}){if(j.uploadWarning)throw Error(j.uploadWarning);if(j.blocking.length>0)throw Error(`Project scan has blocking findings:
344
+ - ${j.blocking.join(`
345
+ - `)}`);let T=await Vd(et(Qd(),"hlix-snapshot-"));await _s(T,448);let N=et(T,"repo"),H=et(T,"source.git"),F=et(T,"project.bundle");try{if(j.manifest.git.detected){let K=$n("git",["clone","--mirror","--no-hardlinks",j.root,H],{encoding:"utf8",timeout:xn,stdio:["ignore","pipe","pipe"]});if(K.status!==0)throw Error(K.stderr.trim()||"Could not mirror repository.");let X=new Map(Je(H,["for-each-ref","--format=%(refname)%00%(objectname)","refs/heads","refs/tags"]).split(`
346
+ `).filter(Boolean).map((V)=>V.split("\x00",2)));for(let V of j.manifest.git.refs)if(X.get(V.name)!==V.oid)throw Error(`Git ref changed after scan: ${V.name}`);let W=$n("git",["clone","--no-hardlinks",H,N],{encoding:"utf8",timeout:xn,stdio:["ignore","pipe","pipe"]});if(W.status!==0)throw Error(W.stderr.trim()||"Could not create snapshot clone.");if(!j.manifest.git.head)throw Error("Git repository has no HEAD commit.");Je(N,["checkout","-B","main",j.manifest.git.head])}else await Rs(N,{recursive:!0,mode:448}),Je(N,["init","-b","main"]);await ep(N);for(let K of j.manifest.files){let X=et(j.root,...K.path.split("/")),W=await ea(X);if(!W.isFile()||W.isSymbolicLink())throw Error(`Source changed after scan: ${K.path}`);if(W.size!==K.size||await na(X)!==K.sha256)throw Error(`Source changed after scan: ${K.path}`);let V=et(N,...K.path.split("/"));await Rs(ta(V),{recursive:!0,mode:493}),await Kd(X,V),await _s(V,K.executable?493:420)}for(let K of j.manifest.symlinks){let X=et(j.root,...K.path.split("/"));if(await Xd(X).catch(()=>null)!==K.target)throw Error(`Source changed after scan: ${K.path}`);let W=et(N,...K.path.split("/"));await Rs(ta(W),{recursive:!0,mode:493}),await Zd(K.target,W)}Je(N,["config","user.name","Hlix Import"]),Je(N,["config","user.email","import@hlix.ai"]),Je(N,["read-tree","--empty"]),Je(N,["add","--force","-A"]),Je(N,["commit","--allow-empty","-m","chore(hlix): import snapshot"]);let M=Je(N,["rev-parse","HEAD"]),U=j.manifest.git.refs.filter((K)=>K.name!=="refs/heads/main");if(U.length>0){let K=$n("git",["-C",N,"update-ref","--stdin"],{encoding:"utf8",timeout:xn,input:U.map((X)=>`update ${X.name} ${X.oid}`).join(`
347
+ `)+`
348
+ `,stdio:["pipe","pipe","pipe"]});if(K.status!==0)throw Error(K.stderr.trim()||"Could not recreate the approved Git refs.")}let L=U.map((K)=>K.name),D=$n("git",["-C",N,"bundle","create",F,"--stdin"],{encoding:"utf8",timeout:xn,input:["refs/heads/main",...L].join(`
349
+ `)+`
350
+ `,stdio:["pipe","pipe","pipe"]});if(D.status!==0)throw Error(D.stderr.trim()||"Could not create the approved Git bundle.");Je(N,["bundle","verify",F]),await _s(F,384);let B=(await ea(F)).size,z=O.maxBundleBytes??524288000;if(B>z){if(j.manifest.git.detected)j.manifest.git={...j.manifest.git,detected:!1,head:null,branch:null,refs:[],commitCount:0},j.manifest.environment.warnings.push("Git history omitted to fit the upload limit; current files are preserved.");else{let K=[...j.manifest.files,...j.manifest.symlinks];if(!K.length)throw Error("The upload limit cannot fit an empty Git snapshot.");let X=Zn(K,Math.max(0,K.length-1),Math.floor(j.manifest.totals.bytes*z/B*0.9));j.manifest.files=j.manifest.files.filter((V)=>!Wt(V.path,X)),j.manifest.symlinks=j.manifest.symlinks.filter((V)=>!Wt(V.path,X));let W=[...j.skippedEntries??j.manifest.skipped,...X.map((V)=>({path:V.replace(/\/$/,""),reason:hn(V)}))];j.skippedEntries=W.length>5000?W:void 0,j.manifest.skipped=Qn(W),j.manifest.totals={files:j.manifest.files.length,bytes:j.manifest.files.reduce((V,Q)=>V+Q.size,0)}}return j.manifestJson=Ze(j.manifest),j.manifestSha256=ra("sha256").update(j.manifestJson).digest("hex"),await dr(T,{recursive:!0,force:!0}),Cn(j,O)}let J=await na(F);return{bundlePath:F,bundleSha256:J,bundleSize:B,commitSha:M,dispose:()=>dr(T,{recursive:!0,force:!0})}}catch(M){throw await dr(T,{recursive:!0,force:!0}),M}}function tt(j,O){let T=j[O];return typeof T==="string"&&T.trim()?T.trim():void 0}function cp(j){return[xe(j,".hlix","config.json"),xe(j,".hlix",".gitignore"),xe(j,".hlixignore")].filter((O)=>!ur(O))}function sa(j,O){for(let T of O)rt(T,{force:!0});if(O.length===0)return;try{sp(xe(j,".hlix"))}catch{}}var lp=44,oa=(j)=>`${j.padEnd(lp)}\r`;async function dp(j,O){let T=Qi(O);if(!T)return{kind:"none"};let N=Xi(T.url);if(!N)return{kind:"unresolved",remoteName:T.name,remoteUrl:T.url,reason:"could not be parsed as a repository URL"};if(!Zi(N))return{kind:"unresolved",remoteName:T.name,remoteUrl:T.url,reason:`not a GitHub repository (${N.host})`};let F=(await j.projects.list()).find((M)=>(M.repos??[]).some((U)=>U.owner.toLowerCase()===N.owner.toLowerCase()&&U.name.toLowerCase()===N.name.toLowerCase()));if(F)return{kind:"owned",owner:N.owner,name:N.name,projectId:F.id,projectName:F.name};return{kind:"connect",owner:N.owner,name:N.name}}function aa(j,O=!0){let{manifest:T}=j,N=[...T.secretFiles,...T.quarantinedResources].map((M)=>M.path),H=T.environment.warnings,F=(M)=>M.slice(0,8).join(", ")+(M.length>8?`, +${M.length-8} more (full list: hlix import --dry-run --json)`:"");return[`Uploaded: ${T.totals.files} files, ${T.symlinks?.length??0} links, ${T.totals.bytes} bytes, ${T.git.commitCount} commits${O?" (scan preview)":""}`,`Skipped: ${F(T.skipped.filter((M)=>M.reason!=="built-in ignore"&&M.reason!=="Hlix-managed ignore").map((M)=>`${M.path} (${M.reason})`))||"ignored paths"}`,`Secrets: ${N.length} files ${O?"to move":"moved"} encrypted${N.length?` (${F(N)})`:""}`,`Warnings: ${H.length?F(H):"none"}`,`Blocked: ${j.blocking.length?j.blocking.join(`
351
+ `):"none"}`].join(`
352
+ `)+`
353
+ `}function nt(j,O){if(j.json)j.stdout(ne(re(mt.name,{action:"none",warning:O})));else j.stdout(`${O}
354
+ `);return 0}function pp(j){let O=j.manifest.environment.install,T=j.manifest.secretFiles.length+j.manifest.quarantinedResources.length;if(O.length===0&&T===0&&j.manifest.secretKeys.length===0)return null;let N=["Hlix will upload this project and encrypted protected files to your selected workspace."];if(O.length>0)N.push("Detected cloud setup commands:",...O.map((H)=>`- ${H}`));if(j.manifest.secretKeys.length>0)N.push("Project secret keys available to cloud tasks:",...j.manifest.secretKeys.map((H)=>`- ${H}`));if(j.manifest.quarantinedResources.length>0)N.push("Quarantined resources (preserved but not activated):",...j.manifest.quarantinedResources.map((H)=>`- ${H.kind}: ${H.path}`));if(j.manifest.environment.warnings.length>0)N.push("Environment warnings:",...j.manifest.environment.warnings.map((H)=>`- ${H}`));return N.push("Setup runs inside the isolated Coding Workspace and may access project secrets."),N.join(`
355
+ `)}var mt={name:"import",summary:"Import a local project into your Hlix workspace",usage:["Usage: hlix import [folder] [options]","","Options:"," --attach If the origin repo already belongs to a project, bind this"," folder to it instead of importing as a new one (no prompt)"," --dry-run Scan and report without uploading"," --env-file <path> Override automatic development dotenv precedence"," --history <mode> preserve (default) or sanitize (current files only)"," --include <path> Include one ignored path (secrets still move encrypted)"," --name <name> Cloud project name (defaults to folder name)"," --no-connect-origin Never connect or check the local repo's origin remote"," --stack <stack> Override detected stack"," --yes Approve the reviewed upload and cloud setup"," --json Machine-readable output (never contains secret values)"].join(`
356
+ `),supportsJson:!0,options:["attach","dry-run","env-file","history","include","name","no-connect-origin","stack","yes"],args:{min:0,max:1},async run(j){if(j.args.length>1)throw Error("import accepts at most one folder.");let O=await ip(pr(j.cwd,j.args[0]??".")),T=r({env:j.env,flags:j.flags,cwd:O});if(T.conflict)return nt(j,`Import left the binding unchanged: ${T.conflict}`);if(!T.workspaceId||!T.credential)throw new e("workspace_required","No workspace selected. Run `hlix auth login` first.");let N=at(O),H=xe(O,".hlix","import.json");if(ur(H)&&j.flags["dry-run"]!==!0){let L;try{L=JSON.parse(rp(H,"utf8"))}catch{return nt(j,"Import left the saved session unchanged: recovery data could not be read. Preserve .hlix/import.json for recovery.")}if(!L||L.schemaVersion!==1||!L.request||!L.originPlan)return nt(j,"Import left the saved session unchanged: invalid recovery data. Preserve .hlix/import.json for recovery.");if(L.workspaceId!==T.workspaceId||L.apiUrl!==T.baseUrl)return nt(j,"Import left the saved session unchanged: it belongs to another workspace or API.");if(N?.projectId){let B=L.importId?await j.requireClient(O).imports.get(L.importId,{signal:j.signal}):void 0;if(N.projectId!==(B?.import.projectId??B?.import.requestedProjectId))return rt(H,{force:!0}),rt(xe(O,".hlix","import.bundle"),{force:!0}),nt(j,"Discarded a stale import session; kept this folder's current project binding.")}let D=await mp(j,{...L,root:O});if(D!==null)return D;j.flags.name??=L.request.name,j.flags.stack??=L.request.stack,j.flags.include??=L.include,j.flags["env-file"]??=L.envFile,j.flags.history??=L.sanitize?"sanitize":"preserve"}if(N?.projectId&&j.flags["dry-run"]!==!0){if(j.json)j.stdout(ne(re(mt.name,{action:"none",warning:"This folder is already imported; kept its binding. Use hlix push to upload changes."})));else j.stdout(`This folder is already imported; kept its binding. Use hlix push to upload changes.
357
+ `);return 0}let F=tt(j.flags,"history");if(F&&F!=="preserve"&&F!=="abort-on-findings"&&F!=="sanitize")throw Error("--history must be `preserve`, `sanitize`, or `abort-on-findings`.");let M=tt(j.flags,"include");if(M&&(As(O,pr(O,M))===".."||As(O,pr(O,M)).startsWith("../")||M.split(/[\\/]/).some((L)=>L===".git"||L===".hlix")))throw new e("invalid_usage","--include must name a path inside this folder, excluding .git and .hlix metadata.");if(M)j.flags.include=As(O,pr(O,M)).replaceAll("\\","/");let U=[];if(!N&&j.flags["dry-run"]!==!0)U=cp(O),wt(O,{schemaVersion:1,workspaceId:T.workspaceId,apiUrl:T.baseUrl});try{return await up(j,{root:O,workspaceId:T.workspaceId,apiUrl:T.baseUrl,historyFlag:F})}catch(L){if(j.signal?.aborted){if(!ur(H))sa(O,U);throw new e("cancelled","Import cancelled.")}if(L instanceof e&&L.code==="cancelled"){if(!ur(H))sa(O,U)}throw L}}};async function up(j,O){let{root:T,historyFlag:N}=O,H=j.json?void 0:(D)=>j.stderr(oa(D)),F=await Le(T,{refreshIgnore:j.flags["dry-run"]!==!0,...tt(j.flags,"env-file")?{envFile:tt(j.flags,"env-file")}:{},environment:j.env,historyMode:N==="sanitize"?"sanitize":"preserve",include:tt(j.flags,"include")?.replace(/^\.\//,"").replace(/\/$/,""),...H?{onProgress:H}:{},...j.signal?{signal:j.signal}:{}});if(H)j.stderr(`
358
+ `);if(!j.json&&F.ignoreReport)j.stderr(`${F.ignoreReport}
359
+ `);if(F.uploadWarning)return nt(j,F.uploadWarning);if(j.signal?.throwIfAborted(),j.flags["dry-run"]!==!0&&F.blocking.length===0){let D=pp(F);if(D&&j.flags.yes!==!0){if(j.json||!j.confirm)throw new e("approval_required","Import needs approval for protected files or cloud setup. Review with `hlix import --dry-run`, then repeat with `--yes`.");if(!await j.confirm(D))throw new e("cancelled","Import cancelled.")}}let M={kind:"none"};if(j.flags["dry-run"]!==!0&&F.blocking.length===0&&j.flags["no-connect-origin"]!==!0){if(M=await dp(j.requireClient(T),F.gitRemotes),M.kind==="owned"){let D=j.flags.attach===!0;if(!D&&!j.json&&j.flags.yes!==!0&&j.confirm){let B=[`Repository ${M.owner}/${M.name} is already attached to project "${M.projectName}" in this workspace.`,"This folder looks like a worktree or branch of that project.",`Attach this folder's work to "${M.projectName}" instead of creating a new project?`].join(`
360
+ `);if(D=await j.confirm(B),!D)j.stderr(`Continuing as a new, repo-less import.
361
+ `)}else if(!D&&!j.json)j.stderr(`Repository ${M.owner}/${M.name} belongs to project "${M.projectName}"; rerun with --attach to bind this folder to it.
362
+ `);if(D){wt(T,{schemaVersion:1,projectId:M.projectId,workspaceId:O.workspaceId,apiUrl:O.apiUrl});let B={root:T,projectId:M.projectId,projectName:M.projectName};if(j.json)j.stdout(ne(re(mt.name,B)));else j.stdout(`Attached ${T}
363
+ Project: ${M.projectName} (${M.projectId})
364
+ Run \`hlix pull\` to sync this folder.
365
+ `);return 0}}else if(M.kind==="connect"){if(!j.json)j.stderr(`Origin repository ${M.owner}/${M.name} detected — connecting it to this project.
366
+ `)}else if(M.kind==="unresolved"&&!j.json)j.stderr(`Origin remote '${M.remoteName}' (${M.remoteUrl}) was not connected: ${M.reason}.
367
+ `)}let U={root:T,name:tt(j.flags,"name")??ap(T),stack:tt(j.flags,"stack")??F.manifest.stack,files:F.manifest.totals.files,bytes:F.manifest.totals.bytes,symlinks:F.manifest.symlinks,activeEnvFiles:F.manifest.activeEnvFiles,secretKeys:F.manifest.secretKeys,protectedFiles:F.manifest.secretFiles.length+F.manifest.quarantinedResources.length,environment:F.manifest.environment,historicalSecretFindings:F.manifest.historicalSecretFindings,quarantinedResources:F.manifest.quarantinedResources,mcpServers:F.manifest.mcpServers,skipped:F.skippedEntries??F.manifest.skipped,blocking:F.blocking,manifestSha256:F.manifestSha256};if(j.flags["dry-run"]===!0){if(j.json)j.stdout(ne(re(mt.name,U)));else j.stdout(aa(F));return F.blocking.length?1:0}if(F.blocking.length)throw new e("scan_blocked",`Project scan blocked import:
368
+ - ${F.blocking.join(`
369
+ - `)}`,{findings:F.blockingHistoryFindings,fixtureFindings:0,blocking:F.blocking});j.signal?.throwIfAborted();let L;try{L=await Cn(F)}catch(D){j.signal?.throwIfAborted();let B=`Import left this folder unchanged because a consistent snapshot could not be built: ${D instanceof Error?D.message:"local files unavailable"}. Run hlix import again after local writes finish.`;if(j.json)j.stdout(ne(re(mt.name,{action:"none",warning:B})));else j.stdout(`${B}
370
+ `);return 0}try{j.signal?.throwIfAborted();let D=j.requireClient(T),B={schemaVersion:1,root:T,workspaceId:O.workspaceId,apiUrl:O.apiUrl,originPlan:M,include:tt(j.flags,"include")?.replace(/^\.\//,"").replace(/\/$/,""),envFile:tt(j.flags,"env-file"),sanitize:!F.manifest.git.detected,request:{idempotencyKey:tp(),name:U.name,stack:U.stack,defaultBranch:"main",historyMode:F.manifest.git.historyMode,manifest:F.manifest,manifestSha256:F.manifestSha256,bundleSha256:L.bundleSha256,bundleSize:L.bundleSize,commitSha:L.commitSha}};wt(T,at(T)),await op(L.bundlePath,xe(T,".hlix","import.bundle"),np.COPYFILE_EXCL),Ke(xe(T,".hlix","import.json"),B);let z=await D.imports.create(B.request);if(B.importId=z.import.id,B.upload=z.upload,Ke(xe(T,".hlix","import.json"),B),z.import.status==="pending_upload"){if(!z.upload)throw Error(`Import ${z.import.id} is ${z.import.status} but has no upload target.`);await D.imports.uploadBundle(z.upload,new Blob([Uint8Array.from(await ia(L.bundlePath))]),{signal:j.signal,onProgress:(K,X)=>{if(!j.json)j.stderr(oa(`uploading ${K}/${X} bytes`))}})}let J=z.import.status==="ready"?{import:z.import}:await D.imports.finalizeAndWait(z.import.id,{secrets:F.secretValues,protectedFiles:F.protectedFiles},{signal:j.signal});return mr(j,B,J.import)}finally{await L.dispose()}}async function mr(j,O,T){let{root:N,originPlan:H}=O,F=j.requireClient(N),M=T.projectId??T.requestedProjectId;if(!M||!T.revisionId||!T.generation)throw Error("Import completed without project revision metadata.");let U=at(N);if(U?.projectId&&U.projectId!==M)return rt(xe(N,".hlix","import.json"),{force:!0}),rt(xe(N,".hlix","import.bundle"),{force:!0}),nt(j,"Discarded a stale import session; kept this folder's current project binding.");if(H.kind==="connect")try{await F.projects.connectRepo(M,{owner:H.owner,name:H.name})}catch(D){if(!j.json){let B=D instanceof Error?D.message:String(D);j.stderr(`Origin repository ${H.owner}/${H.name} could not be connected: ${B}
371
+ `)}}wt(N,{schemaVersion:1,projectId:M,workspaceId:O.workspaceId,apiUrl:O.apiUrl}),ct(N,{schemaVersion:1,revisionId:T.revisionId,generation:T.generation,commitSha:O.request.commitSha,manifestSha256:O.request.manifestSha256,historyMode:O.request.manifest.git.historyMode,snapshotOnly:O.sanitize,includedPaths:O.include?[O.include]:[],rootName:O.request.manifest.rootName,files:Object.fromEntries(Ee(O.request.manifest))});let L={projectId:M,revisionId:T.revisionId,generation:T.generation,commitSha:O.request.commitSha,files:O.request.manifest.totals.files,bytes:O.request.manifest.totals.bytes};if(j.json)j.stdout(ne(re(mt.name,L)));else j.stderr(`
372
+ `),j.stdout(aa({manifest:O.request.manifest,blocking:[]},!1)+`Imported ${O.request.name}.
373
+ `);return rt(xe(N,".hlix","import.json"),{force:!0}),rt(xe(N,".hlix","import.bundle"),{force:!0}),0}async function mp(j,O){let{root:T}=O,N=j.requireClient(T),H=xe(T,".hlix","import.json");if(!j.json)j.stderr(`Resuming the saved import.
374
+ `);let F;if(O.importId)F=await N.imports.get(O.importId,{signal:j.signal});else{let D=await N.imports.create(O.request);O.upload=D.upload,F=D}if(O.importId=F.import.id,Ke(H,O),F.import.projectId||F.import.status==="ready")return mr(j,O,F.import);if(F.import.status==="finalizing"&&Date.parse(F.import.updatedAt)>Date.now()-900000){let D=await N.imports.waitUntilReady(O.importId,{signal:j.signal});return mr(j,O,D.import)}if(["pending_upload","uploaded","failed","expired"].includes(F.import.status)&&Date.parse(F.import.expiresAt)<=Date.now())return rt(xe(T,".hlix","import.bundle"),{force:!0}),rt(H,{force:!0}),j.stderr(`Saved import expired before completion; discarded its recovery state and starting a fresh import.
375
+ `),null;if(!["pending_upload","uploaded","finalizing"].includes(F.import.status))return nt(j,`Import left the saved session unchanged: the server reports ${F.import.status}. No replacement project was created.`);let M=await Le(T,{environment:j.env,historyMode:O.sanitize?"sanitize":O.request.historyMode,include:O.include,envFile:O.envFile,signal:j.signal});if(M.uploadWarning)return nt(j,M.uploadWarning);let U=(D)=>Ze([D.secretFiles,D.quarantinedResources,D.secretKeys]);if(U(M.manifest)!==U(O.request.manifest)||M.blocking.length)throw Error("Protected files changed since the pending import. Restore the reviewed files and rerun hlix import; the saved import has been preserved.");if(F.import.status==="pending_upload"){if(!O.upload)throw Error(`Import ${O.importId} has no saved upload target.`);await N.imports.uploadBundle(O.upload,new Blob([Uint8Array.from(await ia(xe(T,".hlix","import.bundle")))]),{signal:j.signal})}let L=await N.imports.finalizeAndWait(O.importId,{secrets:M.secretValues,protectedFiles:M.protectedFiles},{signal:j.signal});return mr(j,O,L.import)}import{spawnSync as fp}from"node:child_process";import{existsSync as gp,mkdirSync as hp,writeFileSync as yp}from"node:fs";import{dirname as wp}from"node:path";function vp(j){return j==="global"?["# My rules","","Hlix Code reads this file in every project you open, before the project's","own rules. Write how you want an agent to work with you: the tone, the","things to always do, the things to never do.",""].join(`
376
+ `):["# Project rules","","Hlix Code and every other coding agent that opens this repository read","this file. Write the rules that are true of THIS project: how to run its","tests, its conventions, what not to touch.",""].join(`
377
+ `)}function bp(j){return j.VISUAL?.trim()||j.EDITOR?.trim()||"vi"}var Os={name:"rules",summary:"Show or edit the rules files the coding agent reads",usage:["Usage: hlix rules [--edit] [--global] [--cwd <dir>] [--json]","","Without --edit it reports which files Hlix Code loads and how big they are.","","--edit opens one in $EDITOR, creating it with a short header if it does not","exist yet. --global edits your own rules (~/.hlix/AGENTS.md, read in every",`project); without it the project's file (${f.join(", then ")}).`].join(`
378
+ `),supportsJson:!0,options:["edit","global"],async run(j){let O=y({cwd:j.cwd,configDir:".hlix",env:j.env}),T=j.flags.global===!0;if(j.flags.edit===!0){if(j.json)throw new e("invalid_usage","`hlix rules --edit` opens an editor, so it has no --json form.");let N=T?Gr(j.env):qr(j.cwd,".hlix")?.path??`${j.cwd}/AGENTS.md`;if(!gp(N))hp(wp(N),{recursive:!0}),yp(N,vp(T?"global":"project"),"utf8"),j.stdout(`Created ${N}.
379
+ `);let H=bp(j.env),F=fp(H,[N],{stdio:"inherit"});if(F.error)throw new e("invalid_usage",`Could not run ${H}: ${F.error.message}`);return F.status??0}if(j.json){let N=(H)=>H?{path:H.path,characters:H.content.length}:null;return j.stdout(ne(re(Os.name,{user:N(O.global),project:N(O.project)}))),0}return j.stdout(`${w(O,j.cwd)}
380
+ `),0}};var Ts={name:"standards",summary:"Show the standards other agent tools left in this folder",usage:["Usage: hlix standards [--cwd <dir>] [--json]","","Reads the instruction files, skills, slash commands, MCP servers and","subagents this project already carries for Claude Code, Cursor, Windsurf,","Gemini, Codex, Cline, Copilot and VS Code, and shows where each came from.","Hlix Code loads all of it at startup; nothing has to be copied or rewritten.","","Server urls, headers and environment values are never printed."].join(`
381
+ `),supportsJson:!0,async run(j){let O=b(j.cwd,i(j.env),{env:j.env});if(j.json)return j.stdout(ne(re(Ts.name,{instructions:O.instructions.map((T)=>({path:T.path,source:T.source,scope:T.scope,characters:T.content.length,...T.note?{note:T.note}:{}})),skills:O.skills,commands:[...O.commands.map((T)=>({path:T.path,source:T.source,scope:T.scope})),...O.generatedCommands.map((T)=>({path:T.path,source:T.source,scope:T.scope,command:T.name}))],mcpServers:O.mcpServers.map((T)=>({path:T.path,source:T.source,scope:T.scope,name:T.name,transport:"command"in T.config?"stdio":"http"})),subagents:O.subagents.map((T)=>({path:T.path,source:T.source,scope:T.scope,name:T.name,description:T.description,...T.model?{model:T.model}:{}})),skipped:O.skipped}))),0;return j.stdout(ei(O,j.cwd)),0}};var la=(j)=>j instanceof Error?j.message:String(j),ca=(j)=>j.split(/\s*\n\s*/).join(" ").trim();async function x(j,O,T,N,H){try{let F=await Le(O,{historyMode:T,environment:j.env,rootName:N}),M=s(O)?.files,U=Ee(F.manifest);return{changedFiles:M?[...new Set([...Object.keys(M),...U.keys()])].filter((D)=>M[D]!==U.get(D)).length:null,files:F.manifest.totals.files,manifestSha256:F.manifestSha256,changed:H?F.manifestSha256!==H:null,blocking:F.blocking,error:null}}catch(F){return{changedFiles:null,files:null,manifestSha256:null,changed:null,blocking:[],error:la(F)}}}var Ns={name:"status",summary:"Show the workspace, folder binding, and local-vs-cloud drift",usage:["Usage: hlix status [--cwd <dir>] [--json]","","Reports the resolved workspace and API with the source that decided each,","whether this folder is bound to a project, and whether the working tree or","the cloud head has moved since the last sync. Every finding is a line in","the output, so the command itself always exits 0; only an argument error","(rejected before it runs) exits 2."].join(`
382
+ `),supportsJson:!0,async run(j){let O=r({env:j.env,flags:j.flags,cwd:j.cwd}),T=O.binding,N=T?s(T.root):null,H=T?await x(j,T.root,N?.snapshotOnly?"sanitize":N?.historyMode??"preserve",N?.rootName,N?.manifestSha256):null,F=null;if(T?.config.projectId&&O.credential&&!O.conflict)try{let D=(await j.requireClient().revisions.head(T.config.projectId)).revision;F={revisionId:D.id,generation:D.generation,changed:N?D.id!==N.revisionId||D.generation!==N.generation:null,error:null,errorMessage:null}}catch(D){F={revisionId:"",generation:0,changed:null,error:Ur(D).code,errorMessage:D instanceof Ve?"no cloud revision yet — `hlix push` uploads this folder as revision 1":la(D)}}let M=Zr(j.env),U={cwd:j.cwd,workspace:{id:O.workspaceId,source:O.workspaceSource},api:{baseUrl:O.baseUrl,source:O.baseUrlSource},credential:{present:O.credential!==null,source:O.credentialSource,path:O.credentialPath},conflict:O.conflict,project:T?{root:T.root,projectId:T.config.projectId??null,workspaceId:T.config.workspaceId,apiUrl:T.config.apiUrl}:null,revision:N?{id:N.revisionId,generation:N.generation,commitSha:N.commitSha}:null,local:H,cloud:F,install:{channel:M.running?.channel??null,path:M.running?.path??null,copies:M.copies.map(({path:D,channel:B})=>({path:D,channel:B})),duplicate:M.duplicate}};if(j.json)return j.stdout(ne(re(Ns.name,U))),0;let L=[["folder",j.cwd],["workspace",O.workspaceId?`${O.workspaceId} (from ${O.workspaceSource})`:"none — run `hlix auth login --workspace <id>`"],["api",`${O.baseUrl} (from ${O.baseUrlSource})`],["credential",u(O)??"none — run `hlix auth login`"],["project",T?T.config.projectId??`initialized at ${T.root}, not imported yet`:"none — run `hlix import .` to bind this folder"]];if(N)L.push(["revision",`generation ${N.generation} (${N.revisionId})`]);if(H){if(L.push(["local",H.error?`could not scan: ${H.error}`:H.changed===null?`${H.files} files, no synced base revision`:H.changed?`${H.files} files, modified since the last sync`:`${H.files} files, matches the last sync`]),H.blocking.length>0)L.push(["blocking",H.blocking.join("; ")])}if(F)L.push(["cloud",F.error==="not_found"?ca(F.errorMessage??F.error):F.error?`not checked — ${ca(F.errorMessage??F.error)}`:F.changed?`generation ${F.generation} available — run \`hlix pull\``:`generation ${F.generation}, up to date`]);if(O.conflict)L.push(["conflict",O.conflict]);if(M.running)L.push(["installed",Gn(M.running)]);if(M.duplicate)L.push(["duplicate",M.duplicate]);return j.stdout(`${ve(L)}
383
+ `),0}};import{spawnSync as da}from"node:child_process";var Fs={name:"terminal",summary:"Open a shell into the project's Coding Workspace",usage:["Usage: hlix terminal [project-id] [--print] [--web] [--json]","","With no id, the project this folder is bound to is used."," --print Show the ssh command and browser url instead of connecting"," --web Open the browser terminal instead of ssh"].join(`
384
+ `),supportsJson:!0,options:["print","web"],args:{min:0,max:1},async run(j){let O=j.args[0]??t(j.cwd)?.config.projectId;if(!O)throw new e("missing_argument","A project id is required, or run this inside a folder bound to a project.");let T=await j.requireClient().projects.terminal(O);if(j.json)return j.stdout(ne(re(Fs.name,T))),T.available?0:1;if(!T.available){let M=T.environmentState?` (environment: ${T.environmentState})`:"";throw new e("not_found",`${T.reason??"Terminal unavailable"}${M}`)}let N=j.flags.print===!0,H=j.flags.web===!0;if(N||H&&!T.webTerminalUrl||!H&&!T.sshCommand)return j.stdout(`${ve([["ssh",T.sshCommand??"not available"],["browser",T.webTerminalUrl??"not available"]])}
385
+ `),0;if(H){if(da(process.platform==="darwin"?"open":"xdg-open",[T.webTerminalUrl],{stdio:"ignore"}).status!==0)j.stdout(`${T.webTerminalUrl}
386
+ `);return 0}return da("sh",["-c",T.sshCommand],{stdio:"inherit"}).status??1}};import{rmSync as pa}from"node:fs";import{dirname as kp}from"node:path";var Hs={name:"uninstall",summary:"Remove this hlix if the installer put it here (keeps your login)",usage:["Usage: hlix uninstall [--yes] [--json]","","Removes the executable the one-line installer installed, and its notices.","Your login in ~/.config/hlix is kept. A copy installed with Homebrew or npm","is removed with that tool instead; this command names it."].join(`
387
+ `),supportsJson:!0,options:["yes"],async run(j){let O=Yr(j.env);if(!O||O.channel!=="installer")throw new e("invalid_request",O&&O.channel!=="unknown"?`This hlix was installed with ${O.channel==="homebrew"?"Homebrew":"npm"}. Remove it with: ${Xr(O)}`:"Only an hlix installed by the one-line installer can remove itself.");if(j.flags.yes!==!0){if(j.json||!j.confirm)throw new e("approval_required","Removing hlix needs approval. Repeat with `--yes`.");if(!await j.confirm(`Remove ${O.path}? Your login is kept.`))throw new e("cancelled","Uninstall cancelled.")}let T=Vr(j.env);pa(O.path,{force:!0}),pa(T,{recursive:!0,force:!0});let N=kp(ze(j.env));if(j.json)j.stdout(ne(re(Hs.name,{removed:[O.path,T],kept:N})));else j.stdout(`Removed ${O.path}
388
+ Your login in ${N} is kept.
389
+ `);return 0}};import{createHash as ua}from"node:crypto";import{relative as Sp,resolve as jp}from"node:path";import{readFile as Pp,realpath as Ep}from"node:fs/promises";function $p(j,O,T){return ua("sha256").update(`project-push-v1\x00${j}\x00${O}\x00${T}`).digest("hex")}var xp={schemaVersion:1,revisionId:"",generation:0,commitSha:""},_n={id:"",generation:0,commitSha:"",manifest:{}};async function Kt(j,O){try{return await j.revisions.head(O)}catch(T){if(T instanceof Ve)return null;throw T}}async function ma(j,O){let T=await Kt(j,O);if(T)return T;throw new e("not_found","This project has no cloud files yet, so there is nothing to pull or push against. Import the folder into a new project with `hlix import`, or create the first revision from the dashboard.")}async function Ue(j,{allowUnsynced:O=!1}={}){let T=t(j);if(!T?.config.projectId)throw new e("not_initialized","This folder is not bound to an imported Hlix project. Run `hlix import .` first.");let N=s(T.root)??(O?xp:null);if(!N)throw new e("not_initialized","This folder is bound to a project but has never been pulled. Run `hlix pull` first.");return{root:await Ep(T.root),config:T.config,state:N}}async function qe(j,O,T,N,H,F=!1){let M=await Le(j,{historyMode:s(j)?.snapshotOnly?"sanitize":T,environment:O,rootName:N,include:H,refreshIgnore:F});if(M.blocking.length>0)throw new e("scan_blocked",`Project scan blocked sync:
390
+ - ${M.blocking.join(`
391
+ - `)}`);return M}async function Ms(j,O,T,N){let{state:H,config:F}=await Ue(N,{allowUnsynced:!0}),M=j.requireClient(),[U,L]=await Promise.all([qe(N,j.env,H.snapshotOnly?"sanitize":H.historyMode??"preserve",H.rootName,typeof j.flags.include==="string"?j.flags.include:void 0),T==="pull"?ma(M,F.projectId):Kt(M,F.projectId)]),D=Gt(U,H,L?.revision??_n),B=Cs(T,D,j.flags.force===!0),z=Is(B,D,j.flags.yes===!0);if(j.json)j.stdout(ne(re(O,{dryRun:!0,action:B,approvalRequired:z,...D})));else j.stdout(`${Vi(T,B,D,z)}
392
+ `);if(T==="push")return 0;return B==="conflict"?1:0}async function Cp(j,O){if(j.flags.yes===!0)return;if(j.json||!j.confirm)throw new e("approval_required","`pull --force` replaces local files. Review with `hlix pull --dry-run`, then repeat with `--yes`.");let T=[`hlix pull --force will replace this folder with cloud revision ${O.cloud.generation}.`,`Local-only files to delete: ${O.files.localOnly}`,`Files to replace with the cloud copy: ${O.files.differing}`,"Local changes that were never pushed cannot be recovered by Hlix."].join(`
393
+ `);if(!await j.confirm(T))throw new e("cancelled","Pull cancelled.")}function Ip(j,O){let T=O??{},N={...j.manifest,secretFiles:T.secretFiles??[],activeEnvFiles:T.activeEnvFiles??[],secretKeys:T.secretKeys??[],envCollisions:T.envCollisions??[],quarantinedResources:T.quarantinedResources??[],mcpServers:T.mcpServers??[]};return{manifest:N,manifestSha256:ua("sha256").update(Ze(N)).digest("hex")}}async function yr(j,O,T,N,{inheritProtected:H=!1}={}){let{state:F,config:M}=await Ue(j,{allowUnsynced:!0}),U=O.requireClient(),L=F.snapshotOnly?"sanitize":F.historyMode??"preserve",D=T??await qe(j,O.env,L,F.rootName,void 0,!0);if(!O.json&&D.ignoreReport)O.stderr(`${D.ignoreReport}
394
+ `);if(D.uploadWarning){if(!O.json)O.stderr(`${D.uploadWarning}
395
+ `);return{action:"none",warning:D.uploadWarning,revisionId:F.revisionId,generation:F.generation}}if(!O.json)for(let Q of D.manifest.skipped.filter((G)=>G.reason!=="built-in ignore"&&G.reason!=="Hlix-managed ignore"))O.stderr(`Skipped: ${Q.path} (${Q.reason})
396
+ `);let B=N??(await Kt(U,M.projectId))?.revision??_n,z=B.manifest,J=[...z?.files??[],...z?.symlinks??[]],K=Ee(D.manifest),X=J.filter((Q)=>!K.has(Q.path)&&Ui(Q.path,D.includedPaths)||(D.skippedEntries??D.manifest.skipped).some((G)=>Q.path===G.path||Q.path.startsWith(`${G.path}/`)));if(X.length){let Q=`Push left the cloud unchanged: skipped local paths include ${X.slice(0,10).map((G)=>G.path).join(", ")}. Use --include or adjust .hlixignore before pushing.`;if(!O.json)O.stderr(`${Q}
397
+ `);return{action:"none",warning:Q,revisionId:F.revisionId,generation:F.generation}}if(B.id!==F.revisionId||B.generation!==F.generation){if(H)throw new e("conflict","Cloud changed since the local base. Kept both copies unchanged; run hlix sync to reconcile them.");if(!O.json)O.stderr(`Cloud changed since the local base. Kept both copies unchanged; run hlix sync to reconcile them.
398
+ `);return{action:"none",warning:"Cloud changed since the local base. Kept both copies unchanged; run hlix sync to reconcile them.",revisionId:F.revisionId,generation:F.generation}}if(F.manifestSha256&&D.manifestSha256===F.manifestSha256)return ct(j,{...F,includedPaths:D.includedPaths}),{action:"none",revisionId:F.revisionId,generation:F.generation};let W;try{W=await Cn(D)}catch(Q){return{action:"none",warning:`Push left both copies unchanged because a consistent snapshot could not be built: ${Q instanceof Error?Q.message:"local files unavailable"}. Retry after local writes finish.`,revisionId:F.revisionId,generation:F.generation}}let V=H?Ip(D,B.manifest):{manifest:D.manifest,manifestSha256:D.manifestSha256};try{if(J.filter((ue)=>(D.skippedEntries??D.manifest.skipped).some((ae)=>ue.path===ae.path||ue.path.startsWith(`${ae.path}/`))).length)return{action:"none",warning:"Push left the cloud unchanged because fitting the upload would omit existing cloud files.",revisionId:F.revisionId,generation:F.generation};let G=await U.revisions.createUpload(M.projectId,{idempotencyKey:$p(F.revisionId,V.manifestSha256,W.bundleSha256),expectedRevisionId:F.revisionId||null,expectedGeneration:F.generation,manifest:V.manifest,manifestSha256:V.manifestSha256,bundleSha256:W.bundleSha256,bundleSize:W.bundleSize,commitSha:W.commitSha});if(G.revisionUpload.status==="pending_upload"){if(!G.upload)throw Error("Revision upload has no bundle target.");await U.revisions.uploadBundle(G.upload,new Blob([Uint8Array.from(await Pp(W.bundlePath))]),{onProgress:(ue,ae)=>{if(!O.json)O.stderr(`Uploading ${ue}/${ae} bytes\r`)}})}let oe=await U.revisions.finalize(M.projectId,G.revisionUpload.id,H?{secrets:{},protectedFiles:[],inheritProtected:!0}:{secrets:D.secretValues,protectedFiles:D.protectedFiles});if(!oe.revision)throw Error("Revision finalized without head metadata.");return ct(j,{schemaVersion:1,revisionId:oe.revision.id,generation:oe.revision.generation,commitSha:oe.revision.commitSha,manifestSha256:H?D.manifestSha256:oe.revision.manifestSha256,historyMode:F.historyMode??"preserve",snapshotOnly:!D.manifest.git.detected,includedPaths:D.includedPaths,rootName:F.rootName??D.manifest.rootName,files:Object.fromEntries(Ee(D.manifest))}),{action:"push",...oe.revision}}finally{await W.dispose()}}async function fa(j,O,T,N,H){let{state:F,config:M}=await Ue(j,{allowUnsynced:!0}),U=O.requireClient(),L=F.snapshotOnly?"sanitize":F.historyMode??"preserve",D=N??await qe(j,O.env,L,F.rootName),B=H??(await ma(U,M.projectId)).revision;if(B.id===F.revisionId&&B.generation===F.generation)return{action:"none",revisionId:F.revisionId,generation:F.generation};let z=F.manifestSha256?D.manifestSha256!==F.manifestSha256:(()=>{let{files:G}=Gt(D,F,B);return G.localOnly+G.differing>0})();if(z&&!T)throw new e("conflict","Local files changed since the last sync. Push them, or use `hlix pull --force` to replace them.");if(z)await Cp(O,Gt(D,F,B));let[J,K]=await Promise.all([U.revisions.downloadBundle(M.projectId,B.id),U.revisions.protectedFiles(M.projectId)]);await lr(j,D,B,J,K);let X=cr(B.manifest),W=X.historyMode??L,V=X.rootName??F.rootName??D.manifest.rootName,Q=await qe(j,O.env,W,V);return ct(j,{schemaVersion:1,revisionId:B.id,generation:B.generation,commitSha:B.commitSha,manifestSha256:Q.manifestSha256,historyMode:W==="sanitize"?"preserve":W,snapshotOnly:F.snapshotOnly,rootName:V,files:Object.fromEntries(Ee(Q.manifest))}),{action:"pull",revisionId:B.id,generation:B.generation,commitSha:B.commitSha}}function fr(j,O,T){if(j.json)j.stdout(ne(re(O,T)));else if("action"in T&&T.action==="none")j.stdout("warning"in T?`${T.warning}
399
+ `:`Already in sync.
400
+ `);else j.stdout(`${String("action"in T?T.action:"sync")} complete.
401
+ `)}var In={name:"push",summary:"Push local changes as an immutable cloud revision",usage:["Usage: hlix push [--include <path>] [--dry-run] [--json]","","Uploads this folder as the next cloud revision of the bound project.","A project with no cloud revision yet takes this folder as revision 1."," --dry-run Show what would change, upload nothing"," --json Machine-readable output"].join(`
402
+ `),supportsJson:!0,options:["dry-run","include"],async run(j){if(j.args.length)throw Error("push accepts no positional arguments.");let O;try{O=await Ue(j.cwd,{allowUnsynced:!0})}catch(M){if(!(M instanceof e)||M.code!=="not_initialized")throw M;return fr(j,In.name,{action:"none",warning:M.message}),0}let{root:T}=O,{state:N}=await Ue(T,{allowUnsynced:!0}),H=typeof j.flags.include==="string"?Sp(T,jp(T,j.flags.include)).replaceAll("\\","/"):void 0;if(H===".."||H?.startsWith("../")||H?.split("/").some((M)=>M===".git"||M===".hlix"))throw new e("invalid_usage","--include must name a path inside this folder, excluding .git and .hlix metadata.");if(j.flags.include=H,j.flags["dry-run"]===!0)return Ms(j,In.name,"push",T);let F=await qe(T,j.env,N.snapshotOnly?"sanitize":N.historyMode??"preserve",N.rootName,H,!0);return fr(j,In.name,await yr(T,j,F)),0}},gr={name:"pull",summary:"Pull the cloud head into the local project",usage:["Usage: hlix pull [--force] [--yes] [--dry-run] [--json]",""," --force Replace local changes with the cloud revision"," --yes Skip the confirmation --force otherwise requires"," --dry-run Report the divergence and change nothing"].join(`
403
+ `),supportsJson:!0,options:["force","yes","dry-run"],async run(j){if(j.args.length)throw Error("pull accepts no positional arguments.");let{root:O}=await Ue(j.cwd,{allowUnsynced:!0});if(j.flags["dry-run"]===!0)return Ms(j,gr.name,"pull",O);return fr(j,gr.name,await fa(O,j,j.flags.force===!0)),0}},hr={name:"sync",summary:"Reconcile local and cloud changes without guessing conflicts",usage:"Usage: hlix sync [--dry-run] [--json]",supportsJson:!0,options:["dry-run"],async run(j){if(j.args.length)throw Error("sync accepts no positional arguments.");let{root:O,state:T,config:N}=await Ue(j.cwd,{allowUnsynced:!0});if(j.flags["dry-run"]===!0)return Ms(j,hr.name,"sync",O);let H=j.requireClient(),[F,M]=await Promise.all([qe(O,j.env,T.snapshotOnly?"sanitize":T.historyMode??"preserve",T.rootName),Kt(H,N.projectId)]),U=M?.revision??_n,L=Gt(F,T,U);if(L.localChanged&&L.cloudChanged)throw new e("conflict","Both local and cloud changed since the last sync. Pull or push explicitly after reviewing the conflict.");let D=L.localChanged?await yr(O,j,F,U):L.cloudChanged?await fa(O,j,!1,F,M?.revision):{action:"none",revisionId:T.revisionId,generation:T.generation};return fr(j,hr.name,D),0}};import{lstat as _p,readFile as Rp,readlink as Ap,rm as ha,symlink as Op,writeFile as Tp,chmod as Np}from"node:fs/promises";import{watch as Fp}from"node:fs";function v(j){return[...j.pulled!==void 0?[`mirror: pulled revision ${j.pulled} from the cloud`]:[],...j.conflicts.map((O)=>`mirror: ${O.path} changed here and in the cloud — kept the cloud's, yours is ${O.savedAs}`),...j.pushed!==void 0?[`mirror: pushed revision ${j.pushed} to the cloud`]:[]]}async function Hp(j,O){let T=new Map;for(let N of O){let H=`${j}/${N}`;try{let F=await _p(H);if(F.isSymbolicLink())T.set(N,{kind:"link",target:await Ap(H)});else if(F.isFile())T.set(N,{kind:"file",bytes:await Rp(H),mode:F.mode&511})}catch(F){if(F.code!=="ENOENT")throw F}}return T}async function Ls(j,O,T){let N=await qt(j,O);if(await ha(N,{force:!0}),T.kind==="link"){await Op(T.target,N);return}await Tp(N,T.bytes,{mode:T.mode}),await Np(N,T.mode)}var Mp=(j)=>j.toISOString().replace(/\.\d+Z$/,"Z").replace(/[-:]/g,"");async function Lp(j,O,T,N,H,F){let M=new Map(Object.entries(H.files??{})),U=Ee(N.manifest),L=Ee(F.manifest),D=[],B=[],z=[];for(let ae of new Set([...U.keys(),...L.keys()])){let ee=U.get(ae),Y=L.get(ae),q=M.get(ae);if(ee===Y||ee===q)continue;if(Y===q){if(ee===void 0)B.push(ae);else D.push(ae);continue}if(ee!==void 0)z.push(ae)}let J=[...N.manifest.secretFiles,...N.manifest.quarantinedResources].map((ae)=>ae.path),K=await Hp(j,[...D,...z,...J]),X=await O.client.revisions.downloadBundle(T,F.id);await lr(j,N,F,X,null);for(let ae of J){let ee=K.get(ae);if(ee)await Ls(j,ae,ee)}let W=cr(F.manifest),V=W.historyMode??H.historyMode??"preserve",Q=W.rootName??H.rootName??N.manifest.rootName,G=await qe(j,O.env,V,Q);ct(j,{schemaVersion:1,revisionId:F.id,generation:F.generation,commitSha:F.commitSha,manifestSha256:G.manifestSha256,historyMode:V,rootName:Q,snapshotOnly:H.snapshotOnly,files:Object.fromEntries(Ee(G.manifest))});for(let ae of D){let ee=K.get(ae);if(ee)await Ls(j,ae,ee)}for(let ae of B)await ha(`${j}/${ae}`,{force:!0});let oe=`.local-${Mp((O.now??(()=>new Date))())}`,ue=[];for(let ae of z){let ee=K.get(ae);if(!ee)continue;await Ls(j,`${ae}${oe}`,ee),ue.push({path:ae,savedAs:`${ae}${oe}`})}return ue}function ga(j,O){if(!O)return!1;if(!O.files)return O.manifestSha256===j.manifestSha256;let T=Object.entries(O.files),N=Ee(j.manifest);return T.length===N.size&&T.every(([H,F])=>N.get(H)===F)}var Up=(j)=>({requireClient:()=>j.client,env:j.env??{},json:!0,stderr:()=>{}});async function Us(j,O,{cloud:T,onReport:N}){let{config:H,state:F}=await Ue(j,{allowUnsynced:!0}),M=H.projectId,U={conflicts:[]},L=await qe(j,O.env,F.historyMode??"preserve",F.rootName),D;if(T){let B=(await Kt(O.client,M))?.revision,z=Ee(L.manifest),J=F.files?[...new Set([...Object.keys(F.files),...z.keys()])].filter((K)=>F.files[K]!==z.get(K)).length:ga(L,F)?0:z.size;if(N?.({conflicts:[],drift:{localChanges:J,cloudChanged:Boolean(B&&(B.id!==F.revisionId||B.generation!==F.generation))}}),B&&(B.id!==F.revisionId||B.generation!==F.generation))U.conflicts=await Lp(j,O,M,L,F,B),U.pulled=B.generation,L=await qe(j,O.env,F.historyMode??"preserve",F.rootName);D=B??_n}if(ga(L,s(j)))return U;if(!T){let B=Ee(L.manifest),z=F.files??{},J=[...new Set([...Object.keys(z),...B.keys()])].filter((K)=>z[K]!==B.get(K)).length;N?.({conflicts:[],drift:{localChanges:J,cloudChanged:!1}})}try{let B=await yr(j,Up(O),L,D,{inheritProtected:!0});if(B.action==="push")U.pushed=B.generation;return U}catch(B){if(!T&&B instanceof e&&B.code==="conflict")return Us(j,O,{cloud:!0,...N?{onReport:N}:{}});throw B}}function Dp(j){if(!j)return!1;let O=j.split("\\").join("/");return/^(\.git|\.hlix|node_modules)(\/|$)/.test(O)||/\/(\.git|node_modules)(\/|$)/.test(O)}var Bp=300;async function k(j,O,T){let{config:N}=await Ue(j,{allowUnsynced:!0}),H=T.signal,F=!1,M=!1,U=null,L=!1,D=async()=>{while(F||M){if(await Ft(Bp,H),H?.aborted)return;let J=F;F=!1,M=!1;try{let K=await Us(j,O,{cloud:J,onReport:T.onReport});if(T.onReport(K),J&&!L)L=!0,T.onCaughtUp?.()}catch(K){T.onError(K)}}},B=()=>{if(U||H?.aborted)return;U=D().finally(()=>{if(U=null,F||M)B()})},z=Fp(j,{recursive:!0,...H?{signal:H}:{}},(J,K)=>{if(Dp(typeof K==="string"?K:null))return;M=!0,B()});z.on("error",T.onError);try{for await(let J of O.client.revisions.watch(N.projectId,H?{signal:H}:{})){if(J.kind==="head"&&J.generation===s(j)?.generation)continue;F=!0,B()}}finally{z.close(),await U}}function zp(j,O){if(j.json)j.stdout(`${JSON.stringify(re(Rn.name,O))}
404
+ `);else for(let T of v(O))j.stdout(`${T}
405
+ `)}var Rn={name:"mirror",summary:"Keep this folder a live mirror of the project's cloud files",usage:["Usage: hlix mirror [--once] [--json]","","Catches this folder up with the cloud, then follows both ways until","stopped: a change in the cloud is pulled down, a save here is pushed up.","When both sides changed one file, the cloud's version wins and yours is","kept beside it as <file>.local-<timestamp>. `.env` and other protected","files are never written down."," --once One catch-up pass, then exit"," --json One envelope per pass, one per line (JSONL)"].join(`
406
+ `),supportsJson:!0,options:["once"],agentTool:!1,async run(j){if(j.args.length)throw Error("mirror accepts no positional arguments.");let{root:O,config:T}=await Ue(j.cwd,{allowUnsynced:!0}),N={client:j.requireClient(),env:j.env};if(j.flags.once===!0){let H=await Us(O,N,{cloud:!0});if(j.json)j.stdout(ne(re(Rn.name,H)));else{let F=v(H);j.stdout(F.length?`${F.join(`
407
+ `)}
408
+ `:`Already in sync.
409
+ `)}return 0}if(!j.json)j.stdout(`Mirroring ${O} with project ${T.projectId}. Ctrl-C stops.
410
+ `);return await k(O,N,{...j.signal?{signal:j.signal}:{},onCaughtUp:()=>{let H=s(O)?.generation??0;if(j.json)j.stdout(`${JSON.stringify(re(Rn.name,{caughtUp:!0,generation:H}))}
411
+ `);else j.stdout(`Caught up at revision ${H}; following the cloud.
412
+ `)},onReport:(H)=>zp(j,H),onError:(H)=>j.stderr(`mirror: ${H instanceof Error?H.message:String(H)}
413
+ `)}),0}};import{lstat as Bs,readFile as Wp,realpath as Jp}from"node:fs/promises";import{basename as Ds,dirname as qp,extname as Gp,join as wr,parse as ya,resolve as vr}from"node:path";function Vt(j,O){let T=j.flags[O];return typeof T==="string"&&T.trim()?T.trim():void 0}function zs(j){let O=Vt(j,"project");if(O)return{root:j.cwd,projectId:O};return Kp(j.cwd)}function Kp(j){let O=t(j);if(!O?.config.projectId)throw new e("not_initialized","This folder is not bound to an Hlix project. Run `hlix import .` first.");return{root:O.root,projectId:O.config.projectId}}async function Ws(j,O){let T=await Bs(j);if(T.isSymbolicLink()||!T.isFile())throw Error(`Refusing to import a non-regular file: ${j}`);if(T.size>O)throw Error(`Import file exceeds ${O} bytes: ${j}`);return{path:await Jp(j),content:await Wp(j,"utf8")}}function Js(j,O,T,N){if(j.json)j.stdout(ne(re(O,T)));else j.stdout(`${N}
414
+ `)}function Vp(j){let O=/^---\r?\n([\s\S]*?)\r?\n---/.exec(j)?.[1];return(O?/^name:\s*(.+?)\s*$/m.exec(O)?.[1]:void 0)?.replace(/^["']|["']$/g,"").trim()||void 0}var Yp=[wr(".claude","skills"),wr(".agents","skills"),wr(".hlix","skills")];async function Xp(j,O){let T=[vr(j,O),...Yp.map((N)=>vr(j,N,O))];for(let N of T)if(await Bs(N).then(()=>!0,()=>!1))return N;throw new e("not_found",`No skill at ${O}. Pass the SKILL.md or its folder, for example .claude/skills/${O}.`)}var qs={name:"skill import",summary:"Activate a local skill for the bound cloud project",usage:"Usage: hlix skill import <SKILL.md|folder> [--name <slug>] [--project <id>] [--json]",supportsJson:!0,options:["name","project"],args:{min:1,max:1},async run(j){if(j.args.length!==1)throw Error("skill import requires one file or folder.");let O=zs(j),T=await Xp(j.cwd,j.args[0]),N=await Bs(T);if(N.isSymbolicLink())throw Error(`Refusing to import a symlink: ${T}`);let H=N.isDirectory()?wr(T,"SKILL.md"):T,F=await Ws(H,200000),M=N.isDirectory()?Ds(T):Ds(H)==="SKILL.md"?Ds(qp(H)):ya(H).name,U=Vt(j,"name")??M;if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(U))throw Error("Skill name must be a lowercase kebab-case slug.");let L=await j.requireClient().resources.importSkill(O.projectId,{slug:U,content:F.content});return Js(j,qs.name,L.skill,`Imported skill ${U}`),0}},Gs={name:"agent import",summary:"Create a project-scoped agent from a local Markdown brief",usage:"Usage: hlix agent import <markdown-file> [--name <name>] [--runtime <runtime>] [--duty <duty>] [--profile <profile>] [--project <id>] [--json]",supportsJson:!0,options:["name","runtime","duty","profile","project"],args:{min:1,max:1},async run(j){if(j.args.length!==1)throw Error("agent import requires one Markdown file.");let O=zs(j),T=vr(j.cwd,j.args[0]);if(![".md",".mdx"].includes(Gp(T).toLowerCase()))throw Error("Agent imports must be Markdown files.");let N=await Ws(T,20000),H=Vt(j,"runtime")??m;if(!o.includes(H)){let L=new Intl.ListFormat("en",{type:"disjunction"}).format(o);throw Error(`--runtime must be ${L}.`)}let F=Vt(j,"duty")??"executor";if(F!=="executor"&&F!=="intake")throw Error("--duty must be executor or intake.");let M=Vt(j,"name")??Vp(N.content)??ya(T).name.replace(/[-_]+/g," "),U=await j.requireClient().resources.importAgent(O.projectId,{name:M,instructions:N.content,runtimeKind:H,duty:F});return Js(j,Gs.name,U.agent,U.agent.duty==="intake"?`Imported agent ${U.agent.name} as this project's intake agent`:`Imported agent ${U.agent.name}`),0}},Ks={name:"mcp import",summary:"Explicitly activate one validated local MCP server",usage:"Usage: hlix mcp import <.mcp.json> [--server <name>] [--allow-stdio] [--project <id>] [--json]",supportsJson:!0,options:["server","allow-stdio","project"],args:{min:1,max:1},async run(j){if(j.args.length!==1)throw Error("mcp import requires one MCP JSON file.");let O=zs(j),T=await Ws(vr(j.cwd,j.args[0]),200000),N;try{N=JSON.parse(T.content)}catch{throw Error("MCP config is not valid JSON.")}let H=Object.entries(N.mcpServers??{});if(H.length===0)throw Error("MCP config contains no servers.");let F=Vt(j,"server");if(!F&&H.length>1)throw Error("MCP config contains multiple servers; select one with --server <name>.");let M=F?H.find(([W])=>W===F):H[0];if(!M)throw Error(`MCP server not found: ${F}`);let[U,L]=M,D=L.type==="http"||L.type==="sse"?L.type:typeof L.command==="string"?"stdio":typeof L.url==="string"?"http":null;if(!D)throw Error(`MCP server ${U} has no supported transport.`);if(D==="stdio"&&j.flags["allow-stdio"]!==!0)throw Error("Stdio MCP servers execute a local command in the cloud; repeat with --allow-stdio.");let B=L.env&&typeof L.env==="object"&&!Array.isArray(L.env)?L.env:{},z=L.headers&&typeof L.headers==="object"&&!Array.isArray(L.headers)?L.headers:{};if(Object.values(z).some((W)=>typeof W!=="string"))throw Error(`MCP server ${U} headers must be strings.`);for(let[W,V]of Object.entries(B)){if(typeof V!=="string")continue;let Q=/^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(V)?.[1];if(Q&&Q!==W)throw new e("invalid_usage",`MCP server ${U}: env ${W} references \${${Q}}, but a placeholder must be the variable's own name — write "${W}": "\${${W}}" and store the secret as ${W}.`)}let J=Object.values(z).flatMap((W)=>[...W.matchAll(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g)].map((V)=>V[1]));if(Object.keys(z).length>0&&J.length===0)throw Error("MCP remote headers must use ${KEY} placeholders; literal credentials are refused.");let K=/^(?:(?:Bearer|Basic|Token) )?\$\{[A-Za-z_][A-Za-z0-9_]*\}$/i;if(Object.values(z).some((W)=>!K.test(W)))throw Error("MCP remote headers must be ${KEY} or an approved auth scheme followed by ${KEY}.");let X=await j.requireClient().resources.importMcp(O.projectId,{name:U,transport:D,...typeof L.command==="string"?{command:L.command}:{},...Array.isArray(L.args)&&L.args.every((W)=>typeof W==="string")?{args:L.args}:{},...typeof L.url==="string"?{url:L.url}:{},...Object.keys(z).length>0?{headers:z}:{},envKeys:[...new Set([...Object.keys(B),...J])].sort()});return Js(j,Ks.name,X.mcpServer,`Imported MCP server ${U}`),0}};import{spawnSync as Zp}from"node:child_process";import{chmod as Qp,realpath as eu,writeFile as tu}from"node:fs/promises";import{basename as nu,dirname as ru,relative as su,resolve as va,sep as ou}from"node:path";var wa=64;function On(j){let O=t(j.cwd),N=(typeof j.flags.project==="string"?j.flags.project:void 0)??O?.config.projectId;if(!N)throw new e("not_initialized","This folder is not bound to a Hlix project. Run `hlix import .`, or pass --project <id>.");return{projectId:N,root:O?.root??j.cwd}}var An=(j,O)=>typeof j[O]==="string"?j[O]:void 0,Vs={name:"secrets list",summary:"Show every secret the project holds, masked, with its source file",usage:["Usage: hlix secrets list [--project <id>] [--json]","","One row per (key, source file). Values are masked to their last four","characters and there is no flag that unmasks them — `hlix secrets export`","is the one command that returns plaintext, and it is audited."].join(`
415
+ `),supportsJson:!0,options:["project"],async run(j){let{projectId:O}=On(j),T=await j.requireClient().secrets.listEntries(O);if(j.json)return j.stdout(ne(re(Vs.name,T))),0;if(T.entries.length===0)j.stdout(`No secrets stored for this project.
416
+ `);else j.stdout(`${Ge(["key","source","format","value","updated"],T.entries.map((N)=>[N.key,N.source,N.format||"-",N.maskedValue,N.updatedAt?.slice(0,10)??"-"]))}
417
+ `);for(let N of T.warnings)j.stderr(`warning: ${N}
418
+ `);return 0}},Ys={name:"secrets set",summary:"Create or replace one secret in the store",usage:["Usage: hlix secrets set <KEY> [value] [--from-stdin] [--source <file>] [--project <id>] [--json]",""," --from-stdin Read the value from stdin instead of the argument, so it"," never reaches shell history or `ps`. Use this for real"," credentials: `pbpaste | hlix secrets set API_KEY --from-stdin`."," --source The file the value belongs to, e.g. apps/api/.env.local."," Omitted means the project root .env.","","Exactly one trailing newline is stripped from stdin, so a piped value does","not acquire the shell's."].join(`
419
+ `),supportsJson:!0,options:["from-stdin","source","project"],args:{min:1,max:2},async run(j){let{projectId:O}=On(j),T=j.args[0],N=j.flags["from-stdin"]===!0;if(N&&j.args.length>1)throw new e("invalid_usage","Pass the value as an argument or with --from-stdin, not both.");if(!N&&j.args.length<2)throw new e("missing_argument","A value is required. Pass it as an argument, or pipe it with --from-stdin.");let H;if(N){if(!j.readStdin)throw new e("invalid_usage","--from-stdin is not available in this context.");H=(await j.readStdin()).replace(/\r?\n$/,"")}else H=j.args[1];let F=An(j.flags,"source"),M=await j.requireClient().secrets.upsertEntries(O,{entries:[{key:T,value:H,...F?{source:F}:{}}]});if(j.json)return j.stdout(ne(re(Ys.name,M))),M.written>0?0:1;if(M.written===0)throw new e("bad_request",`The store refused ${T}: --source must be a project-relative file path.`);return j.stdout(`${ve([["key",T],["source",F??".env"]])}
420
+ `),0}},Xs={name:"secrets delete",summary:"Remove one secret from the store",usage:["Usage: hlix secrets delete <KEY> [--source <file>] [--project <id>] [--json]","","Without --source the key is removed from EVERY file that declares it,",'which is what "delete this secret" usually means. Removing nothing exits 1.'].join(`
421
+ `),supportsJson:!0,options:["source","project"],args:{min:1,max:1},async run(j){let{projectId:O}=On(j),T=j.args[0],N=An(j.flags,"source"),H=await j.requireClient().secrets.deleteEntry(O,T,N);if(j.json)return j.stdout(ne(re(Xs.name,H))),H.removed>0?0:1;if(H.removed===0)return j.stderr(`No stored secret named ${T}${N?` in ${N}`:""}.
422
+ `),1;return j.stdout(`Removed ${H.removed} entr${H.removed===1?"y":"ies"} for ${T}.
423
+ `),0}},br={name:"secrets import",summary:"Load this folder's secret files into the project secrets store",usage:["Usage: hlix secrets import [file...] [--project <id>] [--json]","","With no arguments, every secret file the project scanner detects. Naming","files narrows it to those; a named file the scanner does not consider a","secret is refused rather than uploaded.","","The files are uploaded as bytes and the server parses them, so every shape","it knows lands here: dotenv and .envrc, Terraform variables, Java","properties, Spring YAML, .NET appsettings, Azure Functions local settings,","npm credentials, Rails database.yml, wrangler/fly TOML and Serverless all","become readable entries under their own path. An opaque credential (a","private key, a keystore, a service-account JSON) is kept byte-exact","instead. A file whose plaintext this platform does not hold — SOPS,","Ansible Vault, git-crypt — and a .env.example are reported as skipped.","","A file that holds key/value pairs REPLACES what the store held for that","path: the file on this machine is the truth."].join(`
424
+ `),supportsJson:!0,options:["project"],args:{min:0,max:64},async run(j){let{projectId:O,root:T}=On(j),N=await Le(T,{historyMode:"preserve",environment:j.env}),H=N.blocking.filter((z)=>!z.startsWith(js));if(H.length>0)throw new e("scan_blocked",`Project scan blocked the import:
425
+ - ${H.join(`
426
+ - `)}`);let F=N.protectedFiles.filter((z)=>z.kind==="dotenv"||z.kind==="credential"),M=await eu(j.cwd),U=j.args.map((z)=>su(N.root,va(M,z)).split(ou).join("/")),L=U.filter((z)=>!F.some((J)=>J.path===z));if(L.length>0)throw new e("invalid_usage",`Not a secret file in this project: ${L.join(", ")}`);let D=U.length>0?F.filter((z)=>U.includes(z.path)):F;if(D.length===0)return j.stdout(j.json?ne(re(br.name,{imported:[],skipped:[],warnings:[],written:0,rejected:[]})):`No secret files found in this project.
427
+ `),0;if(D.length>wa)throw new e("invalid_usage",`${D.length} secret files exceeds the ${wa} the store accepts in one request. Name the files to import, a batch at a time.`);let B=await j.requireClient().secrets.importFiles(O,D.map((z)=>({path:z.path,contentBase64:z.contentBase64})));if(j.json)return j.stdout(ne(re(br.name,B))),0;if(B.imported.length>0)j.stdout(`${Ge(["source","format","stored"],B.imported.map((z)=>[z.path,z.format||"-",z.kind==="file"?"as file":`${z.entries} entr${z.entries===1?"y":"ies"}`]))}
428
+ `);if(j.stdout(`${B.written} value${B.written===1?"":"s"} stored.
429
+ `),B.imported.some((z)=>z.kind!=="file"))j.stdout(`Each imported file replaced what the store held under its path; keys the file no longer has are gone.
430
+ `);for(let z of B.skipped)j.stderr(`skipped ${z.path}: ${z.reason}
431
+ `);for(let z of B.warnings)j.stderr(`warning: ${z}
432
+ `);for(let z of B.rejected)j.stderr(`rejected ${z}: the store refused its source path
433
+ `);return 0}};function iu(j){return Zp("git",["-C",ru(j),"ls-files","--error-unmatch","--",nu(j)],{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).status===0}var Zs={name:"secrets export",summary:"Render one source file back out of the store, values in clear",usage:["Usage: hlix secrets export [--source <file>] [--format <id>] [--out <path>] [--project <id>] [--json]",""," --source Which stored file to render. Omitted means the root .env."," --format Re-render it as a different shape (dotenv, tfvars, …)."," Omitted means the shape the values were parsed as."," --out Write it to this path, mode 0600, instead of stdout. A path"," git TRACKS is refused: an exported file carries plaintext and"," must not become a commit.","","This is the one command that returns secret values, and the server writes","an audit row for every call."].join(`
434
+ `),supportsJson:!0,options:["source","format","out","project"],async run(j){let{projectId:O}=On(j),T=An(j.flags,"source"),N=An(j.flags,"format"),H=An(j.flags,"out"),F=H===void 0?void 0:va(j.cwd,H);if(F!==void 0&&iu(F))throw new e("invalid_usage",`Refusing to overwrite a git-tracked file with secret values: ${F}`);let M=await j.requireClient().secrets.exportEntries(O,{...T?{source:T}:{},...N?{format:N}:{}});if(F!==void 0)await tu(F,M,{mode:384}),await Qp(F,384);if(j.json)return j.stdout(ne(re(Zs.name,{source:T??null,format:N??null,out:F??null,bytes:Buffer.byteLength(M),...F===void 0?{content:M}:{}}))),0;if(F===void 0)j.stdout(M);else j.stdout(`${ve([["wrote",F],["mode","0600"],["bytes",String(Buffer.byteLength(M))]])}
435
+ `);return 0}};function eo(j){let O=j.flags.project;if(typeof O==="string"&&O)return O;return t(j.cwd)?.config.projectId??void 0}function Qs(j,O){let T=j[O];if(typeof T!=="string"||T.trim()==="")throw new e("missing_argument",`--${O} is required.`);return T}var to={name:"cycles create",summary:"Propose a cycle, which starts the project working on it",usage:["Usage: hlix cycles create <project-id> --title <t> --description <d> [--json]","","This is the command that DISPATCHES work. The proposal enters the project's","own loop, which plans the cycle, creates its tasks and starts the coders —","using the project's harness (see `hlix harness get`).","","`adopted` is true when the loop took it on this call, false when it was","recorded and will be planned on the next pass. Neither is an error. The API","returns no cycle id: the roadmap owns cycles, so find it with `hlix tasks","list --project <id>` once planning has run."].join(`
436
+ `),supportsJson:!0,options:["title","description"],args:{min:1,max:1},async run(j){let O=j.args[0],T=Qs(j.flags,"title"),N=Qs(j.flags,"description"),H=await j.requireClient().cycles.propose({projectId:O,title:T,description:N});if(j.json)return j.stdout(ne(re(to.name,H))),0;return j.stdout(`${ve([["project",O],["title",T],["status",H.adopted?"adopted — the project is planning it now":"recorded — it will be planned on the next pass"]])}
437
+ `),0}},no={name:"tasks create",summary:"Add a task to a project's board",usage:["Usage: hlix tasks create <project-id> --description <d> [--title <t>] [--json]","","Creates the task row. It does NOT start it: standalone task execution is","not implemented server-side and answers 501 by design. Work is dispatched","by its cycle — use `hlix cycles create` for that."].join(`
438
+ `),supportsJson:!0,options:["title","description"],args:{min:1,max:1},async run(j){let O=j.args[0],T=Qs(j.flags,"description"),N=typeof j.flags.title==="string"?j.flags.title:void 0,H=await j.requireClient().tasks.create({projectId:O,description:T,...N?{title:N}:{}});if(j.json)return j.stdout(ne(re(no.name,H))),0;return j.stdout(`${ve([["task",H.id],["project",O],["status",H.status??"queued"],["note","not started — dispatch with `hlix cycles create`"]])}
439
+ `),0}},ro={name:"harness get",summary:"Show which coder runs, and which setting chose it",usage:["Usage: hlix harness get [project-id] [--project <id>] [--json]","","With a project id — or from a bound folder — what that project would run.","Otherwise the workspace-wide answer. `source` names the setting that","decided: a project preference, the workspace preference, or the system","default."].join(`
440
+ `),supportsJson:!0,options:["project"],args:{min:0,max:1},async run(j){let O=j.args[0]??eo(j),T=j.requireClient(),N=O?await T.modelConfig.resolvedProjectHarness(O):await T.modelConfig.resolvedHarness();if(j.json)return j.stdout(ne(re(ro.name,N))),0;return j.stdout(`${ve([["scope",O?`project ${O}`:"workspace"],["harness",N.harness],["source",N.source]])}
441
+ `),0}},so={name:"harness set",summary:"Choose the coder a project or the workspace runs",usage:[`Usage: hlix harness set <${o.join("|")}> [project-id] [--org] [--json]`,"","With a project id, sets that project's preference. With --org, the","workspace-wide one that projects fall back to. This is a PERSISTENT server","setting that every future run on that scope uses, and it is audited.","","It is not the same thing as the local `harness` config key, which only","picks the coder Hlix Code spawns on this machine."].join(`
442
+ `),supportsJson:!0,options:["org"],args:{min:1,max:2},async run(j){let O=j.args[0];if(!o.includes(O))throw new e("invalid_usage",`harness must be one of ${o.join(", ")}; got "${O}".`);let T=j.flags.org===!0,N=j.args[1]??(T?void 0:eo(j));if(N&&T)throw new e("invalid_usage","Name a project or pass --org, not both: they are different scopes.");if(!N&&!T)throw new e("invalid_usage","Name the project to set, or pass --org for the whole workspace.");let H=j.requireClient(),F=N?await H.modelConfig.setProjectHarness(N,O):await H.modelConfig.setHarness(O);if(j.json)return j.stdout(ne(re(so.name,F))),0;return j.stdout(`${ve([["scope",N?`project ${N}`:"workspace"],["harness",O]])}
443
+ `),0}},oo={name:"harness clear",summary:"Remove a harness preference so the scope below it decides",usage:["Usage: hlix harness clear [project-id] [--org] [--json]","","With a project id, drops that project's preference so it inherits the","workspace's answer (or the system default). With --org, drops the","workspace-wide one. Audited, like every write on this setting.","","Answers `not_found` when that scope had no preference to clear — the","setting is already off, and saying so beats reporting a change that was","never made. Check the result with `hlix harness get`."].join(`
444
+ `),supportsJson:!0,options:["org"],args:{min:0,max:1},async run(j){let O=j.flags.org===!0,T=j.args[0]??(O?void 0:eo(j));if(T&&O)throw new e("invalid_usage","Name a project or pass --org, not both: they are different scopes.");if(!T&&!O)throw new e("invalid_usage","Name the project to clear, or pass --org for the whole workspace.");let N=j.requireClient(),H=T?await N.modelConfig.clearProjectHarness(T):await N.modelConfig.clearHarness();if(j.json)return j.stdout(ne(re(oo.name,H))),0;return j.stdout(`${ve([["scope",T?`project ${T}`:"workspace"],["harness","cleared — the scope below decides now"]])}
445
+ `),0}};var d=[Qr,es,Dt,Ns,Hs,Fs,Ts,Os,ts,ns,rs,Es,mt,hr,gr,In,Rn,qs,Gs,Ks,Vs,Ys,Xs,br,Zs,ss,os,is,cs,ls,ds,ps,no,to,ro,so,oo];
446
+ export{e,R,s,u,t,r,n,a,p,l,o,m,g,S,h,c,i,E,f,y,C,w,b,I,_,P,A,x,v,k,d};