@hlix/cli 0.7.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +38 -35
- package/THIRD_PARTY_NOTICES +1 -28
- package/bin/hlix +1 -1
- package/dist/index-jf4vh8hj.js +403 -0
- package/dist/index.js +4 -4
- package/dist/main-003f6m56.js +161 -0
- package/dist/package-qbwm0yj5.js +2 -0
- package/package.json +16 -15
- package/skills/hlix/SKILL.md +38 -125
- package/dist/index-70g03k87.js +0 -446
- package/dist/main-73kw5ktg.js +0 -144
- package/dist/package-844qvsxr.js +0 -2
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
class e extends Error{code;details;constructor(j,O,N){super(O);if(this.name="CliError",this.code=j,N!==void 0)this.details=N}}var R=1,oe=(j,O)=>({schemaVersion:1,command:j,data:O}),Jt=(j,O)=>({schemaVersion:1,command:j,error:O});function se(j){return`${JSON.stringify(j,null,2)}
|
|
3
|
+
`}function Se(j){let O=Math.max(0,...j.map(([N])=>N.length));return j.map(([N,L])=>`${N.padEnd(O)} ${L}`).join(`
|
|
4
|
+
`)}function Be(j,O){let N=j.map((F,H)=>Math.max(F.length,...O.map((M)=>(M[H]??"").length))),L=(F)=>F.map((H,M)=>H.padEnd(N[M])).join(" ").trimEnd();return[L(j),L(N.map((F)=>"-".repeat(F))),...O.map(L)].join(`
|
|
5
|
+
`)}import{statSync as _a}from"node:fs";import{dirname as Ca,resolve as Ia}from"node:path";import{closeSync as Zn,constants as Bt,existsSync as Sn,fsyncSync as Ks,lstatSync as Qn,mkdirSync as ya,openSync as Vs,readFileSync as Xs,renameSync as wa,statSync as Ys,unlinkSync as Zs,writeFileSync as va}from"node:fs";import{homedir as ba}from"node:os";import{dirname as ka,join as er}from"node:path";var it="https://server.hlix.ai";function Ue(j=process.env){let O=j.HLIX_CONFIG_HOME??j.XDG_CONFIG_HOME??er(ba(),".config");return er(O,"hlix","credentials.json")}function Qs(j=process.env){let O=j.HLIX_API_KEY;if(!O&&j.HLIX_SESSION_TOKEN)return{baseUrl:j.HLIX_BASE_URL??it,apiKey:"",sessionToken:j.HLIX_SESSION_TOKEN,...j.HLIX_WORKSPACE_ID?{organizationId:j.HLIX_WORKSPACE_ID}:{}};if(O)return{baseUrl:j.HLIX_BASE_URL??it,apiKey:O,...j.HLIX_WORKSPACE_ID?{organizationId:j.HLIX_WORKSPACE_ID}:{}};try{let N=JSON.parse(Xs(Ue(j),"utf8"));return N.apiKey&&N.baseUrl?N:null}catch{return null}}function eo(j=process.env){let O=Ue(j);return Sn(O)?O:null}function tr(j=process.env){let O=Ue(j);if(!Sn(O))return{path:O,removed:!1,reason:"absent"};let N=Qn(O);if(N.isSymbolicLink()||!N.isFile())throw Error("Refusing to remove a credential path that is not a regular file.");let L=process.getuid?.();if(L!==void 0&&Ys(O).uid!==L)throw Error("Refusing to remove a credential file owned by another user.");let F;try{F=JSON.parse(Xs(O,"utf8"))}catch{F=null}let H=F;if(!H||typeof H.apiKey!=="string"||typeof H.baseUrl!=="string")throw Error(`Refusing to remove ${O}: it is not a credential written by this CLI.`);return Zs(O),{path:O,removed:!0,reason:"removed"}}function to(j,O=process.env){let N=Ue(O),L=ka(N);if(ya(L,{recursive:!0,mode:448}),Qn(L).isSymbolicLink())throw Error("Refusing to write credentials through a symlinked directory.");if(Sn(N)){let M=Qn(N);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&&Ys(N).uid!==U)throw Error("Refusing to replace a credential file owned by another user.")}let F=er(L,`.credentials.${process.pid}.${crypto.randomUUID()}.tmp`),H;try{H=Vs(F,Bt.O_WRONLY|Bt.O_CREAT|Bt.O_EXCL|Bt.O_NOFOLLOW,384),va(H,`${JSON.stringify(j,null,2)}
|
|
6
|
+
`,"utf8"),Ks(H),Zn(H),H=void 0,wa(F,N);let M=Vs(L,Bt.O_RDONLY);try{try{Ks(M)}catch(U){let D=U.code;if(D!=="EINVAL"&&D!=="ENOTSUP")throw U}}finally{Zn(M)}}catch(M){if(H!==void 0)Zn(H);if(Sn(F))Zs(F);throw M}return N}import{constants as jn,existsSync as rr,lstatSync as sr,mkdirSync as Sa,openSync as ja,closeSync as no,fsyncSync as Ea,readFileSync as ro,renameSync as xa,unlinkSync as Pa,writeFileSync as nr}from"node:fs";import{dirname as $a,join as Gt,resolve as En}from"node:path";function so(j){if(!rr(j))return;let O=sr(j);if(O.isSymbolicLink()||!O.isFile())throw Error(`Refusing to replace a non-regular Hlix file: ${j}`)}function Wt(j,O){let N=$a(j);if(Sa(N,{recursive:!0,mode:448}),sr(N).isSymbolicLink())throw Error(`Refusing to write through a symlinked Hlix directory: ${N}`);so(j);let L=Gt(N,`.hlix-${process.pid}-${crypto.randomUUID()}.tmp`),F;try{F=ja(L,jn.O_WRONLY|jn.O_CREAT|jn.O_EXCL|jn.O_NOFOLLOW,384),nr(F,`${JSON.stringify(O,null,2)}
|
|
7
|
+
`,"utf8"),Ea(F),no(F),F=void 0,xa(L,j)}catch(H){if(F!==void 0)no(F);if(rr(L))Pa(L);throw H}}function qt(j){return Gt(En(j),".hlix","config.json")}function oo(j){return Gt(En(j),".hlix","state.json")}function xt(j){try{let O=JSON.parse(ro(qt(j),"utf8"));return O.schemaVersion===1&&O.workspaceId&&O.apiUrl?O:null}catch{return null}}function xn(j,O){Wt(qt(j),O);let N=Gt(En(j),".hlix",".gitignore");if(!rr(N))nr(N,`state.json
|
|
8
|
+
`,{mode:420,flag:"wx"});so(N);let L=Gt(En(j),".hlixignore");if(!sr(L,{throwIfNoEntry:!1}))nr(L,`# Additional project-local paths to exclude from Hlix snapshots.
|
|
9
|
+
`,{mode:420,flag:"wx"})}function or(j,O){Wt(oo(j),{...O,snapshotOnly:O.snapshotOnly??i(j)?.snapshotOnly,includedPaths:O.includedPaths??i(j)?.includedPaths})}function i(j){try{let O=JSON.parse(ro(oo(j),"utf8"));return O.schemaVersion===1&&O.repoId&&/^[a-f0-9]{40}$/.test(O.commitSha)?O:null}catch{return null}}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=Ia(j);for(;;){let N=xt(O);if(N)return{root:O,config:N};let L=Ca(O);if(L===O)return null;O=L}}function ao(j){try{return _a(j).isDirectory()}catch{return!1}}function Pn(j){if(typeof j!=="string")return;let O=j.trim();return O?O:void 0}var io=(j,O)=>j.replace(/\/+$/,"")===O.replace(/\/+$/,"");function r(j){let{env:O,flags:N,cwd:L}=j,F=t(L),H=Qs(O),M=H?O.HLIX_API_KEY?"env":O.HLIX_SESSION_TOKEN?"session":"file":null,U=M==="file"?H:null,D=Pn(N["base-url"]),J=Pn(O.HLIX_BASE_URL),B=Pn(N.workspace),G=Pn(O.HLIX_WORKSPACE_ID),q=D??J??F?.config.apiUrl??U?.baseUrl??it,Q=D?"flag":J?"env":F?.config.apiUrl?"project":U?.baseUrl?"credential":"default",te=B??G??F?.config.workspaceId??U?.organizationId??null,V=B?"flag":G?"env":F?.config.workspaceId?"project":U?.organizationId?"credential":null;return{baseUrl:q,baseUrlSource:Q,workspaceId:te,workspaceSource:V,credential:H,credentialSource:M,credentialPath:Ue(O),binding:F,conflict:Ra(F,{flagBaseUrl:D,envBaseUrl:J,flagWorkspace:B,envWorkspace:G})}}function Ra(j,O){if(!j)return null;let N=`${j.root} is bound to`,L="Drop the override, or point --cwd at a folder bound to it.";if(O.flagWorkspace&&O.flagWorkspace!==j.config.workspaceId)return`${N} workspace ${j.config.workspaceId}, but --workspace names ${O.flagWorkspace}. ${L}`;if(O.envWorkspace&&O.envWorkspace!==j.config.workspaceId)return`${N} workspace ${j.config.workspaceId}, but HLIX_WORKSPACE_ID names ${O.envWorkspace}. ${L}`;if(O.flagBaseUrl&&!io(O.flagBaseUrl,j.config.apiUrl))return`${N} ${j.config.apiUrl}, but --base-url names ${O.flagBaseUrl}. ${L}`;if(O.envBaseUrl&&!io(O.envBaseUrl,j.config.apiUrl))return`${N} ${j.config.apiUrl}, but HLIX_BASE_URL names ${O.envBaseUrl}. ${L}`;return null}import{resolve as Qa}from"node:path";import{parseArgs as ec}from"node:util";import Ta from"openapi-fetch";function ir(j){return Ta({baseUrl:j.baseUrl,headers:j.headers,fetch:j.fetch})}var Pt=(j)=>({kind:"apiKey",apiKey:j});var ar=(j)=>({kind:"bearer",token:j});function Aa(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 Oa(j){return j?{"X-Organization-Id":j}:{}}function co(j,O){return{...Aa(j),...Oa(O)}}function Na(j){if(typeof j!=="object"||j===null)return null;let{error:O}=j;return typeof O==="string"?O:null}class _e 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 $t extends _e{issues;constructor(j,O,N){super(j,O);this.issues=N}}class zt extends _e{}class Kt extends _e{}class Vt extends _e{}class at extends _e{}class ct extends _e{}class lt extends _e{retryAfter;constructor(j,O,N){super(j,O);this.retryAfter=N}}class Xt extends _e{}class dt extends _e{}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 La(j){if(typeof j!=="object"||j===null)return null;let O=j;if(O.success!==!1)return null;let N=O.error?.message;if(typeof N!=="string")return null;try{let L=JSON.parse(N);return Array.isArray(L)?L:[]}catch{return[]}}function Fa(j){let O=j.get("retry-after");if(!O)return null;let N=Number(O);return Number.isFinite(N)&&N>=0?N:null}function pt(j,O,N){let L={status:j.status,body:O,requestId:j.headers.get("x-request-id"),method:N.method,url:N.url},F=Na(O),H=`${N.method} ${N.url} failed with ${j.status}`,M=La(O);if(M)return new $t(`${N.method} ${N.url}: request body failed validation`,L,M);let U=F??H;switch(j.status){case 400:return new zt(U,L);case 401:return new Kt(U,L);case 403:return new Vt(U,L);case 404:return new at(U,L);case 409:return new ct(U,L);case 429:return new lt(U,L,Fa(j.headers));case 501:return new Xt(U,L);default:return j.status>=500?new dt(U,L):new _e(U,L)}}var lo=new Set(["GET","HEAD","PUT","DELETE","OPTIONS","TRACE"]);function $n(j){return lo.has(j.toUpperCase())}var Ha=new Set([429,500,502,503,504]);function Ma(j){return Ha.has(j)}var cr={attempts:3,baseDelayMs:200,maxDelayMs:5000};function Yt(j,O,N,L=Math.random){if(N!==null)return Math.min(N*1000,O.maxDelayMs);let F=Math.min(O.baseDelayMs*2**j,O.maxDelayMs);return Math.round(L()*F)}function lr(j){if(!$n(j.method))return!1;if(j.attempt+1>=j.policy.attempts)return!1;return j.status===null||Ma(j.status)}var Ua=(j)=>new Promise((O)=>setTimeout(O,j));function Da(j){let O=j.headers.get("retry-after");if(!O)return null;let N=Number(O);return Number.isFinite(N)&&N>=0?N:null}function po(j){let{base:O,policy:N}=j,L=j.sleep??Ua,F=j.random??Math.random;return async(H)=>{let M=H.method.toUpperCase(),U=$n(M)?H.clone():null;for(let D=0;;D+=1){let J=D===0?H:U.clone(),B;try{B=await O(J)}catch(G){if(!U||!lr({method:M,attempt:D,policy:N,status:null}))throw new Ye(`${M} ${H.url}: ${G instanceof Error?G.message:String(G)}`,{method:M,url:H.url,cause:G});await L(Yt(D,N,null,F));continue}if(!lr({method:M,attempt:D,policy:N,status:B.status}))return B;if(!U)return B;await L(Yt(D,N,Da(B),F))}}}function ae(j,O){if(j.response.ok)return j.data;throw pt(j.response,j.error??j.data,O)}var Zt=(j)=>typeof j==="string"?j:"";function dr(j){let O;try{O=JSON.parse(j)}catch{return null}if(typeof O!=="object"||O===null)return null;let N=O;switch(N.type){case"idle":return{type:"idle"};case"done":return{type:"done"};case"active":return typeof N.runId==="string"?{type:"active",runId:N.runId}:{type:"active"};case"on_chat_model_stream":return{type:"on_chat_model_stream",delta:Zt(N.delta)};case"reasoning":return{type:"reasoning",delta:Zt(N.delta)};case"on_tool_start":return{type:"on_tool_start",name:Zt(N.name),input:N.input};case"on_tool_end":return{type:"on_tool_end",name:Zt(N.name),output:N.output};case"error":return{type:"error",message:Zt(N.message)};default:return null}}var pr=(j)=>j.type==="done"||j.type==="idle"||j.type==="error";var Ja=()=>({event:null,data:[],id:null,retry:null});function uo(j,O,N){switch(O){case"event":j.event=N;return;case"data":j.data.push(N);return;case"id":if(!N.includes("\x00"))j.id=N;return;case"retry":{if(/^\d+$/.test(N))j.retry=Number(N);return}default:return}}function fo(j){let O=j.data.join(`
|
|
10
|
+
`),{event:N,id:L}=j;if(j.data=[],j.event=null,O==="")return null;return{event:N,data:O,id:L,retry:j.retry}}function mo(j,O){if(O==="")return fo(j);if(O.startsWith(":"))return null;let N=O.indexOf(":");if(N===-1)return uo(j,O,""),null;let L=O.slice(0,N),F=O.slice(N+1);if(F.startsWith(" "))F=F.slice(1);return uo(j,L,F),null}function Ba(j){let O=[],N=0;for(let L=0;L<j.length;L+=1){let F=j[L];if(F!==`
|
|
11
|
+
`&&F!=="\r")continue;if(O.push(j.slice(N,L)),F==="\r"&&j[L+1]===`
|
|
12
|
+
`)L+=1;N=L+1}return{lines:O,rest:j.slice(N)}}async function*_n(j,O){let N=j.getReader(),L=new TextDecoder,F=Ja(),H="",M=()=>void N.cancel().catch(()=>{});O?.addEventListener("abort",M,{once:!0});try{for(;;){let{done:D,value:J}=await N.read();if(D)break;H+=L.decode(J,{stream:!0});let{lines:B,rest:G}=Ba(H);H=G;for(let q of B){let Q=mo(F,q);if(Q)yield Q}if(O?.aborted)return}if(H+=L.decode(),H!==""){let D=mo(F,H);if(D)yield D}let U=fo(F);if(U)yield U}finally{O?.removeEventListener("abort",M),N.releaseLock()}}function Ze(j,O){return new Promise((N)=>{if(O?.aborted)return N();let L=setTimeout(F,j);function F(){clearTimeout(L),O?.removeEventListener("abort",F),N()}O?.addEventListener("abort",F,{once:!0})})}var mr=()=>crypto.randomUUID();function yo(j){return{threadId:j.threadId,runId:j.runId??mr(),state:{},messages:[{id:j.messageId??mr(),role:"user",content:j.text}],tools:[],context:[],forwardedProps:j.forwardedProps??{}}}function wo(j,O){return{threadId:j,runId:mr(),state:{},messages:[],tools:[],context:[],...O?{lastSeenEventId:O}:{}}}function fr(j){let O=j.metadata;if(typeof O!=="object"||O===null)return;let N=O.eventId;return typeof N==="string"&&N?N:void 0}function gr(j){let O;try{O=JSON.parse(j)}catch{return null}if(typeof O!=="object"||O===null)return null;return typeof O.type==="string"?O:null}function ut(j,O={}){if(O.taskId)return`project:${j}:task:${O.taskId}`;if(O.cycleId)return`project:${j}:cycle:${O.cycleId}`;return`project:${j}`}var Ga=new Set(["done","merged","failed","pr_created","ci_passing"]),Wa=new Set(["done","pr_created","failed","canceled"]);function hr(j,O){let N=j.tasks.find((M)=>M.id===O);if(!N)return{state:"running",task:N};let L=N.cycleId?j.cycles.find((M)=>M.id===N.cycleId):void 0;if(!(!N.cycleId||L!==void 0&&Wa.has(L.status)))return{state:"running",task:N};if(Ga.has(N.status))return{state:"finished",task:N};if(!L)return{state:"running",task:N};let H=L?.status==="canceled"?"Task cycle was canceled":L?.status==="failed"?"Task cycle failed":"Task cycle ended before this task completed";return{state:"unmet",task:N,reason:H}}async function*yr(j){let O;for await(let N of j){if(N.type==="STATE_SNAPSHOT")O=structuredClone(N.snapshot);else if(N.type==="STATE_DELTA"){if(O===void 0)continue;O=vo(O,N.delta)}else if(N.type!=="CUSTOM"||O===void 0)continue;yield{state:O,event:N}}}function wr(j){if(j==="")return[];if(!j.startsWith("/"))throw Error(`Invalid JSON pointer: ${j}`);return j.slice(1).split("/").map((O)=>O.replace(/~1/g,"/").replace(/~0/g,"~"))}function vr(j,O){let N=j;for(let L of O.slice(0,-1)){if(typeof N!=="object"||N===null)throw Error(`Path not found: /${O.join("/")}`);N=N[L]}if(typeof N!=="object"||N===null)throw Error(`Path not found: /${O.join("/")}`);return{parent:N,key:O[O.length-1]}}function Cn(j,O,N){if(O==="-"&&N)return j.length;let L=Number(O);if(!/^(0|[1-9]\d*)$/.test(O)||L>j.length||!N&&L===j.length)throw Error(`Invalid array index: ${O}`);return L}function go(j,O){let N=wr(O);if(N.length===0)return j;let{parent:L,key:F}=vr(j,N);if(Array.isArray(L))return L[Cn(L,F,!1)];if(!(F in L))throw Error(`Path not found: ${O}`);return L[F]}function ho(j,O){let{parent:N,key:L}=vr(j,wr(O));if(Array.isArray(N))return N.splice(Cn(N,L,!1),1)[0];if(!(L in N))throw Error(`Path not found: ${O}`);let F=N[L];return delete N[L],F}function ur(j,O,N,L){let F=wr(O);if(F.length===0)return N;let{parent:H,key:M}=vr(j,F);if(Array.isArray(H))if(L==="add")H.splice(Cn(H,M,!0),0,N);else H[Cn(H,M,!1)]=N;else{if(L==="replace"&&!(M in H))throw Error(`Path not found: ${O}`);H[M]=N}return j}function vo(j,O){let N=structuredClone(j);for(let L of O)switch(L.op){case"add":case"replace":N=ur(N,L.path,structuredClone(L.value),L.op);break;case"remove":ho(N,L.path);break;case"copy":N=ur(N,L.path,structuredClone(go(N,L.from)),"add");break;case"move":{let F=ho(N,L.from);N=ur(N,L.path,F,"add");break}case"test":if(JSON.stringify(go(N,L.path))!==JSON.stringify(L.value))throw Error(`Test failed at ${L.path}`);break;default:throw Error(`Unknown patch operation: ${L.op}`)}return N}var qa={attempts:6,baseDelayMs:500,maxDelayMs:15000};function za(j){if(j instanceof dt||j instanceof lt)return!0;return!(j instanceof _e)}class _t{raw;baseUrl;headers;fetcher;constructor(j){this.baseUrl=j.baseUrl.replace(/\/+$/,"");let O=co(j.credential,j.organizationId),N=new Set(Object.keys(O).map((H)=>H.toLowerCase()));this.headers={...Object.fromEntries(Object.entries(j.headers??{}).filter(([H])=>!N.has(H.toLowerCase()))),...O};let L={...cr,...j.retry},F=j.fetch??((H)=>globalThis.fetch(H));this.fetcher=po({base:F,policy:L}),this.raw=ir({baseUrl:this.baseUrl,headers:this.headers,fetch:this.fetcher})}at(j,O){return{method:j,url:`${this.baseUrl}${O}`}}workspaces={list:async(j={})=>ae(await this.raw.GET("/v1/api/workspaces",j),this.at("GET","/v1/api/workspaces"))};projects={list:async()=>ae(await this.raw.GET("/v1/api/projects"),this.at("GET","/v1/api/projects")),get:async(j,O={})=>ae(await this.raw.GET("/v1/api/projects/{id}",{...O,params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}`)),create:async(j)=>ae(await this.raw.POST("/v1/api/projects",{body:j}),this.at("POST","/v1/api/projects")),delete:async(j)=>ae(await this.raw.DELETE("/v1/api/projects/{id}",{params:{path:{id:j}}}),this.at("DELETE",`/v1/api/projects/${j}`)),start:async(j,O)=>ae(await this.raw.POST("/v1/api/projects/{id}/start",{params:{path:{id:j}},body:O}),this.at("POST",`/v1/api/projects/${j}/start`)),stop:async(j)=>ae(await this.raw.POST("/v1/api/projects/{id}/stop",{params:{path:{id:j}}}),this.at("POST",`/v1/api/projects/${j}/stop`)),resume:async(j)=>ae(await this.raw.POST("/v1/api/projects/{id}/resume",{params:{path:{id:j}}}),this.at("POST",`/v1/api/projects/${j}/resume`)),status:async(j,O={})=>ae(await this.raw.GET("/v1/api/projects/{id}/status",{...O,params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}/status`)),deliver:async(j)=>ae(await this.raw.POST("/v1/api/projects/{id}/delivery",{params:{path:{id:j}}}),this.at("POST",`/v1/api/projects/${j}/delivery`)),attachGithubRepository:async(j,O)=>ae(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)=>ae(await this.raw.GET("/v1/api/projects/{id}/terminal",{params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}/terminal`)),observeAgent:(j,O,N)=>this.observeAgent(j,O,N),workspace:(j)=>({environment:async()=>ae(await this.raw.GET("/v1/api/projects/{id}/environment",{params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}/environment`)),fs:async(O)=>ae(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)=>ae(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)=>ae(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)=>ae(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)=>ae(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,N)=>ae(await this.raw.DELETE("/v1/api/secrets/project/{projectId}/entries/{key}",{params:{path:{projectId:j,key:O},...N===void 0?{}:{query:{source:N}}}}),this.at("DELETE",`/v1/api/secrets/project/${j}/entries/${encodeURIComponent(O)}`)),exportEntries:async(j,O={})=>{let N=`/v1/api/secrets/project/${j}/export`,L=`${this.baseUrl}${N}`,F=await this.fetcher(new Request(L,{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(!F.ok)throw pt(F,await F.json().catch(()=>{return}),{method:"POST",url:L});return F.text()}};repos={access:async(j,O,N="read")=>ae(await this.raw.POST("/v1/api/projects/{id}/repos/{repoId}/access",{params:{path:{id:j,repoId:O}},body:{scope:N}}),this.at("POST",`/v1/api/projects/${j}/repos/${O}/access`)),head:async(j,O,N={})=>ae(await this.raw.GET("/v1/api/projects/{id}/repos/{repoId}/head",{...N,params:{path:{id:j,repoId:O}}}),this.at("GET",`/v1/api/projects/${j}/repos/${O}/head`)),protectedFiles:async(j)=>ae(await this.raw.GET("/v1/api/projects/{id}/protected-files",{params:{path:{id:j}}}),this.at("GET",`/v1/api/projects/${j}/protected-files`)),watch:(j,O,N={})=>this.watchRepo(j,O,N)};resources={importSkill:async(j,O)=>ae(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)=>ae(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)=>ae(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 N=null;try{N=await j.json()}catch{N=await j.text().catch(()=>null)}throw pt(j,N,{method:"PUT",url:O})}tasks={list:async(j)=>ae(await this.raw.GET("/v1/api/tasks",{params:{query:j??{}}}),this.at("GET","/v1/api/tasks")),get:async(j)=>ae(await this.raw.GET("/v1/api/tasks/{id}",{params:{path:{id:j}}}),this.at("GET",`/v1/api/tasks/${j}`)),create:async(j)=>ae(await this.raw.POST("/v1/api/tasks",{body:j}),this.at("POST","/v1/api/tasks")),update:async(j,O)=>ae(await this.raw.PATCH("/v1/api/tasks/{id}",{params:{path:{id:j}},body:O}),this.at("PATCH",`/v1/api/tasks/${j}`)),listComments:async(j)=>ae(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)=>ae(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)=>ae(await this.raw.GET("/v1/api/tasks/{id}/review",{params:{path:{id:j}}}),this.at("GET",`/v1/api/tasks/${j}/review`))};modelConfig={setProjectHarness:async(j,O)=>ae(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)=>ae(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)=>ae(await this.raw.PUT("/v1/api/model-config/harness",{body:{harness:j}}),this.at("PUT","/v1/api/model-config/harness")),clearHarness:async()=>ae(await this.raw.DELETE("/v1/api/model-config/harness"),this.at("DELETE","/v1/api/model-config/harness")),resolvedHarness:async()=>ae(await this.raw.GET("/v1/api/model-config/harness/resolved"),this.at("GET","/v1/api/model-config/harness/resolved")),resolvedProjectHarness:async(j)=>ae(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)=>ae(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)=>ae(await this.raw.GET("/v1/api/cycles",{params:{query:j??{}}}),this.at("GET","/v1/api/cycles")),get:async(j)=>ae(await this.raw.GET("/v1/api/cycles/{id}",{params:{path:{id:j}}}),this.at("GET",`/v1/api/cycles/${j}`)),propose:async(j)=>ae(await this.raw.POST("/v1/api/cycles",{body:j}),this.at("POST","/v1/api/cycles"))};chat={send:async(j)=>ae(await this.raw.POST("/v1/api/chat/turns",{body:j}),this.at("POST","/v1/api/chat/turns")),turn:async(j,O)=>ae(await this.raw.GET("/v1/api/chat/turns/{turnId}",{params:{path:{turnId:j},query:O}}),this.at("GET",`/v1/api/chat/turns/${j}`))};live={run:(j,O,N)=>this.liveStream(`/agent/${j}/run`,yo(O),N),connect:(j,O,N)=>this.liveStream(`/agent/${j}/connect`,wo(O,N?.lastSeenEventId),N),follow:(j,O,N={})=>this.followLive(j,O,N),stop:async(j,O,N)=>{let L=`/agent/${j}/stop/${encodeURIComponent(O)}`;return await(await this.livePost(L,N?{runId:N}:{})).json()},project:(j,O={})=>yr(this.live.follow("project-live",ut(j,O),O)),task:(j,O,N={})=>this.watchTask(j,O,N)};async*watchTask(j,O,N){let L="";for await(let{state:F}of this.live.project(j,{taskId:O,...N})){let H=hr(F,O),M=JSON.stringify(H);if(M===L)continue;if(L=M,yield H,H.state!=="running")return}}async*followLive(j,O,N){let L=N.retry??qa,F=N.lastSeenEventId,H=0;while(!N.signal?.aborted){let M=!1,U=null;try{for await(let D of this.live.connect(j,O,{...N.signal?{signal:N.signal}:{},...F?{lastSeenEventId:F}:{}})){let J=fr(D);if(J)F=J;if(D.type!=="STATE_SNAPSHOT"&&D.type!=="MESSAGES_SNAPSHOT")H=0;if(D.type==="RUN_STARTED"||D.type==="STATE_SNAPSHOT"||J)M=!0;if(yield D,D.type==="RUN_FINISHED"||D.type==="RUN_ERROR")return}if(!M)return}catch(D){if(N.signal?.aborted)return;if(!za(D))throw D;U=D}if(N.signal?.aborted)return;if(H+=1,H>=L.attempts)throw U??new Ye(`POST ${this.baseUrl}/v1/api/live/agent/${j}/connect: the stream kept closing`,{method:"POST",url:`${this.baseUrl}/v1/api/live/agent/${j}/connect`});await Ze(Yt(H,L,null),N.signal)}}async livePost(j,O,N){let L=`${this.baseUrl}/v1/api/live${j}`,F=await this.fetcher(new Request(L,{method:"POST",headers:{...this.headers,"content-type":"application/json",accept:"text/event-stream"},body:JSON.stringify(O),signal:N?.signal}));if(F.ok)return F;let H=null;try{H=await F.json()}catch{H=null}throw pt(F,H,{method:"POST",url:L})}async*liveStream(j,O,N){let L=await this.livePost(j,O,N);if(!L.body)return;try{for await(let F of _n(L.body,N?.signal)){let H=gr(F.data);if(!H)continue;if(yield H,H.type==="RUN_FINISHED"||H.type==="RUN_ERROR")return}}finally{L.body.cancel().catch(()=>{})}}pendingRequests={list:async(j)=>ae(await this.raw.GET("/v1/api/pending-requests",{params:{query:j??{}}}),this.at("GET","/v1/api/pending-requests")),resolve:async(j,O)=>ae(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)=>ae(await this.raw.GET("/v1/api/client-billing/invoices",{params:{query:j??{}}}),this.at("GET","/v1/api/client-billing/invoices")),get:async(j)=>ae(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)=>ae(await this.raw.POST("/v1/api/client-billing/invoices",{body:j}),this.at("POST","/v1/api/client-billing/invoices")),issue:async(j)=>ae(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)=>ae(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)=>ae(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={})=>ae(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,N){let L=`/v1/api/projects/${j}/agents/${O}/observe`;for await(let F of this.stream(L,N)){let H=dr(F.data);if(!H)continue;if(yield H,pr(H))return}}async*watchRepo(j,O,N){let L;while(!N.signal?.aborted){let F=await this.repos.head(j,O,N);if(F.commitSha!==L)L=F.commitSha,yield{commitSha:L};await Ze(15000,N.signal)}}async*stream(j,O){let N=`${this.baseUrl}${j}`,L=new Request(N,{headers:{...this.headers,accept:"text/event-stream"},signal:O?.signal}),F=await globalThis.fetch(L);if(!F.ok||!F.body){let H=null;try{H=await F.json()}catch{H=null}throw pt(F,H,{method:"GET",url:N})}yield*_n(F.body,O?.signal)}}var Ka=/\x1b(?:\[[0-?]*[ -/]*[@-~]?|\][^\x07\x1b]*(?:\x07|\x1b\\)?|[PX^_][^\x1b]*(?:\x1b\\)?|[\x20-\x7e]?)|\x9b[0-?]*[ -/]*[@-~]?/g,Va=/[\x00-\x08\x0b-\x1f\x7f-\x9f]/g,Xa=/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g,Ya=/(?<![\p{Extended_Pictographic}\p{Emoji_Modifier}\uFE0F])\u200D|\u200D(?!\p{Extended_Pictographic})|[^\P{Cf}\u200D]/gu,Za=/[\u2028\u2029]/g;function s(j,O={}){return j.replace(Ka,"").replace(O.carriageReturn?Xa:Va,"").replace(Ya,"").replace(Za,`
|
|
13
|
+
`)}function br(j){if(j instanceof e)return{code:j.code,status:null};if(j instanceof $t)return{code:"invalid_request",status:400};if(j instanceof zt)return{code:"bad_request",status:400};if(j instanceof Kt)return{code:"unauthenticated",status:401};if(j instanceof Vt)return{code:"forbidden",status:403};if(j instanceof at)return{code:"not_found",status:404};if(j instanceof ct)return{code:"conflict",status:409};if(j instanceof lt)return{code:"rate_limited",status:429};if(j instanceof Xt)return{code:"not_implemented",status:501};if(j instanceof dt)return{code:"server_error",status:j.status};if(j instanceof Ye)return{code:"unreachable",status:null};return{code:"unknown",status:null}}var In=(j)=>{if(j instanceof $t&&j.issues.length>0){let O=j.issues.map((N)=>{let L=N;return` - ${Array.isArray(L.path)&&L.path.length>0?`${L.path.join(".")}: `:""}${typeof L.message==="string"?L.message:JSON.stringify(N)}`});return`${j.message}
|
|
14
|
+
${O.join(`
|
|
15
|
+
`)}`}return j instanceof Error?j.message:String(j)};function n(j,O){let N=r({env:j,flags:O.flags,cwd:O.cwd});if(N.conflict)throw new e("workspace_mismatch",N.conflict);if(!N.credential)throw new e("unauthenticated","No credential. Run `hlix auth login`, or set HLIX_API_KEY for CI.");return new _t({baseUrl:N.baseUrl,credential:N.credential.sessionToken?ar(N.credential.sessionToken):Pt(N.credential.apiKey),...N.workspaceId?{organizationId:N.workspaceId}:{}})}function bo(j){let O=Math.max(...j.map((L)=>L.name.length));return`hlix — the hlix control-plane CLI
|
|
16
|
+
|
|
17
|
+
Usage:
|
|
18
|
+
hlix <command> [options]
|
|
19
|
+
|
|
20
|
+
Commands:
|
|
21
|
+
${[` hlix ${"".padEnd(O)} Open Hlix Code (interactive)`,...j.map((L)=>` hlix ${L.name.padEnd(O)} ${L.summary}`)].join(`
|
|
22
|
+
`)}
|
|
23
|
+
|
|
24
|
+
Options:
|
|
25
|
+
--json Machine-readable output (a versioned, stable contract)
|
|
26
|
+
--cwd <dir> Operate on another directory instead of the current one
|
|
27
|
+
--workspace <id> Workspace to act in, overriding the folder's binding
|
|
28
|
+
--base-url <url> API to talk to, overriding the folder's binding
|
|
29
|
+
--help Show this help
|
|
30
|
+
--version Show the installed CLI version
|
|
31
|
+
|
|
32
|
+
Hlix Code (hlix with no command):
|
|
33
|
+
--sandbox <choice> cloud, docker or local; --local is short for local
|
|
34
|
+
--docker-image <r> image the docker sandbox runs in
|
|
35
|
+
--harness <name> which coder does the work
|
|
36
|
+
--project <id> project to act in, when this folder is not bound
|
|
37
|
+
-p "<prompt>" one turn, print the answer, exit
|
|
38
|
+
--json with -p: one JSON object per event instead of prose
|
|
39
|
+
--allow-writes with -p: let the turn change files and run commands
|
|
40
|
+
--yolo approve every tool call for the whole session
|
|
41
|
+
|
|
42
|
+
A command targets the workspace named by, in order: an explicit flag, the
|
|
43
|
+
HLIX_* environment, the nearest .hlix/config.json, then the stored credential.
|
|
44
|
+
Run \`hlix status\` to see which one applied.
|
|
45
|
+
`}function So(j,O){let N=[...Array(O.length+1).keys()];for(let L=1;L<=j.length;L+=1){let F=[L];for(let H=1;H<=O.length;H+=1)F[H]=Math.min(N[H]+1,F[H-1]+1,N[H-1]+(j[L-1]===O[H-1]?0:1));N=F}return N[O.length]}function tc(j,O,N){let L=/Unknown option '--([^'=]+)/.exec(N)?.[1];if(!L)return N;let F=O.findIndex((D)=>D.startsWith("-")),H=F===-1?O:O.slice(0,F),M=new Set(["json","help","version","cwd","workspace","base-url",...Rn(j,H)?.command.options??[]]),U=null;for(let D of M){let J=So(L,D);if(J<=2&&(!U||J<U.distance))U={name:D,distance:J}}return U?`${N}
|
|
46
|
+
Did you mean --${U.name}?`:N}function ko(j,O){let N=new Set;for(let H of j)N.add(H.name),N.add(H.name.split(" ")[0]);let L=null;for(let H of N){let M=So(O,H);if(M<=2&&(!L||M<L.distance))L={name:H,distance:M}}if(!L)return null;if(j.some((H)=>H.name===L.name))return L.name;let F=j.filter((H)=>H.name.startsWith(`${L.name} `)).sort((H,M)=>H.name.length-M.name.length)[0];return F?F.name:L.name}function Rn(j,O){for(let N of[...j].sort((L,F)=>F.name.length-L.name.length)){let L=N.name.split(" ");if(L.every((F,H)=>O[H]===F))return{command:N,rest:O.slice(L.length)}}return null}function nc(j,O,N){let L=tc(j,O,N);if(!/^Unknown option '/.test(N))return L;let F=L.replace(/\. To specify a positional argument[\s\S]*?after '--'[^\n]*/,"."),H=Rn(j,O.filter((M)=>!M.startsWith("-")));return H?`${F}
|
|
47
|
+
|
|
48
|
+
${H.command.usage}`:F}async function c(j,O,N){if(O.some((X)=>X==="--api-key"||X.startsWith("--api-key=")))return N.stderr("error: API keys are never accepted as command-line arguments. Run `hlix auth login` and use the hidden prompt.\n"),2;let L;try{L=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(X){let re=O.includes("--json"),ue=nc(j,O,In(X));if(N.onFailure?.({code:"invalid_usage",message:ue,status:null}),re)N.stdout(se(Jt("cli",{code:"invalid_usage",message:ue,status:null})));else N.stderr(`${ue}
|
|
49
|
+
`);return 2}let F=L.values.json===!0,H=L.positionals;if(L.values.version===!0){let{version:X}=await import("./package-qbwm0yj5.js");return N.stdout(`${X}
|
|
50
|
+
`),0}if(H.length===0||L.values.help===!0){let X=Rn(j,H);return N.stdout(X?`${X.command.usage}
|
|
51
|
+
`:bo(j)),H.length===0&&L.values.help!==!0?1:0}let M=Rn(j,H);if(!M){let X=H.join(" "),re=ko(j,X)??ko(j,H[0]),ue=re?`Unknown command: ${X}
|
|
52
|
+
Did you mean \`hlix ${re}\`?`:`Unknown command: ${X}`;if(N.onFailure?.({code:"unknown_command",message:ue,status:null}),F)N.stdout(se(Jt(X,{code:"unknown_command",message:ue,status:null})));else N.stderr(`${ue}
|
|
53
|
+
|
|
54
|
+
${bo(j)}`);return 2}let U=new Set(["json","help","version","cwd","workspace","base-url"]),D=new Set(M.command.options??[]),J=Object.entries(L.values).filter(([X,re])=>re!==void 0&&!U.has(X)&&!D.has(X)).map(([X])=>`--${X}`),B=M.command.args??{min:0,max:0},G=M.rest.length<B.min?{code:"missing_argument",message:M.command.usage.split(`
|
|
55
|
+
`)[0]}:M.rest.length>B.max?{code:"invalid_usage",message:M.command.usage.split(`
|
|
56
|
+
`)[0]}:null,q=typeof L.values.cwd==="string"?L.values.cwd:void 0,Q=Qa(q??"."),te=q!==void 0&&!ao(Q)?{code:"invalid_usage",message:`--cwd is not a directory: ${Q}`}:null,V=J.length>0?{code:"invalid_usage",message:`Unsupported option for ${M.command.name}: ${J.join(", ")}`}:te??G;if(V){if(N.onFailure?.({...V,status:null}),F)N.stdout(se(Jt(M.command.name,{...V,status:null})));else{let X=M.command.usage.startsWith(V.message)?M.command.usage:`${V.message}
|
|
57
|
+
|
|
58
|
+
${M.command.usage}`;N.stderr(`error: ${X}
|
|
59
|
+
`)}return 2}let z=L.values,Z={...N,args:M.rest,json:F,flags:z,cwd:Q,requireClient:(X)=>n(N.env,{cwd:X??Q,flags:z})};try{return await M.command.run(Z)}catch(X){let{code:re,status:ue}=br(X);if(N.onFailure?.({code:re,message:s(In(X)),status:ue,...X instanceof e&&X.details!==void 0?{details:X.details}:{}}),F)N.stdout(se(Jt(M.command.name,{code:re,message:In(X),status:ue})));else if(N.stderr(`error: ${s(In(X))}
|
|
60
|
+
`),process.env.HLIX_DEBUG&&X instanceof Error&&X.stack)N.stderr(`${X.stack}
|
|
61
|
+
`);return re==="unauthenticated"||re==="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 jo=20000;function m(j){if(j===void 0)return;let O=typeof j==="number"?j:Number(j.trim());return Number.isInteger(O)&&O>=jo?O:void 0}var l=["cloud","docker","local"],ic={"claude-code":!0,codex:!0,"cursor-agent":!0,opencode:!0,goose:!0,"qwen-code":!0,pi:!0,hlix:!0},o=Object.keys(ic),g="hlix",Eo={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"},Ct=["dockerImage","harness","memoryTokens","model","sandbox","yolo"],kr=["projectId","workspaceId","apiUrl"];function Sr(j=process.env){return oc(j.HLIX_CONFIG_HOME??sc(),".hlix","config.json")}function xo(j=process.env){try{let O=JSON.parse(rc(Sr(j),"utf8"));return O.schemaVersion===1?O:null}catch{return null}}function f(j,O=process.env){let N=xo(O),L=t(j),F=L?.root??null,H=L?.config??null,M={},U={},D=(J)=>{let B=H?.[J],G=N?.[J];if(B!==void 0)M[J]=B,U[J]="project";else if(G!==void 0)M[J]=G,U[J]="global"};for(let J of Ct)D(J);for(let J of kr){let B=H?.[J];if(B!==void 0)M[J]=B,U[J]="project"}return{merged:M,sources:U,global:N,project:H,paths:{global:Sr(O),project:F?qt(F):null}}}function Po(j){return[...Ct,...kr].map((N)=>({key:N,value:j.merged[N]??null,source:j.sources[N]??"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"&&m(O)===void 0)return`memoryTokens must be a whole number of tokens, at least ${jo}; got "${O}".`;if(j==="dockerImage"&&O.trim()==="")return"dockerImage must not be empty.";if(j==="yolo"&&x(O)===void 0)return`yolo must be true or false; got "${O}".`;return null}function x(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 jr(j){if(Ct.includes(j))return j;let O=kr.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: ${Ct.join(", ")}.`)}function $o(j,O){let N=ac(j,O);if(N)throw new e("invalid_usage",N);return O}function y(j){if(j.scope==="global"){let L=Sr(j.env),F=xo(j.env)??{schemaVersion:1};return Wt(L,{...F,[j.key]:j.value}),L}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 N=qt(O.root);return Wt(N,{...O.config,[j.key]:j.value}),N}import{createHash as cc}from"node:crypto";import{mkdirSync as lc,readdirSync as Ao,readFileSync as dc,rmSync as pc,statSync as Oo,writeFileSync as uc}from"node:fs";import{homedir as mc,tmpdir as fc}from"node:os";import{basename as No,isAbsolute as gc,join as me,relative as hc}from"node:path";var a=(j=process.env)=>j.HOME??j.USERPROFILE??mc();function Re(j){try{if(!Oo(j).isFile())return null;return dc(j,"utf8")}catch{return null}}function yc(j){try{return Oo(j).isDirectory()}catch{return!1}}function It(j,O){try{return Ao(j,{withFileTypes:!0}).filter((N)=>N.isFile()&&N.name.endsWith(O)).map((N)=>me(j,N.name)).sort()}catch{return[]}}function wc(j){try{return Ao(j,{withFileTypes:!0}).filter((O)=>O.isDirectory()||O.isSymbolicLink()).map((O)=>me(j,O.name)).sort()}catch{return[]}}function xr(j){let O=j.replace(/^\uFEFF/,""),N=O.indexOf(`
|
|
62
|
+
`);if(!O.startsWith("---")||N===-1)return{fields:{},body:O.trim()};let L=O.indexOf(`
|
|
63
|
+
---`,N);if(L===-1)return{fields:{},body:O.trim()};let F={};for(let M of O.slice(N+1,L).split(`
|
|
64
|
+
`)){let U=/^([A-Za-z_][\w-]*)\s*:\s*(.*)$/.exec(M);if(!U)continue;F[U[1]]=U[2].trim().replace(/^["']|["']$/g,"")}let H=O.indexOf(`
|
|
65
|
+
`,L+1);return{fields:F,body:H===-1?"":O.slice(H+1).trim()}}function vc(j){let O=j.trimStart(),N=/^"((?:[^"\\]|\\.)*)"/.exec(O)??/^'([^']*)'/.exec(O);if(N)return N[1].replace(/\\"/g,'"').replace(/\\n/g,`
|
|
66
|
+
`);if(O.startsWith("["))return[...O.matchAll(/"((?:[^"\\]|\\.)*)"|'([^']*)'/g)].map((F)=>F[1]??F[2]??"");if(O.startsWith("{")){let F={};for(let H of O.matchAll(/([A-Za-z0-9_.-]+)\s*=\s*"((?:[^"\\]|\\.)*)"/g))F[H[1]]=H[2].replace(/\\"/g,'"');return F}let L=/^[^\s#]+/.exec(O)?.[0];if(L===void 0)return;if(L==="true"||L==="false")return L==="true";if(/^-?\d+(\.\d+)?$/.test(L))return Number(L);return L}function Lo(j){let O={"":{}},N="",L=j.split(`
|
|
67
|
+
`);for(let F=0;F<L.length;F+=1){let M=L[F].trim();if(!M||M.startsWith("#"))continue;let U=/^\[\[?([^\]]+)\]\]?$/.exec(M);if(U){N=U[1].trim(),O[N]??={};continue}let D=/^([A-Za-z0-9_.-]+|"[^"]+")\s*=\s*(.*)$/.exec(M);if(!D)continue;let J=D[1].replace(/^"|"$/g,""),B=D[2];if(B.startsWith('"""')){let q=[],Q=B.slice(3);if(Q.includes('"""'))q.push(Q.slice(0,Q.indexOf('"""')));else{if(Q)q.push(Q);while(F+1<L.length){F+=1;let te=L[F],V=te.indexOf('"""');if(V===-1){q.push(te);continue}q.push(te.slice(0,V));break}}O[N][J]=q.join(`
|
|
68
|
+
`).replace(/^\n/,"");continue}let G=vc(B);if(G!==void 0)O[N][J]=G}return O}function Er(j,O){return j.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g,(N,L,F)=>{let H=O[L];return H!==void 0&&H!==""?H:F??""})}var _o=(j,O)=>{let N={};for(let[L,F]of Object.entries(j))if(typeof F==="string")N[L]=Er(F,O);return N},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 N=me(j,".clinerules"),L=yc(N)?It(N,".md"):[N],F=[];for(let H of L){let M=Re(H)?.trim();if(M)F.push({path:H,source:"cline",scope:O,content:M})}return F}function Ec(j,O,N){let{fields:L,body:F}=xr(O);if(L.alwaysApply==="false")return{path:j,source:"cursor",scope:N,reason:"alwaysApply: false"};if(!F)return{path:j,source:"cursor",scope:N,reason:"no rule body"};let H=L.globs?.replace(/^\[|\]$/g,"").trim();return{path:j,source:"cursor",scope:N,content:F,...H?{note:`Applies to: ${H}`}:{}}}var xc=["AGENTS.md","CLAUDE.md"],Fo=["",".claude"],_=["commands"];function Pc(j,O){let N=[],L=new Set;for(let F of[...Fo,O])for(let H of xc){let M=me(j,F,H),U=Re(M)?.trim();if(!U||L.has(U))continue;L.add(U),N.push({path:M,content:U})}return N}function Co(j,O){return Pc(j,O).map((N)=>N.content)}var h=["AGENTS.md","CLAUDE.md","GEMINI.md"];function Pr(j,O){for(let N of h)for(let L of[...Fo,O]){let F=me(j,L,N),H=Re(F)?.trim();if(H)return{path:F,content:H}}return null}var $r=(j=process.env)=>me(j.HLIX_CONFIG_HOME??me(a(j),".hlix"),"AGENTS.md");function w(j){let O=j.env??process.env,N=$r(O),L=Re(N)?.trim();return{global:L?{path:N,content:L}:null,project:Pr(j.cwd,j.configDir)}}var Io=(j)=>{let O=Math.round(j.length/4);return O>=1000?`${(O/1000).toFixed(1)}k tokens`:`${O} tokens`};function A(j,O,N=process.env){let L=[...j.global?[Mo(j.global.path,N)]:[],...j.project?[en(j.project.path,O)]:[]];return L.length===0?"":`rules: ${L.join(" + ")}`}function b(j,O,N=process.env,L=[]){let F=(H,M,U)=>M?`${H.padEnd(8)} ${U(M.path)} (${Io(M.content)})`:`${H.padEnd(8)} none`;return[F("user",j.global,(H)=>Mo(H,N)),F("project",j.project,(H)=>en(H,O)),...L.map((H)=>`${"nested".padEnd(8)} ${en(H.path,O)} (${Io(H.content)})`),"","User rules go first, the project's after, so the project wins a conflict.",L.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(`
|
|
69
|
+
`)}var Ro=[{dir:".claude",source:"claude",harnessReads:!0},{dir:".agents",source:"agents",harnessReads:!0},{dir:".hlix",source:"hlix",harnessReads:!0},{dir:".codex",source:"codex",harnessReads:!1}],$c=[{relative:me(".cursor","commands"),source:"cursor"},{relative:me(".codex","prompts"),source:"codex"}],_c=[{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 Ho(j){return[..._c,{relative:me(j,"mcp.json"),source:"hlix",key:"mcpServers",format:"json"}]}var Cc="found, not loaded (machine-wide; enable per project by copying into .hlix/mcp.json)",Ic=(j)=>Ho(j).filter((O)=>O.source!=="vscode");function Rc(j,O){if(!j||typeof j!=="object"||Array.isArray(j))return{reason:"not an object"};let N=j;if(N.enabled===!1||N.disabled===!0)return{reason:"disabled"};let L=typeof N.command==="string"&&N.command!=="",F=typeof N.url==="string"&&N.url!=="";if(L&&F)return{reason:'has both "command" and "url"'};if(L){let G=Array.isArray(N.args)?N.args.filter((Q)=>typeof Q==="string"):void 0,q=N.env&&typeof N.env==="object"&&!Array.isArray(N.env)?_o(N.env,O):void 0;return{config:{command:N.command,...G&&G.length>0?{args:G}:{},...q&&Object.keys(q).length>0?{env:q}:{}}}}if(!F)return{reason:'missing "command" or "url"'};let H=N.headers??N.http_headers,M=H&&typeof H==="object"&&!Array.isArray(H)?_o(H,O):{},U=N.bearer_token_env_var;if(typeof U==="string"&&/^[A-Za-z_][A-Za-z0-9_]*$/.test(U)&&!Object.keys(M).some((G)=>G.toLowerCase()==="authorization"))M.Authorization=`Bearer ${Er(`\${${U}}`,O)}`;let D=Object.entries(M).find(([G])=>G.toLowerCase()==="authorization")?.[1]?.trim(),J=D&&!/^Bearer$/i.test(D)&&!D.includes("${"),B=N.oauth===!0||N.oauth&&typeof N.oauth==="object"||typeof U==="string"&&!O[U];return{config:{url:Er(N.url,O),...B&&!J?{needsSignIn:!0}:{},...Object.keys(M).length>0?{headers:M}:{}}}}function To(j,O,N,L){let F=Re(j),H=[],M=[];if(F===null)return{servers:H,skipped:M};let U=[];if(O.format==="toml"){let D=Lo(F);U=Object.entries(D).filter(([J])=>J.startsWith(`${O.key}.`)).map(([J,B])=>[J.slice(O.key.length+1),B])}else try{let J=JSON.parse(F)?.[O.key];if(J&&typeof J==="object"&&!Array.isArray(J))U=Object.entries(J)}catch{return M.push({path:j,source:O.source,scope:N,reason:"not valid JSON"}),{servers:H,skipped:M}}for(let[D,J]of U){let B=Rc(J,L);if("reason"in B){M.push({path:j,source:O.source,scope:N,reason:`${D}: ${B.reason}`});continue}H.push({path:j,source:O.source,scope:N,name:D,config:B.config})}return{servers:H,skipped:M}}function Tc(j,O,N){let{fields:L,body:F}=xr(O);if(!F)return{path:j,source:"claude",scope:N,reason:"no instructions"};let H=L.tools?.replace(/^\[|\]$/g,"").split(",").map((M)=>M.trim()).filter(Boolean);return{path:j,source:"claude",scope:N,name:L.name||No(j,".md"),description:L.description??"",instructions:F,...H&&H.length>0&&H[0]!=="*"?{tools:H}:{},...L.model?{model:L.model}:{}}}function Ac(j){let O=Lo(j)[""]??{},N=typeof O.prompt==="string"?O.prompt.trim():"";if(!N)return null;return{description:typeof O.description==="string"?O.description:"",body:N}}function v(j,O,N={}){let L=N.configDir??".hlix",F=N.env??process.env,H={instructions:[],skills:[],commands:[],generatedCommands:[],mcpServers:[],subagents:[],skipped:[]},M=(te)=>{if("reason"in te)H.skipped.push(te);else H.instructions.push(te)};for(let te of bc){let V=me(j,te.relative),z=Re(V)?.trim();if(z)H.instructions.push({path:V,source:te.source,scope:"project",content:z})}for(let te of Sc)for(let V of It(me(j,te.relative),te.extension)){let z=Re(V);if(z===null)continue;if(te.source==="cursor"){M(Ec(V,z,"project"));continue}let{body:Z}=xr(z);if(Z)H.instructions.push({path:V,source:te.source,scope:"project",content:Z})}for(let te of jc(j,"project"))M(te);let U=Co(j,L),D=me(j,".codex","AGENTS.md"),J=Re(D)?.trim();if(J&&U.includes(J))H.skipped.push({path:D,source:"codex",scope:"project",reason:"same content as the project's AGENTS.md"});else if(J)H.instructions.push({path:D,source:"codex",scope:"project",content:J});for(let te of kc){let V=me(O,te.relative),z=Re(V)?.trim();if(z)H.instructions.push({path:V,source:te.source,scope:"global",content:z})}let B=me(O,".codex","AGENTS.md"),G=Re(B)?.trim(),q=Co(O,L);if(G&&q.includes(G))H.skipped.push({path:B,source:"codex",scope:"global",reason:"same content as the machine's AGENTS.md"});else if(G)H.instructions.push({path:B,source:"codex",scope:"global",content:G});for(let[te,V]of[[j,"project"],[O,"global"]])for(let z of Ro){let Z=me(te,z.dir===".hlix"?L:z.dir,"skills");if(!wc(Z).some((re)=>Re(me(re,"SKILL.md"))!==null))continue;H.skills.push({path:Z,source:z.source,scope:V,harnessReads:z.harnessReads})}for(let[te,V]of[[j,"project"],[O,"global"]]){for(let z of Ro){if(!z.harnessReads)continue;let Z=me(te,z.dir,"commands");if(It(Z,".md").length===0)continue;H.commands.push({path:Z,source:z.source,scope:V,harnessReads:!0})}for(let z of $c){let Z=me(te,z.relative);if(It(Z,".md").length===0)continue;H.commands.push({path:Z,source:z.source,scope:V})}for(let z of It(me(te,".gemini","commands"),".toml")){let Z=Re(z),X=Z===null?null:Ac(Z);if(!X){H.skipped.push({path:z,source:"gemini",scope:V,reason:"no prompt field"});continue}H.generatedCommands.push({path:z,source:"gemini",scope:V,name:No(z,".toml"),body:`---
|
|
70
|
+
description: ${X.description}
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
${X.body}
|
|
74
|
+
`})}}for(let te of Ho(L)){let V=To(me(j,te.relative),te,"project",F);H.skipped.push(...V.skipped);for(let z of V.servers){let Z=H.mcpServers.findIndex((X)=>X.name===z.name);if(Z===-1)H.mcpServers.push(z);else H.mcpServers[Z]=z}}for(let te of Ic(L)){let V=To(me(O,te.relative),te,"global",F);for(let z of V.servers)H.skipped.push({path:z.path,source:z.source,scope:"global",reason:`${z.name}: ${Cc}`})}let Q=[{dir:me(".claude","agents"),source:"claude"},{dir:me(L,"agents"),source:"hlix"}];for(let[te,V]of[[j,"project"],[O,"global"]])for(let z of Q.flatMap((Z)=>It(me(te,Z.dir),".md"))){let Z=Re(z);if(Z===null)continue;let X=Tc(z,Z,V);if("reason"in X)H.skipped.push(X);else if(H.subagents.some((re)=>re.name===X.name))H.skipped.push({path:z,source:"claude",scope:V,reason:`a project agent already claims the name ${X.name}`});else H.subagents.push(X)}return H}function I(j,O){if(j.length===0)return null;let N=me(fc(),"hlix-standards-commands",cc("sha256").update(O).digest("hex").slice(0,16));try{pc(N,{recursive:!0,force:!0}),lc(N,{recursive:!0});for(let L of j)uc(me(N,`${L.name}.md`),L.body,"utf8");return N}catch{return null}}var en=(j,O)=>{let N=hc(O,j);return!N||N.startsWith("..")||gc(N)?j:N},Mo=(j,O=process.env)=>{let N=O.HLIX_CONFIG_HOME;if(N&&j.startsWith(`${N}/`))return`~/.hlix/${j.slice(N.length+1)}`;let L=a(O);return L&&j.startsWith(`${L}/`)?`~/${j.slice(L.length+1)}`:j};function C(j,O){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(`
|
|
75
|
+
`),L=j.map((F)=>{let H=`# From ${en(F.path,O)} (${F.source})`;return`${F.note?`${H}
|
|
76
|
+
${F.note}`:H}
|
|
77
|
+
|
|
78
|
+
${F.content}`});return`${N}
|
|
79
|
+
|
|
80
|
+
${L.join(`
|
|
81
|
+
|
|
82
|
+
`)}`}var Qt=(j,O,N)=>`${j} ${j===1?O:N}`;function P(j){let O=[];if(j.instructions.length>0)O.push(Qt(j.instructions.length,"instruction file","instruction files"));if(j.skills.length>0)O.push(Qt(j.skills.length,"skill directory","skill directories"));let N=j.commands.length+j.generatedCommands.length;if(N>0)O.push(Qt(N,"command source","command sources"));if(j.mcpServers.length>0)O.push(Qt(j.mcpServers.length,"mcp server","mcp servers"));if(j.subagents.length>0)O.push(Qt(j.subagents.length,"subagent","subagents"));if(O.length===0)return"";let L=[...new Set([...j.instructions,...j.skills,...j.commands,...j.generatedCommands,...j.mcpServers,...j.subagents].map((F)=>F.source))].sort();return`standards: ${O.join(" · ")} (${L.join(", ")})`}function Uo(j,O){let N=[],L=(H,M)=>{if(M.length===0)return;N.push(H,...M.map((U)=>` ${U}`),"")},F=(H)=>`${H.source}${H.scope==="global"?" (global)":""} ${en(H.path,O)}`;if(L("Instructions",j.instructions.map((H)=>`${F(H)}${H.note?` — ${H.note}`:""}`)),L("Skills",j.skills.map((H)=>`${F(H)}${H.harnessReads?" — already read by the harness":""}`)),L("Commands",[...j.commands.map((H)=>`${F(H)}${H.harnessReads?" — already read by the harness":""}`),...j.generatedCommands.map((H)=>`${F(H)} → /${H.name}`)]),L("MCP servers",j.mcpServers.map((H)=>`${F(H)} → ${H.name} (${"command"in H.config?"stdio":"http"})`)),L("Subagents",j.subagents.map((H)=>`${F(H)} → ${H.name}`)),L("Skipped",j.skipped.map((H)=>`${F(H)} — ${H.reason}`)),N.length===0)return`No standards from other agent tools were found in this folder.
|
|
83
|
+
`;return`${N.join(`
|
|
84
|
+
`).trimEnd()}
|
|
85
|
+
`}import{accessSync as Oc,constants as Nc,mkdirSync as Lc,readFileSync as Fc,realpathSync as Hc,statSync as Jo,writeFileSync as Mc}from"node:fs";import{homedir as Uc}from"node:os";import{basename as Dc,dirname as Do,join as Rt}from"node:path";var Jc={homebrew:"Homebrew",npm:"npm",installer:"installer",unknown:"unknown origin"},Bo=(j)=>j.HOME||Uc();function Cr(j){return Rt(j.XDG_DATA_HOME||Rt(Bo(j),".local","share"),"hlix","hlix")}function Go(j){try{return Hc(j)}catch{return null}}function Bc(j){try{let O=JSON.parse(Fc(Rt(Cr(j),"install.json"),"utf8"));if(typeof O.path==="string")return O.path}catch{}return Rt(Bo(j),".local","bin","hlix")}function Gc(j,O){if(/\/Cellar\/hlix\//.test(j))return"homebrew";if(/\/node_modules\/@hlix\/cli\//.test(j))return"npm";if(Go(Bc(O))===j)return"installer";return"unknown"}function _r(j,O){let N=Go(j);if(!N)return null;try{if(!Jo(N).isFile())return null;Oc(N,Nc.X_OK)}catch{return null}return{path:j,realPath:N,channel:Gc(N,O)}}function Wc(j){let O=[];for(let N of(j.PATH??"").split(":")){if(!N)continue;let L=_r(Rt(N,"hlix"),j);if(L&&!O.some((F)=>F.realPath===L.realPath))O.push(L)}return O}function Ir(j,O=process.execPath){if(j.HLIX_SELF)return _r(j.HLIX_SELF,j);if(/^(node|bun)(\.exe)?$/.test(Dc(O)))return null;return _r(O,j)}function Rr(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 Tn=(j)=>`${j.path} (${Jc[j.channel]})`;function Tr(j,O=process.execPath){let N=Ir(j,O),L=Wc(j);if(N&&!L.some((U)=>U.realPath===N.realPath))L.push(N);if(L.length<2)return{running:N,copies:L,duplicate:null};let[F,...H]=L,M=`${L.length} copies of hlix are installed: ${Tn(F)} runs, ${H.map(Tn).join(" and ")} ${H.length===1?"does":"do"} not. Keep one: ${H.map(Rr).join(" && ")}`;return{running:N,copies:L,duplicate:M}}var qc=86400000;function T(j,O=Date.now(),N=process.execPath){let{duplicate:L}=Tr(j,N);if(!L)return null;let F=Rt(Do(Ue(j)),"duplicate-notice");try{if(O-Jo(F).mtimeMs<qc)return null}catch{}try{Lc(Do(F),{recursive:!0}),Mc(F,`${L}
|
|
86
|
+
`)}catch{}return L}async function zc(j,O,N){let L=O.map((U)=>U.id);if(N){if(!L.includes(N))throw new e("workspace_mismatch",O.length===0?`This key belongs to a user who is not a member of any workspace, including ${N}.`:`This key cannot act in workspace ${N}. Available: ${L.join(", ")}.`);return N}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 F=O[0];if(F&&O.length===1)return j.stderr(`Using your only workspace: ${F.name} (${F.id})
|
|
87
|
+
`),F.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: ${L.join(", ")}.`);let H=Math.max(...O.map((U)=>U.name.length));j.stderr(`${O.map((U,D)=>` ${D+1}) ${U.name.padEnd(H)} ${U.slug} ${U.role} ${U.id}`).join(`
|
|
88
|
+
`)}
|
|
89
|
+
`);let M=await j.promptChoice(`Workspace [1-${O.length}]: `,O.length);return L[M]}var Ar={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 ${it}`," --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(`
|
|
90
|
+
`),supportsJson:!0,options:["base-url","workspace"],async run(j){let O=typeof j.flags.workspace==="string"?j.flags.workspace:j.env.HLIX_WORKSPACE_ID,N=j.env.HLIX_API_KEY??await j.readSecret?.("Hlix API key: ")??"";if(!N)throw new e("missing_credential","No API key entered. Run from a terminal or set HLIX_API_KEY for CI.");let L=typeof j.flags["base-url"]==="string"?j.flags["base-url"]:j.env.HLIX_BASE_URL??it,F=new URL(L),H=F.hostname==="localhost"||F.hostname==="127.0.0.1"||F.hostname==="::1";if(F.protocol!=="https:"&&!(F.protocol==="http:"&&H))throw new e("invalid_base_url","--base-url must use HTTPS (HTTP is allowed only for localhost).");let M=new _t({baseUrl:L,credential:Pt(N),retry:{attempts:1}}),U=await zc(j,await M.workspaces.list(),O);await new _t({baseUrl:L,credential:Pt(N),organizationId:U,retry:{attempts:1}}).projects.list();let J=to({baseUrl:L,apiKey:N,organizationId:U},j.env);if(j.json)j.stdout(se(oe(Ar.name,{baseUrl:L,organizationId:U,credentialPath:J})));else j.stdout(`Signed in to ${L}
|
|
91
|
+
Credential stored at ${J}
|
|
92
|
+
`);return 0}},Or={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(`
|
|
93
|
+
`),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(L){throw j.stderr(`credential from ${O.credentialSource}, workspace ${O.workspaceId??"none"}, api ${O.baseUrl}
|
|
94
|
+
`),L}let N={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(se(oe(Or.name,N))),0;return j.stdout(`${Se([["credential",u(O)??"none"],["api",`${O.baseUrl} (from ${O.baseUrlSource})`],["workspace",O.workspaceId?`${O.workspaceId} (from ${O.workspaceSource})`:"none"],["status","valid"]])}
|
|
95
|
+
`),0}},Tt={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(`
|
|
96
|
+
`),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 L=O.credentialSource==="session",F=L?"session":"environment",H=L?"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=eo(j.env);if(!M){let D={removed:!1,reason:F,path:null};if(j.json)j.stdout(se(oe(Tt.name,D)));else j.stdout(`${H}
|
|
97
|
+
`);return 0}if(j.flags.yes!==!0){let D={removed:!1,reason:F,path:M};if(j.json)j.stdout(se(oe(Tt.name,D)));else j.stdout(`${H}
|
|
98
|
+
A stored credential also exists at ${M} — repeat with --yes to remove it.
|
|
99
|
+
`);return 0}let U=tr(j.env);if(j.json)j.stdout(se(oe(Tt.name,U)));else j.stdout(`Removed ${U.path}
|
|
100
|
+
${L?"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."}
|
|
101
|
+
`);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 N=tr(j.env);if(j.json)j.stdout(se(oe(Tt.name,N)));else j.stdout(N.removed?`Removed ${N.path}
|
|
102
|
+
`:`No stored credential at ${N.path}
|
|
103
|
+
`);return 0}};var Wo=Ct.join(" | "),Nr={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(`
|
|
104
|
+
`),supportsJson:!0,async run(j){let O=f(j.cwd,j.env),N=Po(O);if(j.json)return j.stdout(se(oe(Nr.name,{settings:N,paths:O.paths}))),0;return j.stdout(`${Be(["setting","value","source","applies to"],N.map((L)=>[L.key,L.value??"-",L.source,Eo[L.key]??"this folder's binding"]))}
|
|
105
|
+
`),j.stdout(`
|
|
106
|
+
global ${O.paths.global}
|
|
107
|
+
`),j.stdout(`project ${O.paths.project??"- (this folder is not bound to hlix)"}
|
|
108
|
+
`),0}},Lr={name:"config get",summary:"Print one setting's effective value",usage:[`Usage: hlix config get <${Wo}> [--cwd <dir>] [--json]`,"","Prints the value the cascade resolves for one key, or exits 1 when no","file names it."].join(`
|
|
109
|
+
`),supportsJson:!0,args:{min:1,max:1},async run(j){let O=jr(j.args[0]),N=f(j.cwd,j.env),L=N.merged[O]??null,F=N.sources[O]??"default";if(j.json)return j.stdout(se(oe(Lr.name,{key:O,value:L,source:F}))),L===null?1:0;if(L===null)return j.stderr(`${O} is not set. Set it with \`hlix config set ${O} <value>\`.
|
|
110
|
+
`),1;return j.stdout(`${L}
|
|
111
|
+
`),0}},Fr={name:"config set",summary:"Set one setting for this folder, or for the machine with --global",usage:[`Usage: hlix config set <${Wo}> <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(`
|
|
112
|
+
`),supportsJson:!0,options:["global"],args:{min:2,max:2},async run(j){let O=jr(j.args[0]),N=$o(O,j.args[1]),L=j.flags.global===!0?"global":"project",F=y({key:O,value:N,scope:L,cwd:j.cwd,env:j.env});if(j.json)return j.stdout(se(oe(Fr.name,{key:O,value:N,scope:L,path:F}))),0;return j.stdout(`${O} = ${N} (${L}: ${F})
|
|
113
|
+
`),0}};var Kc="project-manager",Vc=2000,Xc="Cloud work landed. Run /pull (hlix pull) to bring it into this folder.",qo=new Set(["done","pr_created"]),Yc=new Set(["done","pr_created","failed","canceled"]),Zc={"project-manager":"Project Manager","senior-engineer":"Senior Engineer","product-engineer":"Product Engineer","ui-engineer":"UI Engineer","qa-engineer":"QA Engineer","security-engineer":"Security Engineer","technical-writer":"Technical Writer"};function Qc(j){let O=j.role?Zc[j.role]:void 0;return O?`${j.name} · ${O}`:j.name}function el(j){return j.replace(/^project-/,"").replace(/[-_]+/g," ")}function Ge(j){return typeof j==="string"&&j.trim()?j.trim():void 0}function zo(j){if(j.status==="running")return null;let O=j.detail??{kind:""},N=el(j.stepId);if(O.kind==="narration"){let L=Array.isArray(O.tasks)?O.tasks.filter((H)=>typeof H==="string"):[];N=Ge(O.title)??(L.length>0?L.join(", "):N);let F=Ge(O.reason);if(F)N+=` — ${F}`}else if(O.kind==="reason"&&Ge(O.reason))N+=` — ${Ge(O.reason)}`;else if(O.kind==="verdict")N=O.approved===!0?"review approved":`review asked for changes${Ge(O.feedback)?` — ${Ge(O.feedback)}`:""}`;else if(O.kind==="dispatch"&&typeof O.launched==="number")N+=` — ${O.launched} started`;return j.status==="failed"?`${N} (failed)`:N}function Ko(j){return{kind:"cycle",text:`cycle "${j.title}": ${j.stage}`}}function tl(j){return{kind:"task",text:`task "${j.title||j.id}": ${j.status}`}}function Vo(j){return{kind:"preview",text:`preview: ${j.state}${j.url?` ${j.url}`:""}`}}function nl(j,O,N){let L=[],F=O.activity.filter((H)=>zo(H)!==null&&!N.has(H.id));if(!j){L.push({kind:"project",text:`${O.project.name}: ${O.project.status} (${O.project.runStatus})`});for(let H of O.cycles)if(!Yc.has(H.status))L.push(Ko(H));if(O.preview.url)L.push(Vo(O.preview))}else{if(j.project.status!==O.project.status||j.project.runStatus!==O.project.runStatus)L.push({kind:"project",text:`project: ${O.project.status} (${O.project.runStatus})`});let H=!1;for(let M of O.cycles){let U=j.cycles.find((D)=>D.id===M.id);if(U&&U.status===M.status)continue;if(L.push(Ko(M)),qo.has(M.status)&&!(U&&qo.has(U.status)))H=!0}for(let M of O.tasks){let U=j.tasks.find((D)=>D.id===M.id);if(!U||U.status!==M.status)L.push(tl(M))}for(let M of O.agents){let U=j.agents.find((D)=>D.id===M.id);if(U&&U.state!==M.state)L.push({kind:"agent",text:`${Qc(M)} ${M.state==="working"?"started working":"is idle"}`})}if(j.preview.url!==O.preview.url||j.preview.state!==O.preview.state){if(L.push(Vo(O.preview)),O.preview.url&&j.preview.url!==O.preview.url)H=!0}if(H)L.push({kind:"landed",text:Xc})}for(let H of F){if(N.has(H.id))continue;N.add(H.id),L.push({kind:"activity",text:zo(H)})}return L}function Xo(j){if(typeof j==="string")return Ge(j);if(Array.isArray(j))return Ge(j.map((O)=>O&&typeof O==="object"&&O.type==="text"?String(O.text??""):"").join(""));return}var rl=(j)=>j==="assistant"?"project manager":"to project manager";class Yo{seen=new Set;drafts=new Map;spoke=!1;unsaved;lines(j){switch(j.type){case"MESSAGES_SNAPSHOT":{let O=j.messages.filter((N)=>{if(typeof N.id!=="string"||this.seen.has(N.id))return!1;if(N.role==="assistant"&&this.unsaved!==void 0&&Xo(N.content)===this.unsaved)return this.unsaved=void 0,this.seen.add(N.id),!1;return!0});for(let N of O)this.seen.add(N.id);return O.flatMap((N)=>{if(N.role!=="user"&&N.role!=="assistant")return[];let L=Xo(N.content);return L?[{kind:"message",text:`${rl(N.role)}: ${L}`}]:[]})}case"RUN_STARTED":return this.spoke=!1,[{kind:"run",text:"project manager is working…"}];case"TEXT_MESSAGE_START":return this.drafts.set(j.messageId,""),[];case"TEXT_MESSAGE_CONTENT":return this.drafts.set(j.messageId,(this.drafts.get(j.messageId)??"")+j.delta),[];case"TEXT_MESSAGE_END":{let O=Ge(this.drafts.get(j.messageId));if(this.drafts.delete(j.messageId),this.seen.has(j.messageId))return[];if(this.seen.add(j.messageId),!O)return[];return this.spoke=!0,this.unsaved=O,[{kind:"message",text:`project manager: ${O}`}]}case"TOOL_CALL_START":return[{kind:"tool",text:`project manager → ${j.toolCallName.replace(/[_-]+/g," ")}`}];case"CUSTOM":{let O=j.name==="hlix.turn_saved"?j.value?.messageId:void 0;if(typeof O==="string"&&this.spoke)this.seen.add(O),this.unsaved=void 0;return[]}case"RUN_FINISHED":return this.spoke=!1,[{kind:"run",text:"project manager finished"}];case"RUN_ERROR":return this.spoke=!1,[{kind:"run",text:`project manager stopped: ${j.message}`}];default:return[]}}}async function Zo(j,O,N){let L=ut(O),F=new AbortController,H=()=>F.abort();if(N.signal?.aborted)return;N.signal?.addEventListener("abort",H,{once:!0});let M=new Yo,U,D=null,J=!1,B=null,G=()=>{if(D){J=!0;return}D=(async()=>{do{J=!1;let V=new AbortController,z=()=>V.abort();F.signal.addEventListener("abort",z,{once:!0}),B=z;try{for await(let Z of j.live.follow(Kc,L,{signal:V.signal}))for(let X of M.lines(Z))N.emit(X)}finally{B=null,F.signal.removeEventListener("abort",z)}}while(J&&!F.signal.aborted)})().catch((V)=>{if(F.signal.aborted)return;U=V,F.abort()}).finally(()=>{D=null})},q=()=>{let V=B;if(!V)return G();J=!0,Ze(Vc,F.signal).then(()=>{if(B===V)V()})},Q=new Set,te;try{G();for await(let{state:V,event:z}of j.live.project(O,{signal:F.signal})){if(z.type==="CUSTOM"){let Z=z.value;if(z.name==="hlix.thread_changed"&&Z?.threadId===L){if(Z.kind==="run_finished")q();else if(Z.kind!=="renamed")G()}continue}for(let Z of nl(te,V,Q))N.emit(Z);te=V}}catch(V){if(!F.signal.aborted)U??=V}finally{F.abort(),N.signal?.removeEventListener("abort",H),await D}if(U!==void 0)throw U}function ei(j){let N=(typeof j.flags.project==="string"?j.flags.project.trim():"")||t(j.cwd)?.config.projectId;if(!N)throw new e("missing_argument","A project is required: pass --project <id>, or run this inside a folder bound to a project.");return N}var Qo="The project manager is busy with another message. Try again in a moment; /watch shows what it is doing.";function mt(j,O){if(typeof j!=="object"||j===null)return"";let N=j[O];return N===null||N===void 0?"":String(N)}var Hr={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(se(oe(Hr.name,O))),0;let N=Array.isArray(O)?O:[];if(N.length===0)return j.stdout(`No projects.
|
|
114
|
+
`),0;return j.stdout(`${Be(["ID","NAME","STACK"],N.map((L)=>[mt(L,"id"),mt(L,"name"),mt(L,"stack")]))}
|
|
115
|
+
`),0}},Mr={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(`
|
|
116
|
+
`),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 N=await j.requireClient().projects.get(O);if(j.json)return j.stdout(se(oe(Mr.name,N))),0;let L=N.repos;return j.stdout(`${Se([["id",mt(N,"id")],["name",mt(N,"name")],["stack",mt(N,"stack")],["status",mt(N,"status")],["repos",Array.isArray(L)?String(L.length):""]].filter(([,F])=>F!==""))}
|
|
117
|
+
`),0}},Ur={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(),N=j.args[0],L=await O.projects.list(),F=L.find((J)=>J.id===N),H=F?[F]:L.filter((J)=>J.name===N);if(H.length===0)throw new e("not_found",`No project named or identified by "${N}".`);if(H.length>1)throw new e("invalid_usage",`More than one project is named "${N}". Use its ID.`);let M=H[0],U=`Delete project "${M.name}"?`;if(j.stderr(`${U}
|
|
118
|
+
`),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 D=await O.projects.delete(M.id);if(j.json)j.stdout(se(oe(Ur.name,D)));else j.stdout(`Deleted project "${M.name}".
|
|
119
|
+
`);return 0}},Dr={name:"projects watch",summary:"Stream the project manager's feed: decisions, cycles, tasks and messages",usage:["Usage: hlix projects watch [--project <id>] [--json]","","Follows the project as its manager sees it: cycle and task changes, the","decisions it makes, its messages, and the runs it starts, including the ones","it starts on its own. Read-only; it runs until you stop it.","","With no --project, the project this folder is bound to is watched.","","With --json, each line is one envelope (JSONL): data is { kind, text }, where","kind is project, cycle, task, agent, preview, activity, message, tool, run or","landed (finished cloud work to pull)."].join(`
|
|
120
|
+
`),supportsJson:!0,options:["project"],agentTool:!1,async run(j){let O=ei(j),N=j.requireClient();return await N.projects.get(O),await Zo(N,O,{...j.signal?{signal:j.signal}:{},emit:(L)=>j.stdout(j.json?`${JSON.stringify(oe(Dr.name,L))}
|
|
121
|
+
`:`${s(L.text)}
|
|
122
|
+
`)}),0}},Jr={name:"projects message",summary:"Send a message to the project manager and print its answer",usage:["Usage: hlix projects message [--project <id>] <text> [--json]","","Posts to the project's thread, the same one the dashboard chat uses, and","prints the project manager's answer as it is written. A manager already","answering someone else is busy: the command fails with conflict and nothing","is sent. With --json, data is { answer }."].join(`
|
|
123
|
+
`),supportsJson:!0,options:["project"],args:{min:1,max:1e4},freeText:!0,async run(j){let O=ei(j),N=j.args.join(" ").trim();if(!N)throw new e("missing_argument","A message is required.");let L=j.requireClient(),F="";try{for await(let H of L.live.run("project-manager",{threadId:ut(O),text:N},j.signal?{signal:j.signal}:void 0))if(H.type==="TEXT_MESSAGE_CONTENT"){if(F+=H.delta,!j.json)j.stdout(s(H.delta))}else if(H.type==="RUN_ERROR"){if(H.code==="409")throw new e("conflict",Qo);throw new e("server_error",`The project manager could not answer: ${H.message}`)}}catch(H){if(H instanceof ct)throw new e("conflict",Qo);throw H}if(j.json)j.stdout(se(oe(Jr.name,{answer:F})));else if(!F)j.stdout(`Sent. The project manager answered without text.
|
|
124
|
+
`);else if(!F.endsWith(`
|
|
125
|
+
`))j.stdout(`
|
|
126
|
+
`);return 0}};function Br(j,O){let N=j.args[0];if(!N)throw new e("missing_argument",`A ${O} id is required.`);return N}function ti(j,O){let N=j.flags[O];return typeof N==="string"&&N.trim()?N.trim():void 0}function We(j,O){if(typeof j!=="object"||j===null)return"";let N=j[O];return N===null||N===void 0?"":String(N)}var Gr={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(`
|
|
127
|
+
`),supportsJson:!0,options:["project","status"],async run(j){let O=ti(j,"project")??t(j.cwd)?.config.projectId,N=ti(j,"status"),L=await j.requireClient().tasks.list({...O?{projectId:O}:{},...N?{status:N}:{}});if(j.json)return j.stdout(se(oe(Gr.name,L))),0;let F=Array.isArray(L)?L:[];if(F.length===0)return j.stdout(`No tasks.
|
|
128
|
+
`),0;return j.stdout(`${Be(["ID","STATUS","TITLE"],F.map((H)=>[We(H,"id"),We(H,"status"),We(H,"title")||We(H,"description").split(`
|
|
129
|
+
`)[0]||""]))}
|
|
130
|
+
`),0}},Wr={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=Br(j,"task"),N=await j.requireClient().tasks.get(O);if(j.json)return j.stdout(se(oe(Wr.name,N))),0;return j.stdout(`${Se([["id",We(N,"id")],["status",We(N,"status")],["title",We(N,"title")],["project",We(N,"projectId")],["description",We(N,"description")]])}
|
|
131
|
+
`),0}},qr={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=Br(j,"task"),N=await j.requireClient().tasks.review(O);if(j.json)return j.stdout(se(oe(qr.name,N))),0;return j.stdout(`${JSON.stringify(N,null,2)}
|
|
132
|
+
`),0}},zr={name:"tasks watch",summary:"Stream a task's status changes until it finishes",usage:["Usage: hlix tasks watch <task-id> [--json]","","Prints the task's status each time it changes and exits when the task is","over: finished, or left unfinished by a cycle that ended (with the reason).","A task the reviewer failed is retried while its cycle is in review, so","watching continues through it.","","With --json, each change is printed as one envelope per line (JSONL) so a","consumer can read them as they arrive: data is { state, task, reason? },","where state is running, finished or unmet."].join(`
|
|
133
|
+
`),supportsJson:!0,args:{min:1,max:1},async run(j){let O=Br(j,"task"),N=j.requireClient(),{projectId:L}=await N.tasks.get(O),F;for await(let H of N.live.task(L,O))if(j.json)j.stdout(`${JSON.stringify(oe(zr.name,H))}
|
|
134
|
+
`);else if(H.state==="unmet")j.stdout(`error: ${s(H.reason)}
|
|
135
|
+
`);else if(H.task&&H.task.status!==F)F=H.task.status,j.stdout(`${s(F)}
|
|
136
|
+
`);return 0}};import{realpath as Ld}from"node:fs/promises";import{resolve as Fd}from"node:path";import{parse as Pl}from"jsonc-parser";import{parse as $l}from"smol-toml";import{parse as _l}from"yaml";var On={install:null,previewCommand:null,previewPort:null,verifyCommand:null,packageManager:null};var sl=[["next",3000],["nuxt",3000],["@remix-run/dev",5173],["@sveltejs/kit",5173],["astro",4321],["@angular/cli",4200],["gatsby",8000],["react-scripts",3000],["vite",5173],["hono",3000]],ol=["vite","next","webpack","react-scripts","@rsbuild/core","parcel"],tn=8080,An=8000,il=String.raw`import http.server as h, urllib.parse as u, sys, os, re, io
|
|
137
|
+
B = (sys.argv[2] if len(sys.argv) > 2 else "").rstrip("/")
|
|
138
|
+
D = os.path.abspath(sys.argv[3] if len(sys.argv) > 3 and sys.argv[3] else ".")
|
|
139
|
+
E = sys.argv[4] if len(sys.argv) > 4 else "index.html"
|
|
140
|
+
P = int(os.environ.get("PORT") or ${tn})
|
|
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, E if os.path.abspath(f) == D else "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, E)
|
|
158
|
+
if not (f.lower().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 Fn(j=".",O="index.html"){return`python3 -c 'import base64,sys;exec(base64.b64decode(sys.argv[1]))' ${nn(il)} "$PREVIEW_PUBLIC_PATH" ${j}${O==="index.html"?"":` ${ai(O)}`}`}function oi(j){if(j.has("index.html"))return"index.html";let O=[...j].filter((N)=>!N.startsWith(".")&&!/[\\/]/.test(N)&&/\.html?$/i.test(N));return O.length===1?O[0]:null}var ii="HLIX_PREVIEW_FAILURE";function Nn(j){return`{ echo "${ii}=${j}"; exit 1; }`}var al=`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
|
+
`,cl=`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
|
+
`,ll=[[86,57],[85,56],[83,55],[81,54],[79,53],[76,52],[74,51]],dl=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("${ii}=" + 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(ll)}).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(al)})
|
|
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(cl)}.replace("__CONFIG__", config))
|
|
254
|
+
`,pl=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
|
+
`,ul=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
|
+
`,ml=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 ni(j,O){return`python3 -c 'import base64,sys;exec(base64.b64decode(sys.argv[1]))' ${nn(j)} ${O}`}function fl(){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)"; ${ni(ul,'"$HOME/.cache/hlix-flutter"')}; } || ${Nn("flutter_sdk_unavailable")}; }`,`{ command -v unzip >/dev/null 2>&1 || { printf '#!/bin/sh\\n%s "$@"\\n' ${ai(ni(ml,""))} > "$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 || ${Nn("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/" && ${Fn("build/web")}; } || ${Nn("web_build_failed")}; }`].join(" && ")}function gl(j){let O=`printf %s ${nn(dl)} | base64 -d | node - "$PREVIEW_PUBLIC_PATH" ${j}`,N=`CI=1 npx expo export --platform web --output-dir dist && ${Fn("dist")}`;return`${O} && ${ci(pl,"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"; ${N}; } || ${Nn("web_build_failed")}; }`}function ai(j){return`'${j.replace(/'/g,"'\\''")}'`}var hl=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
|
+
`,yl=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 ci(j,O){return`printf %s ${nn(j)} | base64 -d | node - "$${O}"`}var wl=["test","typecheck","check","build","lint"],vl=/^(?:\.eslintrc(?:\.(?:js|cjs|mjs|json|ya?ml))?|eslint\.config\.(?:js|cjs|mjs|ts|cts|mts))$/;function bl(j,O){return/\bnext\s+lint\b/.test(j)&&![...O].some((N)=>vl.test(N))}var Lm=Object.freeze({CI:"true",DEBIAN_FRONTEND:"noninteractive",GIT_TERMINAL_PROMPT:"0",GIT_EDITOR:"true",npm_config_yes:"true",NPM_CONFIG_FUND:"false",NPM_CONFIG_AUDIT:"false",NPM_CONFIG_UPDATE_NOTIFIER:"false",PIP_NO_INPUT:"1",PIP_DISABLE_PIP_VERSION_CHECK:"1",NEXT_TELEMETRY_DISABLED:"1",NO_COLOR:"1",TERM:"dumb"});var kl=["dev","start","serve","preview"];function Kr(j){if(!j)return{};try{let O=JSON.parse(j);return O&&typeof O==="object"?O:{}}catch{return{}}}function Sl(j){return{...qe(j.dependencies)?j.dependencies:{},...qe(j.devDependencies)?j.devDependencies:{}}}function jl(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 li(j){let O=new Set(j.rootFiles),N=Kr(j.packageJson),L=typeof N.packageManager==="string"?N.packageManager.split("@")[0]:"",F=L==="bun"||O.has("bun.lock")||O.has("bun.lockb")?"bun":L==="pnpm"||O.has("pnpm-lock.yaml")?"pnpm":L==="yarn"||O.has("yarn.lock")?"yarn":L==="npm"||O.has("package.json")?"npm":null,H=oi(O);if(!F){if(jl(j))return{...On,previewCommand:fl(),previewPort:tn,mobile:!0};let J=xl(O,j.configFiles??{});if(J)return J;return H?{...On,previewCommand:Fn(".",H),previewPort:tn}:On}let M=di(N,O,F),U={install:`${F} install`,verifyCommand:M.verifyCommand,packageManager:F},D=M.webApp?null:El(j.workspacePackages??[],F)[0]??null;if(D){let J=(B)=>`cd ${D.dir} && ${B}`;return{...U,previewCommand:J(D.previewCommand),previewPort:D.previewPort,verifyCommand:U.verifyCommand??(D.verifyCommand?J(D.verifyCommand):null),...D.mobile?{mobile:!0}:{}}}return{...U,previewCommand:M.previewCommand,previewPort:M.previewPort,...M.mobile?{mobile:!0}:{}}}function di(j,O,N,L){let F=qe(j.scripts)?j.scripts:{},H=(re)=>`${N} run ${re}`,M=(re,ue)=>`${H(re)}${N==="npm"?" --":""} ${ue}`,U=kl.find((re)=>typeof F[re]==="string"),D=wl.find((re)=>typeof F[re]==="string"&&!/no test specified/i.test(String(F[re]))&&!/(?:^|\s)(?:--watch(?:All)?|-w)(?:\s|=|$)/.test(String(F[re]))&&!bl(String(F[re]),O)),J=D?H(D):null,B=Sl(j),G={previewCommand:null,previewPort:null,verifyCommand:J,webApp:!1,mobile:!1,explicitPort:!1};if("expo"in B||"react-native"in B&&!ol.some((re)=>(re in B)))return{previewCommand:gl(N),previewPort:L??tn,verifyCommand:J,webApp:!0,mobile:!0,explicitPort:!1};let q=sl.find(([re])=>(re in B)),Q=U?si(String(F[U]))??q?.[1]??null:null,te=oi(O);if(!U&&!q&&te)return{...G,previewCommand:Fn(".",te),previewPort:L??tn};if(!U)return G;let V=String(F[U]).trim(),z=L!=null?` --port ${L}`:"",Z=z?M(U,z.trim()):H(U),X=V.split("&&").map((re)=>re.trim());if(X.length>1&&X.every((re)=>/^vite(?:\s|$)/.test(re))&&!("@sveltejs/kit"in B)){let re={npm:"npx",bun:"bunx",pnpm:"pnpm exec",yarn:"yarn exec"}[N];Z=X.map((ue,fe)=>`${re} ${ue} --base "$PREVIEW_BASE_PATH/"${/^vite\s+build\b/.test(ue)?"":" --host 0.0.0.0"}${fe===X.length-1?z:""}`).join(" && ")}else if(/^vite(?:\s+(?:dev|serve|preview))?(?:\s|$)/.test(V)&&!/&&|;|\|/.test(V)&&!("@sveltejs/kit"in B))Z=M(U,`--base "$PREVIEW_BASE_PATH/" --host 0.0.0.0${z}`);else if(/^astro\s+(?:dev|preview)(?:\s|$)/.test(V))Z=M(U,`--base "$PREVIEW_BASE_PATH"${z}`);else if(/^next\s+(?:dev|start)(?:\s|$)/.test(V))Z=`${ci(hl,"PREVIEW_BASE_PATH")} && ${Z}`;else if(/^nuxt\s+(?:dev|preview|start)(?:\s|$)/.test(V))Z=`NUXT_APP_BASE_URL="$PREVIEW_BASE_PATH/" ${Z}`;return{previewCommand:Z,previewPort:L??Q,verifyCommand:J,webApp:Boolean(q),mobile:!1,explicitPort:si(V)!=null}}var ri=["web","app","frontend","site","www","client","dashboard"];function El(j,O){let N=j.filter((F)=>Ln(F.dir)).map((F)=>{let H=Kr(F.packageJson),M=new Set(F.rootFiles??[]);return{dir:F.dir,pkg:H,files:M,...di(H,M,O)}}).filter((F)=>F.webApp&&F.previewCommand&&F.previewPort!=null),L=(F)=>{let H=ri.indexOf(F.split("/").at(-1)??"");return H<0?ri.length:H};return N.sort((F,H)=>Number(F.mobile)-Number(H.mobile)||Number(!F.dir.startsWith("apps/"))-Number(!H.dir.startsWith("apps/"))||L(F.dir)-L(H.dir)||(F.dir<H.dir?-1:F.dir>H.dir?1:0))}function Ln(j){return/^[A-Za-z0-9._@-]+(?:\/[A-Za-z0-9._@-]+)*$/.test(j)&&!j.split("/").some((O)=>O===".."||O===".")}function pi(j){let O=Kr(j.packageJson),N=Array.isArray(O.workspaces)?O.workspaces:qe(O.workspaces)&&Array.isArray(O.workspaces.packages)?O.workspaces.packages:[],L=j.configFiles?.["pnpm-workspace.yaml"]??"";for(let U of L.split(/\r?\n/)){let D=U.match(/^\s*-\s*["']?([^"'#\s]+)["']?/);if(D)N.push(D[1])}let F=N.filter((U)=>typeof U==="string"&&!U.startsWith("!"));if(F.length===0&&new Set(j.rootFiles).has("turbo.json"))F.push("apps/*","packages/*");for(let U of Object.values(qe(O.scripts)?O.scripts:{})){if(typeof U!=="string")continue;let D=U.match(/^\s*cd\s+([A-Za-z0-9._@/-]+)\s*&&/)?.[1];if(D&&Ln(D))F.push(D)}let H=new Set,M=new Set;for(let U of F){let D=U.replace(/^\.\//,"").replace(/\/$/,"");if(/^[^*]+\/\*$/.test(D)&&Ln(D.slice(0,-2)))H.add(D.slice(0,-2));else if(!D.includes("*")&&Ln(D))M.add(D)}return{parents:[...H].sort(),packages:[...M].sort()}}function xl(j,O){let N=`${O["requirements.txt"]??""}
|
|
318
|
+
${O["pyproject.toml"]??""}`.toLowerCase(),L=(B)=>new RegExp(`(^|[\\s"'\\[,])${B}\\b`,"m").test(N),F=j.has("requirements.txt")?'"$V/bin/pip" install -q -r requirements.txt':j.has("pyproject.toml")?'"$V/bin/pip" install -q .':null,H=(B,G="")=>F?`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" && ${F}${G} && touch "$V/.ready"; }; } && "$V/bin/python" ${B}`:null,M=L("pytest")?H("-m pytest",' && "$V/bin/pip" install -q pytest'):null,D=["main.py","app.py","server.py","api.py"].find((B)=>j.has(B))?.replace(/\.py$/,""),J=(B,G=M)=>({...On,previewCommand:B,previewPort:An,verifyCommand:G});if(j.has("manage.py")){let B=`python3 -c 'import base64,sys;exec(base64.b64decode(sys.argv[1]))' ${nn(yl)} "$PREVIEW_ALLOWED_HOSTS"`;return J(`${B} && python3 manage.py runserver 0.0.0.0:${An}`,M??(L("django")?H("manage.py test"):null))}if(D&&L("fastapi"))return J(`python3 -m uvicorn ${D}:app --host 0.0.0.0 --port ${An} --root-path "$PREVIEW_PUBLIC_PATH"`);if(D&&L("flask"))return J(`python3 -m flask --app ${D} run --host 0.0.0.0 --port ${An}`);return null}function nn(j){return btoa(j)}function si(j){let O=j.match(/(?:--port(?:=|\s+)|-p\s+|\bPORT=)(\d{2,5})\b/),N=O?Number(O[1]):NaN;return Number.isInteger(N)&&N>0&&N<=65535?N:null}function qe(j){return Boolean(j)&&typeof j==="object"&&!Array.isArray(j)}function ui(j){let O=new Set(j.rootFiles),N=new Set;if(O.has("package.json")){for(let F of["coverage",".cache"])N.add(F);if(["package-lock.json","pnpm-lock.yaml","yarn.lock","bun.lock","bun.lockb"].some((F)=>O.has(F)))N.add("node_modules")}if(O.has("Cargo.toml"))N.add("target");if(["pyproject.toml","requirements.txt","setup.py"].some((F)=>O.has(F)))N.add("__pycache__");if(O.has("composer.json")&&O.has("composer.lock"))N.add("vendor");for(let F of Vr({...j,rootFiles:O}))N.add(F);return[...N].sort()}function De(j,O,N){let L=(j.match(/"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`|\/\*[\s\S]*?\*\/|\/\/[^\n]*|[A-Za-z_$][\w$]*|[^\s]/g)??[]).filter((D)=>!D.startsWith("//")&&!D.startsWith("/*"));if(L[0]!=="{"){let D=L.findIndex((B,G)=>B==="export"&&L[G+1]==="default"),J=L.findIndex((B,G)=>B==="module"&&L.slice(G+1,G+4).join("")===".exports=");if(D<0&&J<0)return null;if(L=L.slice(D>=0?D+2:J+4),["defineConfig","defineNuxtConfig"].includes(L[0]??"")&&L[1]==="(")L=L.slice(2);if(L[0]!=="{")return null}if(L.some((D,J)=>D==="."&&L[J+1]==="."&&L[J+2]==="."))return null;let F=(D="")=>D.replace(/^["']|["']$/g,""),H=[],M,U=0;for(let D=0;D<L.length;D++){let J=L[D];if(J==="{")H.push(L[D-1]===":"?F(L[D-2]):"");if(J==="}")H.pop();if(!H.length)break;if(J==="["&&["{",","].includes(L[D-1]??""))return null;if(O&&H.length===1&&F(J)===O){if(L[D+1]!==":"||L[D+2]!=="{"||++U>1)return null}if(F(J)===N&&(O?H.length===2&&H.at(-1)===O:H.length===1)&&L[D+1]!==":")return null;if(F(J)!==N||L[D+1]!==":"||(O?H.length!==2||H.at(-1)!==O:H.length!==1))continue;let B=L[D+2]??"";if(M!==void 0||!/^["'`][^\\$]*["'`]$/.test(B)||![",","}"].includes(L[D+3]??""))return null;M=B.slice(1,-1)}return M}function Vr(j){let O={};try{let q=JSON.parse(j.packageJson??"{}");if(qe(q))O=q}catch{}let N={...qe(O.dependencies)?O.dependencies:{},...qe(O.devDependencies)?O.devDependencies:{}},L=qe(O.scripts)?Object.entries(O.scripts).filter((q)=>typeof q[1]==="string"):[],F=(q,Q=q)=>(q in N)||L.some(([,te])=>new RegExp(`(?:^|[;&|\\s])${Q}(?:\\s|$)`).test(te)),H=j.configFiles??{},M=new Set,U=(q)=>{if(typeof q!=="string")return null;let Q=q.replace(/^\.\//,"").replace(/\/$/,"");return Q&&!Q.startsWith("/")&&!/[\\:*?\[\]#!$`"'\r\n]/.test(Q)&&!Q.split("/").some((te)=>!te||[".","..",".git",".hlix"].includes(te))?Q:null},D=(q)=>{let Q=U(q);if(Q)M.add(Q)},J=(q,Q)=>{let te=L.filter(([X,re])=>/(?:^|:)build(?:$|:)/.test(X)||new RegExp(`\\b${q} build\\b`).test(re)),V=te.filter(([,X])=>new RegExp(`(?:^|\\s)${q}(?:\\s|$)`).test(X));if(!V.length&&(te.length||O.workspaces!==void 0))return null;if(te.some((X)=>!V.includes(X)&&/--(?:out|dist|root|config|project)|\s-[dpc]\b/.test(X[1])))return null;let z,Z=!1;for(let[,X]of V){if(/[$`\\;|<>\n]/.test(X)||/(?:^|\s)(?:cd|pushd|popd)\s/.test(X))return null;for(let re of X.split("&&")){let ue=re.match(/"[^"\n]*"|'[^'\n]*'|[^\s]+/g)??[];if(ue.some((ee)=>/["']/.test(ee)&&!/^(?:"[^"\n]*"|'[^'\n]*')$/.test(ee)))return null;let fe=ue.map((ee)=>ee.replace(/^["']|["']$/g,"")),ne=fe.indexOf(q);if(ne<0)continue;if(ne!==0&&!(ne===1&&["npx","bunx"].includes(fe[0])))return null;let K=fe.slice(ne+1);if(K[0]==="build")K.shift();let W;for(let ee=0;ee<K.length;ee++){let[de,...ge]=K[ee].split("="),he=ge.length?ge.join("="):void 0;if(!Q.includes(de)||W!==void 0)return null;let Ee=he??K[++ee],ye=U(Ee);if(!ye)return null;W=ye}if(Z&&W!==z)return null;Z=!0,z=W}}return z},B=(q)=>{let Q=[...new Set([...j.rootFiles,...Object.keys(H)])].filter((te)=>te.startsWith(`${q}.config.`)||q==="turbo"&&te==="turbo.json");if(!Q.length)return"{}";return Q.length===1?H[Q[0]]??null:null},G=(q,Q,te,V,z,Z,X)=>{let re=B(q),ue=J(q,z);if(re===null||ue===null)return;let fe=Z?De(re,null,Z):void 0,ne=De(re,Q,te);if(fe===null||ne===null)return;let K=fe===void 0||fe==="."||fe==="./"?"":U(fe);if(K===null)return;let ee=U(ue??ne??V);if(!ee)return;D(K?`${K}/${ee}`:ee);for(let de of X??[])D(K?`${K}/${de}`:de)};if(F("vite"))G("vite","build","outDir","dist",["--outDir","--out-dir"],"root");if(F("next")){let q=B("next"),Q=q===null?null:De(q,null,"output");if(q!==null&&(Q===void 0||Q==="standalone"||Q==="export"&&De(q,null,"distDir")===void 0))G("next",null,"distDir",".next",[],void 0,Q==="export"?["out"]:[])}if(F("astro"))G("astro",null,"outDir","dist",["--outDir","--out-dir"],"root");if(F("nuxt")){let q=B("nuxt");if(q!==null&&De(q,null,"nitro")===void 0&&De(q,null,"extends")===void 0)G("nuxt",null,"buildDir",".nuxt",[],"rootDir",[".output"])}if(F("turbo"))G("turbo",null,"cacheDir",".turbo",["--cache-dir"]);if(F("webpack")){let q=B("webpack");if(q!==null&&De(q,null,"context")===void 0)G("webpack","output","path","dist",["--output-path"])}if(F("rollup"))G("rollup","output","dir",void 0,["--dir","-d"]);if(F("parcel")||F("parcel-bundler","parcel")){let q=J("parcel",["--dist-dir"]);if(q!==null&&O.targets===void 0&&!["main","module","browser"].some((Q)=>typeof O[Q]==="string"))D(q??"dist")}if(F("react-scripts")&&J("react-scripts",[])!==null)D("build");if(F("typescript","tsc")){let q=J("tsc",["--outDir"]),Q=Object.keys(H).filter((te)=>/^tsconfig(?:\.[^/]*)?\.json$/.test(te));if(q!==null&&Q.length===1&&Q[0]==="tsconfig.json"){let te=H["tsconfig.json"];if(De(te,null,"extends")===void 0&&De(te,null,"references")===void 0){let V=De(te,"compilerOptions","outDir");if(V!==null)D(q??V)}}}if(Xr(H)){D("build"),D("dist");for(let q of j.rootFiles)if(q.endsWith(".egg-info"))D(q)}return[...M].sort()}function Xr(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 xe=(j)=>j&&typeof j==="object"&&!Array.isArray(j)?j:{},At=(j)=>Array.isArray(j)?j.filter((O)=>typeof O==="string"):[];function mi(j){let O=[];function N(K,W="json"){let ee=j.get(K);if(!ee)return{};try{if(W==="yaml")return xe(_l(ee,{maxAliasCount:50}));if(W==="toml")return xe($l(ee));if(W==="jsonc"){let de=[],ge=Pl(ee,de,{allowTrailingComma:!0});if(de.length)throw Error("invalid JSONC");return xe(ge)}return xe(JSON.parse(ee))}catch{return O.push(`Could not parse ${K}`),{}}}let L=[...j.keys()].sort(),F=N("package.json"),H={packageJson:j.get("package.json")??null,rootFiles:L.filter((K)=>!K.includes("/")),configFiles:Object.fromEntries(["requirements.txt","pyproject.toml","pnpm-workspace.yaml"].flatMap((K)=>j.get(K)?[[K,j.get(K)]]:[]))},M=pi(H),U=L.flatMap((K)=>{let W=K.replace(/\/package\.json$/,""),ee=W!==K&&(M.packages.includes(W)||M.parents.some((ge)=>W.startsWith(`${ge}/`)&&!W.slice(ge.length+1).includes("/"))),de=j.get(K);return ee&&de?[{dir:W,packageJson:de}]:[]}),D=li({...H,workspacePackages:U}),J=typeof F.packageManager==="string"?/^(npm|pnpm|yarn|bun)@(.+)$/.exec(F.packageManager):null,B=Object.create(null);for(let[K,W]of Object.entries(xe(F.engines)))if(typeof W==="string")B[K]=W;if(J)B[J[1]]=J[2].split("+")[0];let G=N("composer.json"),q={...xe(G["require-dev"]),...xe(G.require)},Q={...typeof q.php==="string"?{constraint:q.php}:{},extensions:Object.keys(q).filter((K)=>K.startsWith("ext-")).map((K)=>K.slice(4)).sort()};for(let[K,W]of[[".nvmrc","node"],[".node-version","node"],[".python-version","python"],[".php-version","php"],[".bun-version","bun"]]){let ee=j.get(K)?.trim();if(ee)B[W]=ee}for(let K of(j.get(".tool-versions")??"").split(/\r?\n/)){let[W,ee]=K.replace(/#.*/,"").trim().split(/\s+/);if(W&&ee)B[W==="nodejs"?"node":W]=ee}for(let K of[".mise.toml","mise.toml"])for(let[W,ee]of Object.entries(xe(N(K,"toml").tools)))if(typeof ee==="string"||typeof ee==="number")B[W]=String(ee);else O.push(`Unsupported tool version for ${W} in ${K}`);let te=[];for(let K of L.filter((W)=>/(^|\/)package.json$/.test(W))){let W=K==="package.json"?F:N(K),ee={...xe(W.dependencies),...xe(W.devDependencies)};for(let de of["nuxt","next","astro","@sveltejs/kit","vite"])if(de in ee)te.push({path:K,name:de})}for(let[K,W]of[["yiisoft/yii2","yii2"],["laravel/framework","laravel"]])if(K in q)te.push({path:"composer.json",name:W});let V=new Set,z=Object.create(null);function Z(K,W){if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(K))return;if(V.add(K),/(?:^|_)HOST$/.test(K)&&typeof W==="string"&&/^[a-zA-Z0-9_.-]+$/.test(W))z[K]=W}for(let K of L.filter((W)=>/(^|\/)\.env\.(example|sample|template)$/.test(W)))for(let W of(j.get(K)??"").split(/\r?\n/)){let ee=/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*(?:#.*)?$/.exec(W);if(ee)Z(ee[1],ee[2].replace(/^['"]|['"]$/g,""))}let X=[],re=[];for(let K of L.filter((W)=>/(^|\/)(?:docker-compose|compose)(?:[.-][^/]*)?\.ya?ml$/.test(W)))for(let[W,ee]of Object.entries(xe(N(K,"yaml").services))){let de=xe(ee),ge=typeof de.image==="string"?de.image:"",he=ge.split("/").at(-1)?.split(/[:@]/)[0],Ee=he==="mysql"||he==="mariadb"?"mysql":he==="postgres"?"postgres":he==="redis"?"redis":null;if(Ee)X.push({file:K,name:W,kind:Ee,image:ge});else if(he!=="traefik"&&he!=="nginx"&&he!=="caddy")re.push({file:K,name:W});for(let[ye,je]of Object.entries(xe(de.environment)))Z(ye,je);for(let ye of At(de.environment)){let je=ye.indexOf("=");Z(je<0?ye:ye.slice(0,je),je<0?null:ye.slice(je+1))}}let ue=L.find((K)=>K===".devcontainer/devcontainer.json")??L.find((K)=>K==="devcontainer.json"),fe;if(ue){let K=N(ue,"jsonc");for(let W of[K.containerEnv,K.remoteEnv])for(let[ee,de]of Object.entries(xe(W)))Z(ee,de);fe={...typeof K.image==="string"?{image:K.image}:{},services:[...typeof K.service==="string"?[K.service]:[],...At(K.runServices)],ports:Array.isArray(K.forwardPorts)?K.forwardPorts.filter((W)=>Number.isInteger(W)&&Number(W)>0&&Number(W)<=65535):[],commands:[K.onCreateCommand,K.updateContentCommand,K.postCreateCommand,K.postStartCommand].filter((W)=>typeof W==="string")}}let ne=At(F.workspaces).length?At(F.workspaces):At(xe(F.workspaces).packages);return ne.push(...At(N("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:D,packageManager:J?{name:J[1],version:J[2]}:D.packageManager?{name:D.packageManager}:null,lockfiles:L.filter((K)=>/(^|\/)(bun.lockb?|pnpm-lock.yaml|yarn.lock|package-lock.json|composer.lock|uv.lock|poetry.lock|Pipfile.lock|Cargo.lock|Gemfile.lock)$/.test(K)),toolchain:B,php:Q,workspaces:[...new Set(ne)].sort(),frameworks:te,turbo:j.has("turbo.json")||"turbo"in xe(F.devDependencies)||"turbo"in xe(F.dependencies),services:X,unsupportedServices:re,envKeys:[...V].sort(),envHosts:z,...fe?{devcontainer:fe}:{},warnings:O}}import{createHash as un}from"node:crypto";import{createReadStream as Dl}from"node:fs";import{lstat as Oi,mkdir as Jl,readFile as dn,readdir as Bl,readlink as Gl,realpath as Ni,stat as Li,writeFile as Wl}from"node:fs/promises";import{basename as gt,dirname as ql,join as mn,relative as Un,resolve as Dn,sep as zl}from"node:path";import{execFile as Kl,spawnSync as Vl}from"node:child_process";import ln from"ignore";import{createReadStream as Cl}from"node:fs";import{lstat as Ot,mkdtemp as Il,readFile as Qr,readdir as Hn,rename as Rl,rm as Tl,writeFile as Al}from"node:fs/promises";import{join as Te}from"node:path";import hi from"ignore";function rn(j,O){if(Array.isArray(O))return O.some((N)=>rn(j,N));if(!O||j.split("/").some((N)=>N===".git"||N===".hlix"))return!1;return j===O||j.startsWith(`${O}/`)}function sn(j,O){if(typeof O!=="string")return O?.some((N)=>sn(j,N))??!1;return rn(j,O)||O.startsWith(`${j}/`)}function fi(j,O,N,L){let F=new Map,H=j.length,M=0;for(let B of j){let G=B.path.indexOf("/"),q=G<0?B.path:B.path.slice(0,G+1),Q=F.get(q)??{count:0,bytes:0,included:!1};Q.count++,Q.bytes+=B.size??0,Q.included||=rn(B.path,L),F.set(q,Q),M+=B.size??0}let U=M>N,D=[...F].sort(([B,G],[q,Q])=>Number(G.included)-Number(Q.included)||(U?Q.bytes-G.bytes:Q.count-G.count)||B.localeCompare(q)),J=[];for(let[B,G]of D){if(H<=O&&M<=N)break;J.push(B),H-=G.count,M-=G.bytes}return J}function Yr(j,O){return O.some((N)=>j===N||N.endsWith("/")&&j.startsWith(N))}function Zr(j){return`upload limit; add /${j} to .hlixignore, or try --include ${j.replace(/\/$/,"")}`.slice(0,200)}function gi(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 vi="# --- managed by Hlix: safe to edit above/below, this block is regenerated ---",es="# --- end managed by Hlix ---",Mn=new Set(["agent-artifacts",".context",".claude/worktrees"]),Ol=/(?:^|\/)(?:Makefile|Dockerfile|Containerfile|Justfile|Rakefile|Gemfile)(?:\.[^/]*)?$/i,Nl=/\.(?:md|txt|json)$/i,yi=/(?:^|\n)\s*(?:\/\/|\/\*+|\*|#|<!--)\s*(?:@generated\b|generated by\b|do not edit\b)|(?:^|\n)\s*\/\/[#@]\s*sourceMappingURL=/i,wi=/\.(?:log(?:\.\d+)?|tmp|cache|pyc|tsbuildinfo|map)$/i;function on(j){let O=[...j.matchAll(new RegExp(`^${vi}\\r?$`,"gm"))],N=[...j.matchAll(new RegExp(`^${es}\\r?$`,"gm"))];if(!O.length&&!N.length)return{before:j,after:"",managed:""};if(O.length!==1||N.length!==1||N[0].index<O[0].index)return null;let L=O[0].index,H=N[0].index+es.length,M=j.slice(H).match(/^\r?\n/)?.[0]??"";return{before:j.slice(0,L),after:j.slice(H+M.length),managed:j.slice(L,H)}}function ts(j){let O=on(j);return(O?O.before+`
|
|
319
|
+
`+O.after:j).split(/\r?\n/).filter((N)=>N.startsWith("!")&&N.length>1).map((N)=>N.slice(1))}async function bi(j,O){let N=Te(j,".hlixignore"),L="";try{let F=await Ot(N).catch((W)=>{if(W.code==="ENOENT")return null;throw W});if(F&&!F.isFile())return{warning:"Kept .hlixignore unchanged: managed rules require a regular file."};if(F)L=await Qr(N,"utf8");let H=on(L);if(!H)return{warning:"Kept .hlixignore unchanged: repair its managed-block markers before refreshing."};let M=ts(L),U=hi().add(M),D=[],J=[],B=hi(),G=new Set;for(let W of O.tracked){let ee=W.split("/");while(ee.length)G.add(ee.join("/")),ee.pop()}let q=0,Q=0,te=()=>q<30000&&Q<268435456,V=(W)=>G.has(W)||sn(W,O.includes)||M.some((ee)=>{let de=ee.replace(/^\//,"").split(/[?*[\\]/)[0];return!de||de.startsWith(`${W}/`)||U.ignores(`${W}/`)||U.ignores(W)}),z=async(W,ee,de=!1)=>{if(O.signal?.throwIfAborted(),!te()||V(W)||O.protectedPath(W,ee))return!1;q++;let ge=await Ot(Te(j,W));if(ge.isSymbolicLink())return ee;if(ge.isDirectory()){let ye=(await Hn(Te(j,W))).sort();for(let je of ye){if(je===".git")continue;if(!await z(`${W}/${je}`,ee,de))return!1}return!0}if(!ge.isFile()||Q+ge.size>268435456)return!1;let he="",Ee="";for await(let ye of Cl(Te(j,W),{encoding:"utf8",signal:O.signal})){if(Q+=Buffer.byteLength(ye),he.length<4096)he+=ye.slice(0,4096-he.length);let je=Ee+ye;if(O.protectedContent(W,je))return!1;Ee=je.slice(-4096)}return ee||yi.test(he)||yi.test(Ee)||!Ol.test(W)&&!/^#!|^<\?php/.test(he)&&(de&&Nl.test(W)||wi.test(W))},Z=new Set,X=async(W,ee=[],de=!1)=>{if(O.signal?.throwIfAborted(),!te())return;let ge=Te(j,W),he=await Hn(ge,{withFileTypes:!0}),Ee=async(pe)=>he.find((be)=>be.name===pe)?.isFile()&&(await Ot(Te(ge,pe))).size<1048576?Qr(Te(ge,pe),"utf8"):null,ye=await Ee("package.json"),je=await Ee("composer.json"),we=!1,ht=new Set;try{let pe=JSON.parse(await Ee("composer.lock")??"null");we=Array.isArray(pe?.packages);for(let le of[...pe?.packages??[],...pe?.["packages-dev"]??[]]){if(typeof le.name==="string")ht.add(le.name);if(le.dist?.type==="path")we=!1}}catch{}try{let pe=JSON.parse(ye??"{}"),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 rt=(W?`${W}/`:"")+be.replace(/^\.\//,"");J.push(rt),B.add(rt)}}catch{}let yt=[ye,je].filter(Boolean).join(`
|
|
320
|
+
`),Ke={};for(let pe of he){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 Ee(pe.name);if(le!==null)Ke[pe.name]=le}let wt={packageJson:ye,rootFiles:he.map((pe)=>pe.name),configFiles:Ke};de||=Xr(Ke);let yn=ui(wt);for(let pe of Vr(wt))Z.add(W?`${W}/${pe}`:pe);let nt=new Set([...yn,...ee]);for(let pe of he.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=W?`${W}/${pe.name}`:pe.name;if(/[\n\r\\*?[\]!#]/.test(le)||le.endsWith(" "))continue;if(q++,!te())return;if(pe.isDirectory()){let be=await Ot(Te(j,le,".git")).then(()=>O.isRepository(le),()=>!1),rt=Mn.has(le)||[...Mn].some((Ae)=>le.startsWith(`${Ae}/`)),wn=O.gitIgnored.directories.some((Ae)=>`${le}/`.startsWith(Ae)),st=B.ignores(`${le}/`)||J.some((Ae)=>Ae.split(/[?*[\\]/)[0].startsWith(`${le}/`))||yt.includes(pe.name)||/(?:^|\/)(?:src|lib|apps|packages|tests|resources|public)(?:\/|$)/.test(le),vt=be&&(rt||wn)&&!st;if(pe.name==="vendor"&&we)for(let Ae of await Hn(Te(j,le),{withFileTypes:!0})){if(["autoload.php","composer","bin"].includes(Ae.name))continue;if(!Ae.isDirectory()){we=!1;break}for(let Ht of await Hn(Te(j,le,Ae.name)))if(!ht.has(`${Ae.name}/${Ht}`))we=!1}let Ve=yn.includes(pe.name)&&(pe.name==="node_modules"||pe.name==="vendor"&&we&&!/"type"\s*:\s*"path"/.test(je??"")),vn=Z.has(le)||de&&pe.name.endsWith(".egg-info");if(((pe.name==="node_modules"||pe.name==="vendor"?Ve:nt.has(pe.name))||Mn.has(le)&&!st||["logs","runtime","tmp"].includes(pe.name)||vt||vn)&&!V(le)&&await z(le,Ve||vt||vn,nt.has(pe.name)||Mn.has(le))){D.push(`/${le}/`);continue}if(!be&&!["node_modules","vendor"].includes(pe.name))await X(le,nt.has("__pycache__")?["__pycache__"]:[],de)}else if(pe.isFile()&&(wi.test(pe.name)||(await Ot(Te(j,le))).size>O.maxFileBytes)&&!V(le)&&await z(le,!1))D.push(`/${le}`)}};await X("");let re=L.includes(`\r
|
|
321
|
+
`)?`\r
|
|
322
|
+
`:`
|
|
323
|
+
`,ue=[vi,...D.sort(),es,""].join(re),ne=H.before+(H.before&&!H.before.endsWith(`
|
|
324
|
+
`)?re:"")+ue+H.after;if(O.write!==!1&&ne!==L){let W=await Il(Te(j,".hlixignore-"));try{let ee=Te(W,"rules");await Al(ee,ne,{mode:F?.mode??420});let de=await Ot(N).catch((ge)=>{if(ge.code==="ENOENT")return null;throw ge});if(de?!de.isFile()||de.ino!==F?.ino||de.dev!==F?.dev||await Qr(N,"utf8")!==L:F!==null)return{warning:"Kept .hlixignore unchanged: it changed while generated paths were being checked."};await Rl(ee,N)}finally{await Tl(W,{recursive:!0,force:!0})}}let K=D.every((W)=>W.endsWith("/"))?"generated folders":"generated paths";return{rules:D,report:`Hlix ignored ${D.length} ${K} — see .hlixignore`}}catch(F){return O.signal?.throwIfAborted(),{warning:`Kept .hlixignore unchanged: could not safely refresh generated paths (${F.code??"unreadable"}).`}}}import{readFile as Fl}from"node:fs/promises";import{join as Hl}from"node:path";function Ll(j){let O=j.trim();if(!O||/^[|>[{]/.test(O))return null;let N=O.match(/^(["'])([\s\S]*)\1$/);if(!N&&/^["']/.test(O))return null;return(N?N[2].trim():O.replace(/(?:^|\s)#.*$/,"").trim())||null}function ki(j){let O=j.split(/\r?\n/),N=O.findIndex((M)=>/^tasks:\s*(?:#.*)?$/.test(M));if(N===-1)return{tasks:[],partial:/^tasks:\s*\S/m.test(j)};let L=[],F=!1,H=-1;for(let M of O.slice(N+1)){if(!M.trim()||/^\s*#/.test(M))continue;let U=M.length-M.trimStart().length,D=M.match(/^(\s*-(?:\s+|$))(.*)$/);if(D){if(H!==-1&&U>=H)continue;if(L.push({}),H=D[2]?D[1].length:-1,!D[2])continue}else if(U===0)break;else if(L.length===0)continue;else if(H===-1)H=U;else if(U!==H)continue;let J=(D?D[2]:M.trim()).match(/^([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/);if(!J)continue;let B=J[1];if(B!=="name"&&B!=="before"&&B!=="init"&&B!=="command")continue;let G=Ll(J[2]);if(G===null)F=!0;else L[L.length-1][B]=G}return{tasks:L,partial:F}}async function ft(j,O){try{return await Fl(Hl(j,...O.split("/")),"utf8")}catch(N){if(N.code==="ENOENT")return null;throw N}}function Si(j){try{let O=j.replace(/(^|[^:\\])\/\/.*$/gm,"$1").replace(/\/\*[\s\S]*?\*\//g,"").replace(/,\s*([}\]])/g,"$1");return JSON.parse(O)}catch{return null}}function Qe(j){if(typeof j==="string"&&j.trim())return[j.trim()];if(Array.isArray(j))return j.flatMap(Qe);if(j&&typeof j==="object")return Object.values(j).flatMap(Qe);return[]}function ns(j){if(!j||typeof j!=="object")return[];return Object.keys(j).filter((O)=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(O))}function Ml(j,O){let N=new Set,L=[/\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)L.push(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::[-?][^}]*)?\}/g);for(let F of L)for(let H of j.matchAll(F))N.add(H[1]);return[...N]}function Ul(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 ji(j){let O=typeof j==="number"?j:Number(j);return Number.isInteger(O)&&O>0&&O<=65535?O:null}function Ne(j,O,N){if(!j.some((L)=>L.path===O&&L.kind===N))j.push({path:O,kind:N})}async function Ei(j,O,N){let L=[],F=[],H=[],M=[],U=new Map,D=new Set,J=new Set,B=[],G={},q=null,Q=0,te=await ft(j,".cursor/environment.json");if(te){Ne(L,".cursor/environment.json","cursor");let ne=Si(te);if(!ne)B.push("Could not parse .cursor/environment.json; it remains quarantined.");else{F.push(...Qe(ne.install));let K=Qe(ne.start);if(K[0])q=K[0];if(Array.isArray(ne.terminals))for(let W of ne.terminals){if(!W||typeof W!=="object")continue;let ee=W;if(typeof ee.command!=="string"||!ee.command.trim())continue;M.push({name:typeof ee.name==="string"&&ee.name.trim()?ee.name.trim():"Terminal",command:ee.command.trim(),...typeof ee.cwd==="string"&&ee.cwd.trim()?{cwd:ee.cwd.trim()}:{}})}}}let V=O.has(".devcontainer/devcontainer.json")?".devcontainer/devcontainer.json":O.has("devcontainer.json")?"devcontainer.json":null;if(V){Ne(L,V,"devcontainer");let ne=Si(N.get(V)??await ft(j,V)??"");if(!ne)B.push(`Could not parse ${V}; it remains quarantined.`);else{F.push(...Qe(ne.onCreateCommand),...Qe(ne.updateContentCommand),...Qe(ne.postCreateCommand));let K=Qe(ne.postStartCommand);if(!q&&K[0])q=K[0];for(let W of ns(ne.secrets))D.add(W);for(let W of[...ns(ne.containerEnv),...ns(ne.remoteEnv)])D.add(W);if(Array.isArray(ne.forwardPorts))for(let W of ne.forwardPorts){let ee=ji(W);if(ee)U.set(ee,{port:ee,visibility:"private"})}}}if(O.has(".gitpod.yml")){Ne(L,".gitpod.yml","gitpod");let ne=N.get(".gitpod.yml")??await ft(j,".gitpod.yml");if(ne===null)B.push("Could not read .gitpod.yml; its task commands were not imported.");else{let K=ki(ne);Q=K.tasks.filter((W)=>W.before).length;for(let W of K.tasks){if(W.before)F.push(W.before);if(W.init)F.push(W.init);if(!W.command)continue;if(!q)q=W.command;else M.push({name:W.name??"Terminal",command:W.command})}if(K.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 ne of["Dockerfile","docker-compose.yml","docker-compose.yaml","compose.yml","compose.yaml"])if(O.has(ne))Ne(L,ne,"docker");for(let ne of["project.toml","nixpacks.toml","railpack.json","Aptfile"])if(O.has(ne))Ne(L,ne,"buildpack");for(let ne of["fly.toml","railway.json","render.yaml","vercel.json","netlify.toml"])if(O.has(ne))Ne(L,ne,"platform");let z=N.get("package.json")??await ft(j,"package.json");if(z){Ne(L,"package.json","package");try{let ne=JSON.parse(z);if(ne.engines?.node)G.node=ne.engines.node;let K=Ul(O,ne.packageManager);if(K&&F.length===Q)F.push(K);if(ne.scripts?.build&&H.length===0)H.push(`${ne.packageManager?.split("@")[0]??(O.has("bun.lock")?"bun":"npm")} run build`);let W=ne.scripts?.dev?`${O.has("bun.lock")?"bun":"npm"} run dev`:null,ee=ne.scripts?.start?`${O.has("bun.lock")?"bun":"npm"} run start`:W;if(!q&&ee)q=ee}catch{B.push("Could not parse package.json for environment discovery.")}}if(O.has("uv.lock"))F.push("uv sync --frozen");else if(O.has("poetry.lock"))F.push("poetry install --no-interaction");else if(O.has("requirements.txt"))F.push("python -m pip install -r requirements.txt");if(O.has("go.mod"))F.push("go mod download");if(O.has("Procfile")){Ne(L,"Procfile","procfile");let K=(N.get("Procfile")??"").split(/\r?\n/).find((W)=>/^web\s*:/.test(W));if(K)q=K.replace(/^web\s*:\s*/,"").trim()||q}let Z=[[".node-version","node"],[".nvmrc","node"],[".python-version","python"]];for(let[ne,K]of Z){let W=(N.get(ne)??await ft(j,ne))?.trim();if(W)G[K]=W,Ne(L,ne,"tool-version")}let X=N.get(".tool-versions")??await ft(j,".tool-versions");if(X){Ne(L,".tool-versions","tool-version");for(let ne of X.split(/\r?\n/)){let[K,W]=ne.trim().split(/\s+/,2);if(!W)continue;if(K==="nodejs")G.node=W;else if(K==="python")G.python=W;else if(K==="bun")G.bun=W}}let re=N.get("mise.toml")??await ft(j,"mise.toml");if(re){Ne(L,"mise.toml","tool-version");for(let ne of re.matchAll(/^\s*(node|python|bun)\s*=\s*["']([^"']+)["']/gm))G[ne[1]]=ne[2]}for(let[ne,K]of N){let W=/(?:^|\/)(?:Dockerfile|Procfile)$/i.test(ne)||/\.(?:jsonc?|ya?ml|toml|ini|conf|config|env|sh|bash|zsh|fish)$/i.test(ne);for(let ee of Ml(K,W))J.add(ee);for(let ee of K.matchAll(/(?:--port(?:=|\s+)|PORT\s*=\s*)(\d{2,5})/g)){let de=ji(ee[1]);if(de)U.set(de,{port:de,visibility:"private"})}}if(L.length===0&&O.size>0)Ne(L,"repository","detected");let ue=(ne)=>[...new Set(ne.filter(Boolean))],fe=L.length+F.length+(q?1:0);return{sources:L.sort((ne,K)=>ne.path.localeCompare(K.path)),toolchain:G,install:ue(F),build:ue(H),start:q,terminals:M,ports:[...U.values()].sort((ne,K)=>ne.port-K.port),requiredSecretKeys:[...D].sort(),observedSecretKeys:[...J].sort(),confidence:fe>=4?"high":fe>=2?"medium":"low",warnings:B}}var xi=2;var Fi=300000,Xl=25000,Pi=52428800,Yl=524288000,pn=1e4,Zl="Potential secrets exist in Git history",Ql="Never delete .git folders or files to get past this; use .hlixignore instead.",Jn=1048576,an=20971520,Hi=[".git/",".hlix/","node_modules/",".next/",".turbo/",".cache/","dist/","build/","coverage/","__pycache__/",".venv/","venv/","target/",".DS_Store"],hf=ln().add(Hi);var as="Required project environment value was not found locally: ",ed=/(^|\/)\.env\.(example|sample|template)$/i,td=/(^|\/)\.env(?:\.[^/]+)?$/i,nd=/(^|\/)(?:\.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,rd=/\.(?:example|sample|template)$/i,sd=/(^|\/)\.(?:npmrc|yarnrc(?:\.yml)?|pypirc)$/i,od=/(?:^|\/)(?:__tests__|tests?|fixtures)\/|\.(?:test|spec)\.[^/]+$|\.snap$/i,id=/\.(?:md|mdx|txt|rst)$/i,ad=/fake|dummy|example|placeholder|unused|changeme|xxxx|redacted|your[_-]|<[^>]*>/i,cd=/^(.)\1+$/,ld=/RegExp\(/,cs="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,}",dd=new RegExp(cs,"g"),pd=/(^|\/)(?:\.mcp\.json|mcp\.json|claude_desktop_config\.json)$/i,ud=/(^|\/)(?:AGENTS\.md|CLAUDE\.md|\.cursorrules|\.github\/copilot-instructions\.md)$/i,md=/(^|\/)(?:\.agents|\.claude)\/skills\//i,os=/-----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,}/,yf=new RegExp(os.source,"g"),$i=/\.(?:json|ya?ml|toml|ini|conf|config)$/i,_i=/(?:^|[,{\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,cn=new Set(["HLIX_AGENT_RUN_ID","HLIX_API_KEY","HLIX_API_URL","HLIX_BASE_URL","HLIX_PROJECT_ID","HLIX_SESSION_TOKEN","HLIX_WORKSPACE_ID"]),rs="Your hlix credentials were left out of the project's secrets — the platform provides them.",ss=new Set(["CI","HOME","LANG","LOGNAME","NODE_ENV","OLDPWD","PATH","PORT","PWD","SHELL","SHLVL","TERM","TMPDIR","USER","_"]),fd=100,Ci=12;function gd(j){let O=j.slice(0,Ci).join(", "),N=j.length-Ci;return j.length===1?`Observed environment reference has no local value: ${j[0]}`:`${j.length} observed environment references have no local value: ${O}${N>0?`, +${N} more`:""}`}var hd=250;function et(j){return j.split(zl).join("/")}function ze(j){if(j>=1048576)return`${(j/1048576).toFixed(1)} MB`;if(j>=1024)return`${(j/1024).toFixed(1)} KB`;return`${j} bytes`}function Ii(j,O=5){return[...j].sort((N,L)=>L.size-N.size||N.path.localeCompare(L.path)).slice(0,O).map((N)=>`${N.path} (${ze(N.size)})`).join(", ")}function yd(j,O=5){let N=new Map;for(let L of j){let F=L.indexOf("/"),H=F===-1?".":L.slice(0,F);N.set(H,(N.get(H)??0)+1)}return[...N].sort((L,F)=>F[1]-L[1]||L[0].localeCompare(F[0])).slice(0,O).map(([L,F])=>`${L}/ (${F} files)`).join(", ")}function Le(j,O,N=10485760){return Vl("git",["-C",j,...O],{encoding:"utf8",timeout:Fi,maxBuffer:N,stdio:["ignore","pipe","pipe"]})}function d(j,O,N={}){return new Promise((L)=>{Kl("git",["-C",j,...O],{encoding:"utf8",timeout:Fi,maxBuffer:N.maxBuffer??10485760,...N.signal?{signal:N.signal}:{}},(F,H)=>{let M=F?.code;L({status:F===null?0:typeof M==="number"?M:1,stdout:typeof H==="string"?H:""})})})}async function wd(j){let O=un("sha256");for await(let N of Dl(j))O.update(N);return O.digest("hex")}function is(j){if(Array.isArray(j))return`[${j.map(is).join(",")}]`;if(j&&typeof j==="object")return`{${Object.entries(j).sort(([O],[N])=>O.localeCompare(N)).map(([O,N])=>`${JSON.stringify(O)}:${is(N)}`).join(",")}}`;return JSON.stringify(j)}function Mi(j){let O={};for(let[N,L]of String(j).replace(/^\uFEFF/,"").split(/\r?\n/).entries()){let F=L.trim();if(!F||F.startsWith("#"))continue;let M=(F.startsWith("export ")?F.slice(7).trimStart():F).match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);if(!M)throw Error(`Invalid dotenv assignment on line ${N+1}`);let U=M[2]??"";if(U.startsWith('"')){if(!U.endsWith('"'))throw Error(`Unclosed dotenv quote on line ${N+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 ${N+1}`);U=U.slice(1,-1)}else U=U.replace(/\s+#.*$/,"").trimEnd();O[M[1]]=U}return O}function vd(j,O){return j.split(/(?<=\n)/).filter((N)=>{let L=N.trim(),H=(L.startsWith("export ")?L.slice(7).trimStart():L).match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=/)?.[1];return H===void 0||!O.has(H)}).join("")}function bd(j){let O=null;for(let N=0;N<j.length;N+=1){let L=j[N];if(L==="\\"&&O!=="single"){if(j[N+1]!=="$")return!0;N+=1;continue}if(L==="'"&&O!=="double"){O=O==="single"?null:"single";continue}if(L==='"'&&O!=="single"){O=O==="double"?null:"double";continue}if(O!=="single"&&(L==="$"||L==="`"))return!0;if(O===null&&(L==="<"||L===">")&&j[N+1]==="(")return!0}return O!==null}function kd(j){let O={},N=new Set,L=new Set;for(let F of String(j).replace(/^\uFEFF/,"").split(/\r?\n/)){let H=F.trim();if(!H||H.startsWith("#"))continue;let U=(H.startsWith("export ")?H.slice(7).trimStart():H).match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);if(!U)continue;let D=U[1],J=U[2]??"";if(N.add(D),bd(J)){delete O[D],L.add(D);continue}try{let G=Mi(`${D}=${J}`)[D];if(G===void 0)throw Error("missing literal");O[D]=J.trimStart().startsWith("'")?G:G.replace(/\\\$/g,"$"),L.delete(D)}catch{delete O[D],L.add(D)}}return{values:O,keys:[...N].sort(),dynamicKeys:[...L].sort()}}async function Sd(j){let O=Le(j,["rev-parse","--show-toplevel"]);if(O.status!==0)return!1;try{return await Ni(O.stdout.trim())===j}catch{return!1}}function jd(j,O){if(!O)return new Set;let N=Le(j,["ls-files","-z"]);if(N.status!==0)throw Error("Could not enumerate tracked files.");return new Set(N.stdout.split("\x00").filter(Boolean).map(et))}function Ed(j,O){if(!O)return[];let N=Le(j,["config","--get-regexp","^remote\\..*\\.url$"]);if(N.status!==0)return[];let L=[];for(let F of N.stdout.split(`
|
|
326
|
+
`)){let H=F.trim();if(!H)continue;let M=/^remote\.(.*)\.url (.+)$/.exec(H);if(M)L.push({name:M[1],url:M[2]})}return L}function xd(j,O){if(!O)return{files:new Set,directories:[]};let N=Le(j,["ls-files","-z","--others","--ignored","--exclude-standard","--directory"]);if(N.status!==0)throw Error("Could not enumerate ignored files.");let L=new Set,F=[];for(let H of N.stdout.split("\x00").filter(Boolean)){let M=et(H);if(M.endsWith("/"))F.push(M);else L.add(M)}return{files:L,directories:F}}async function Ri(j,O){let N=[],L=[],F=[],H="";for(let J of[".gitignore",".hlixignore"])try{let B=mn(j,J),G=await Oi(B);if(J===".gitignore"&&G.isSymbolicLink()){L.push(J);continue}if(G.isFile()||G.isSymbolicLink())try{if(G.isSymbolicLink()&&!(await Li(B)).isFile()){N.push(J);continue}let q=await dn(B,"utf8");if(J===".hlixignore")H=q;let Q=J===".hlixignore"?on(q):null;if(O&&Q?.managed)q=q.replace(Q.managed,O.join(`
|
|
327
|
+
`));F.push(q)}catch{N.push(J)}}catch(B){if(B.code!=="ENOENT")N.push(J)}let M=on(H)?.managed??"",U=M?[".git/",".hlix/"]:Hi,D=ts(H);return{hardMatcher:ln().add(D.length?[".git/",".hlix/"]:U),matcher:ln().add([...U,...F.flatMap((J)=>J.split(/\r?\n/))]),unignored:ln().add(D),managedMatcher:ln().add(O??M),hasManaged:Boolean(M),unreadable:N,symlinked:L}}function Bn(j){if(pd.test(j))return"mcp";if(md.test(j))return"skill";if(ud.test(j))return"agent";return null}function Gn(j){if(td.test(j)&&!ed.test(j))return"dotenv";if(nd.test(j))return"credential";return null}function Pd(j,O){if(O)return[et(O)];let N=new Map([[".env",0],[".env.development",1],[".env.local",2],[".env.development.local",3]]),L=j.filter((F)=>N.has(gt(F).toLocaleLowerCase("en-US"))).sort((F,H)=>F.slice(0,-gt(F).length).localeCompare(H.slice(0,-gt(H).length))||N.get(gt(F).toLocaleLowerCase("en-US"))-N.get(gt(H).toLocaleLowerCase("en-US")));return L.length>0?L:j.length===1?[...j]:[]}function $d(j,O){try{let N=JSON.parse(O);if(!N.mcpServers||typeof N.mcpServers!=="object")return[];return Object.entries(N.mcpServers).map(([L,F])=>{let H=F&&typeof F==="object"?F:{},M=H.type==="http"||H.type==="sse"||H.type==="stdio"?H.type:typeof H.command==="string"?"stdio":typeof H.url==="string"?"http":"unknown",U=H.env&&typeof H.env==="object"?H.env:{};return{sourcePath:j,name:L,transport:M,...typeof H.command==="string"?{command:H.command}:{},...Array.isArray(H.args)&&H.args.every((D)=>typeof D==="string")?{args:H.args}:{},...typeof H.url==="string"?{url:H.url}:{},envKeys:Object.keys(U).sort(),enabled:!1}})}catch{return[]}}function _d(j){let O=!1,N=!1;for(let L of j.split(/\r?\n/)){let F=L.trim();if(!F||F.startsWith("#")||F.startsWith(";")||F.startsWith("["))continue;let H=F.indexOf("=");if(H===-1)continue;let M=F.slice(0,H).trim().toLowerCase(),U=F.slice(H+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"))N=!0;else if(M.endsWith("username"))O=!0}return O&&N}async function Cd(j,O,N,L){if(rd.test(N))return!1;if(!sd.test(N))return!0;let F=await d(j,["show",`${O}:${N}`],{...L?{signal:L}:{}});return F.status===0&&_d(F.stdout)}function Id(j,O,N){let L=j.lastIndexOf("/",O),F=j.indexOf("/",N);return L!==-1&&F!==-1&&!/\s/.test(j.slice(L,O)+j.slice(N,F))}function Rd(j){if(od.test(j))return"test fixture";if(id.test(j))return"documentation or pattern definition";return null}function Td(j,O){let N=null;for(let L of j.split(/\r?\n/))for(let F of L.matchAll(O)){let H=F[0],M=F.index??0,U=ld.test(L)||Id(L,M,M+H.length)?"documentation or pattern definition":ad.test(H)||cd.test(H)?"placeholder value":null;if(U===null)return null;N??=U}return N}async function Ad(j,O,N,L){let F=Rd(N);if(F!==null)return F;let H=await d(j,["show",`${O}:${N}`],{...L?{signal:L}:{}});return H.status===0?Td(H.stdout,dd):null}async function Ti(j,O,N){let L=[],F="unknown";for(let H of j.split(/\r?\n/)){if(H.startsWith("@@"))F=H.slice(2);else if(H.trim()){let M=et(H.trim());if(await N(F,M))L.push({commit:F,path:M,reason:O})}if(L.length>=100)break}return L}async function Ai(j,O,N={}){if(!O)return{head:null,branch:null,refs:[],commitCount:0,complete:!0,findings:[],blockingFindings:[],waivedReasons:[]};let L=Le(j,["rev-parse","HEAD"]).stdout.trim()||null,F=Le(j,["symbolic-ref","--short","-q","HEAD"]),H=F.status===0?F.stdout.trim()||null:null,M=Number.parseInt(Le(j,["rev-list","--count","--all"]).stdout.trim(),10)||0,U=Le(j,["for-each-ref","--format=%(refname)%00%(objectname)","refs/heads","refs/tags"]),D=U.stdout.split(`
|
|
328
|
+
`).filter(Boolean).map((Z)=>{let[X,re]=Z.split("\x00");return{name:X,oid:re}}).filter(({name:Z,oid:X})=>/^refs\/(?:heads|tags)\/.+/.test(Z)&&/^[0-9a-f]{40,64}$/.test(X)).sort((Z,X)=>Z.name.localeCompare(X.name)),J=N.signal,B=J?{signal:J}:{};N.onProgress?.(`history: ${M} commit${M===1?"":"s"}…`);let G=["log","--all",`--max-count=${pn}`,"--pretty=format:@@%H","--name-only"],q=await d(j,[...G,"--",".env",".env.*","*.pem","*.key",".npmrc","*.tfvars"],B),Q=await d(j,["log","--all",`--max-count=${pn}`,"-G",cs,"--pretty=format:@@%H","--name-only"],B);J?.throwIfAborted();let te=new Map;for(let Z of[...await Ti(q.stdout,"sensitive-path",(X,re)=>Cd(j,X,re,J)),...await Ti(Q.stdout,"secret-pattern",async()=>!0)])te.set(`${Z.commit}:${Z.path}:${Z.reason}`,Z);let V=[...te.values()].slice(0,100),z=new Map;for(let Z of V){if(Z.reason!=="secret-pattern")continue;let X=await Ad(j,Z.commit,Z.path,J);if(X!==null)z.set(Z,X)}return N.onProgress?.(`history: ${M} commit${M===1?"":"s"} scanned`),{head:L,branch:H,refs:D,commitCount:M,complete:M<=pn&&D.length<=1000&&U.status===0&&q.status===0&&Q.status===0,findings:V,blockingFindings:V.filter((Z)=>!z.has(Z)),waivedReasons:[...z.values()]}}function Od(j,O){let N=O?.XDG_CACHE_HOME??(O?.HOME?mn(O.HOME,".cache"):null);if(!N)return null;return mn(N,"hlix","history",`${un("sha256").update(j).digest("hex")}.json`)}async function Nd(j,O,N){let L=O?Od(j,N.environment):null;if(!L)return Ai(j,O,N);let F=un("sha256").update([Le(j,["for-each-ref","--format=%(refname)%00%(objectname)"]).stdout,Le(j,["rev-parse","HEAD"]).stdout,Le(j,["symbolic-ref","--short","-q","HEAD"]).stdout,cs,String(pn)].join("\x00")).digest("hex");try{let M=JSON.parse(await dn(L,"utf8"));if(M.key===F&&M.history)return N.onProgress?.(`history: ${M.history.commitCount} commits, unchanged since the last scan`),M.history}catch{}let H=await Ai(j,O,N);if(H.complete)try{await Jl(ql(L),{recursive:!0,mode:448}),await Wl(L,JSON.stringify({key:F,history:H}),{mode:384})}catch{}return H}async function Je(j,O={}){let N=await Ni(Dn(j));if(!(await Li(N)).isDirectory())throw Error("Import target must be a directory.");let L=await Sd(N),F=Ed(N,L),H=jd(N,L),M=new Set(L?(await d(N,["ls-files","--stage","-z"])).stdout.split("\x00").filter((Y)=>Y.startsWith("160000 ")).map((Y)=>Y.slice(Y.indexOf("\t")+1)):[]),U=xd(N,L),D=[...new Set([...i(N)?.includedPaths??[],...O.include?[O.include]:[]].map((Y)=>Y.replace(/^\.\//,"").replace(/\/$/,"")))],J=await Ri(N),B=O.refreshIgnore||J.hasManaged?await bi(N,{write:O.refreshIgnore===!0,tracked:L?H:new Set((await d(N,["ls-files","-z"])).stdout.split("\x00").filter(Boolean)),includes:D,gitIgnored:U,signal:O.signal,maxFileBytes:O.maxFileBytes??Pi,isRepository:async(Y)=>{let ie=await d(mn(N,Y),["rev-parse","--show-toplevel"]);return ie.status===0&&Dn(ie.stdout.trim())===Dn(N,Y)},protectedPath:(Y,ie)=>Boolean(Gn(Y)||!ie&&Bn(Y)),protectedContent:(Y,ie)=>os.test(ie)||$i.test(Y)&&_i.test(ie)}):void 0,{hardMatcher:G,matcher:q,unignored:Q,managedMatcher:te,unreadable:V,symlinked:z}=B?await Ri(N,B.rules??[]):J,Z=V.length?`Upload left unchanged: cannot read ${V.join(", ")}; check the ignore file target and permissions before retrying.`:void 0,X=[],re=[],ue=[],fe=[],ne=[],K=[],W=[],ee=[],de=O.envFile?et(Un(N,Dn(N,O.envFile))):void 0,ge=de!==void 0&&de!==""&&de!==".."&&!de.startsWith("../");if(O.envFile&&!ge)ee.push(`Selected environment file must stay inside the project: ${O.envFile}`);let he=new Map,Ee=new Map,ye=new Map,je=new Map,we=B?.warning?[B.warning]:[],ht=new Set,yt=[],Ke=[],wt=new Map,yn=O.maxFiles??Xl,nt=O.maxFileBytes??Pi,pe=O.maxTotalBytes??Yl,le=O.historyMode==="sanitize",be=0,rt=0,wn=async(Y,ie=!1)=>{let ke=await Bl(Y,{withFileTypes:!0}).catch(($e)=>{let Ce=et(Un(N,Y))||"repository";if(W.push({path:Ce,reason:`Cannot read folder (${$e.code??"unreadable"}); check read and search permissions`}),we.push(`Cannot read folder ${Ce}; check its read and search permissions. Existing cloud files are preserved.`),Y===N)Z="Upload left unchanged: cannot read the project folder; check its permissions.";return[]});ke.sort(($e,Ce)=>$e.name.localeCompare(Ce.name));for(let $e of ke){if(O.signal?.throwIfAborted(),rt+=1,rt%hd===0)O.onProgress?.(`scanning … ${X.length} files`);let Ce=mn(Y,$e.name),ce=et(Un(N,Ce));if($e.name===".git"){if(ce!==".git"&&!ie)ht.add(et(Un(N,Y)));continue}if(ce.length>1000||ce.includes("\\")||ce.includes("\x00")){we.push(`Skipped a path that cannot be represented safely: ${ce.slice(0,350)}`);continue}try{let Pe=await Oi(Ce),Mt=$e.isDirectory()?`${ce}/`:ce,qs=H.has(ce)&&!M.has(ce),Ut=!(rn(ce,D)||Q.ignores(Mt))&&!qs&&(q.ignores(Mt)||U.files.has(ce)||U.directories.some((ve)=>Mt.startsWith(ve))),zs=!sn(ce,D)&&G.ignores(Mt);if(zs){if(ce!==".hlix")W.push({path:ce,reason:"built-in ignore"});continue}if(Ut&&te.ignores(Mt))W.push({path:ce,reason:"Hlix-managed ignore"});if(Pe.isSymbolicLink()){if(Ut)continue;if(re.push({path:ce,target:await Gl(Ce)}),Bn(ce)||Gn(ce))ue.push(ce);continue}if($e.isDirectory()){if(zs)continue;if(M.has(ce)&&!Ut)ht.add(ce);await wn(Ce,Ut);continue}let bt=Bn(ce),kt=Gn(ce);if(Ut&&!bt&&!kt)continue;if(!$e.isFile()){W.push({path:ce,reason:"non-regular-file"});continue}if(Pe.size>nt&&!bt&&!kt){W.push({path:ce,reason:Zr(ce)});continue}if(Pe.size>nt){ee.push(`File ${ce} is ${ze(Pe.size)}, over the ${ze(nt)} per-file limit. Exclude it with .hlixignore.`);continue}let Dt=await wd(Ce);if(bt){if(Pe.size>Jn){ee.push(`Protected configuration ${ce} is ${ze(Pe.size)}, over the ${ze(Jn)} per-file limit. Move the large content out of it, or exclude it with .hlixignore.`);continue}let ve=await dn(Ce);if(be+=ve.byteLength,Ke.push({path:ce,size:ve.byteLength}),be>an)continue;if(ne.push({path:ce,kind:bt,size:Pe.size,sha256:Dt}),yt.push({path:ce,kind:bt,contentBase64:ve.toString("base64")}),bt==="mcp")K.push(...$d(ce,ve.toString("utf8")));continue}if(kt){if(Pe.size>Jn){ee.push(`Protected file ${ce} is ${ze(Pe.size)}, over the ${ze(Jn)} per-file limit. Move the large content out of it, or exclude it with .hlixignore.`);continue}let ve=await dn(Ce);if(be+=ve.byteLength,Ke.push({path:ce,size:ve.byteLength}),be>an)continue;let ot=[],St=new Set;if(kt==="dotenv")try{let kn=Mi(ve),jt={};for(let[Xe,Et]of Object.entries(kn)){if(cn.has(Xe)){St.add(Xe);continue}jt[Xe]=Et}he.set(ce,jt),ot=Object.keys(jt).sort()}catch{ee.push(`Could not parse environment file: ${ce}`)}else if(gt(ce)===".envrc"){let kn=kd(ve),jt={},Xe=new Set,Et=[];for(let[Ie,ha]of Object.entries(kn.values)){if(cn.has(Ie)){St.add(Ie);continue}if(ss.has(Ie)){we.push(`Ignored ambient runtime assignment in ${ce}: ${Ie}`);continue}Xe.add(Ie),jt[Ie]=ha}Ee.set(ce,jt);for(let Ie of kn.dynamicKeys){if(cn.has(Ie)){St.add(Ie);continue}if(ss.has(Ie)){we.push(`Ignored ambient runtime assignment in ${ce}: ${Ie}`);continue}Xe.add(Ie),Et.push(Ie)}if(ye.set(ce,[...Xe].sort()),je.set(ce,Et.sort()),ot=[...Xe].sort(),Et.length>0)we.push(`Did not execute dynamic .envrc assignments; collect their resolved local values when available: ${Et.join(", ")}`)}if(St.size>0)we.push(rs),ve=Buffer.from(vd(ve.toString("utf8"),St),"utf8"),Dt=un("sha256").update(ve).digest("hex");fe.push({path:ce,kind:kt,keys:ot,size:ve.byteLength,sha256:Dt}),yt.push({path:ce,kind:kt,contentBase64:ve.toString("base64")});continue}if(Pe.size<=1048576){let ve=await dn(Ce),ot=ve.toString("utf8");if(wt.set(ce,ot),os.test(ot)||$i.test(ce)&&_i.test(ot)){if(be+=ve.byteLength,Ke.push({path:ce,size:ve.byteLength}),be>an)continue;fe.push({path:ce,kind:"detected-content",keys:[],size:Pe.size,sha256:Dt}),yt.push({path:ce,kind:"detected-content",contentBase64:ve.toString("base64")});continue}}X.push({path:ce,size:Pe.size,sha256:Dt,tracked:qs,executable:(Pe.mode&73)!==0})}catch(Pe){if(O.signal?.throwIfAborted(),Gn(ce)||Bn(ce))throw Pe;W.push({path:ce,reason:`Cannot read file (${Pe.code??"unreadable"})`})}}};await wn(N);let st=fi([...X,...re],Math.max(0,yn-fe.length-ne.length),pe,D);if(st.length)X=X.filter((Y)=>!Yr(Y.path,st)),re=re.filter((Y)=>!Yr(Y.path,st)),W.push(...st.map((Y)=>({path:Y.replace(/\/$/,""),reason:Zr(Y)})));if(O.onProgress?.(`scanning … ${X.length} files`),O.onProgress?.(`secrets: ${fe.length+ne.length} files`),O.signal?.throwIfAborted(),ue.length>0){let Y=ue.slice(0,5).join(", "),ie=ue.length-5;we.push(`Imported as symlinks, so no content was read or uploaded for them and the cloud recreates the link: ${Y}${ie>0?`, +${ie} more`:""}`)}for(let Y of z)we.push(`Ignore file ${Y} is a symlink, so its rules were not applied. Replace it with a regular file inside the project.`);if(Z)we.push(Z);if(be>an)ee.push(`Protected project files total ${ze(be)}, over the ${ze(an)} limit. Largest: ${Ii(Ke)}. Move large assets out of skill and config folders, or add them to .hlixignore.`);if(fe.length>2000)ee.push(`Project has ${fe.length} environment and credential files, over the 2000 limit. Largest: ${Ii(fe)}. Exclude the ones the cloud project does not need with .hlixignore.`);if(ne.length>5000)ee.push(`Project has ${ne.length} agent, skill and MCP files, over the 5000 limit. Largest folders: ${yd(ne.map((Y)=>Y.path))}. Exclude the ones the cloud project does not need with .hlixignore.`);X.sort((Y,ie)=>Y.path.localeCompare(ie.path)),re.sort((Y,ie)=>Y.path.localeCompare(ie.path)),fe.sort((Y,ie)=>Y.path.localeCompare(ie.path)),ne.sort((Y,ie)=>Y.path.localeCompare(ie.path)),K.sort((Y,ie)=>`${Y.sourcePath}:${Y.name}`.localeCompare(`${ie.sourcePath}:${ie.name}`));let vt=Pd([...he.keys()].sort(),ge?de:void 0);if(O.envFile&&ge&&!he.has(vt[0]))ee.push(`Selected environment file was not found or is not a dotenv file: ${O.envFile}`);let Ve=new Map;for(let[Y,ie]of he)for(let ke of Object.keys(ie))Ve.set(ke,[...Ve.get(ke)??[],Y]);for(let[Y,ie]of ye)for(let ke of ie)Ve.set(ke,[...Ve.get(ke)??[],Y]);let vn=[...Ve].filter(([,Y])=>Y.length>1).map(([Y,ie])=>({key:Y,paths:ie.sort()})).sort((Y,ie)=>Y.key.localeCompare(ie.key)),He={};for(let Y of vt)Object.assign(He,he.get(Y)??{});let Ae=[...Ee.keys()].sort((Y,ie)=>{if(Y===".envrc")return 1;if(ie===".envrc")return-1;return Y.localeCompare(ie)}),Ht=new Set;for(let Y of Ae){let ie=new Set(je.get(Y)??[]);for(let ke of ye.get(Y)??[]){if(ie.has(ke)){delete He[ke],Ht.add(ke);continue}let $e=Ee.get(Y)?.[ke];if($e!==void 0)He[ke]=$e;Ht.delete(ke)}}for(let Y of ht)we.push(`${Y} has its own Git repository — uploaded as files, its history not included`);let ua=O.historyMode==="abort_on_findings"?"abort_on_findings":"preserve";if(le)we.push("Git history omitted; uploading a snapshot of the current files.");let Oe=await Nd(N,L,O);if(!Oe.complete)we.push(`Git history scan exceeded ${pn} commits or failed; history is preserved, but the findings may be incomplete.`);if(L&&!Oe.head)le=!0,we.push("Git has no readable HEAD; uploading the current files as a snapshot.");let Ds=Oe.waivedReasons;for(let Y of[...new Set(Ds)].sort()){let ie=Ds.filter(($e)=>$e===Y).length,ke=ie===1;we.push(`${ie} Git history finding${ke?"":"s"} did not block this import — ${Y}, not ${ke?"a real credential":"real credentials"}; --history preserve is not needed for ${ke?"it":"them"}.`)}if(Oe.blockingFindings.length>0){let Y=Oe.blockingFindings.length;we.unshift([`${Zl} (${Y} finding${Y===1?"":"s"}${Y>5?", first 5 shown":""}); ${le?"history is omitted":"history is preserved"}:`,...Oe.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 Js=new Set(X.map((Y)=>Y.path)),ma=await Ei(N,Js,wt),{observedSecretKeys:fa,...Me}=ma;Me.warnings.unshift(...we);let bn=new Set(Me.requiredSecretKeys);for(let Y of Ht)bn.add(Y);for(let Y of K)for(let ie of Y.envKeys)bn.add(ie);for(let Y of cn)if(bn.delete(Y))Me.warnings.push(rs);Me.requiredSecretKeys=[...bn].sort();for(let Y of Me.requiredSecretKeys){if(He[Y]!==void 0)continue;let ie=O.environment?.[Y];if(ie===void 0){ee.push(`${as}${Y}`);continue}He[Y]=ie}let Yn=[];for(let Y of fa){if(cn.has(Y)){Me.warnings.push(rs);continue}if(ss.has(Y))continue;if(He[Y]!==void 0)continue;let ie=O.environment?.[Y];if(ie===void 0){Yn.push(Y);continue}He[Y]=ie}if(Yn.length>0)Me.warnings.push(gd(Yn.sort()));Me.warnings=[...new Set(Me.warnings.flatMap((Y)=>Y.split(`
|
|
330
|
+
`)))].map((Y)=>Y.slice(0,500)).slice(0,fd);let Bs=mi(new Map([...Js].map((Y)=>[Y,wt.get(Y)??null]))),Gs={schemaVersion:xi,rootName:O.rootName??gt(N),stack:Bs.language,git:{detected:L&&!le,head:le?null:Oe.head,branch:le?null:Oe.branch,refs:le?[]:Oe.refs,commitCount:le?0:Oe.commitCount,historyScanComplete:Oe.complete,historyMode:ua},files:X,symlinks:re,secretFiles:fe,activeEnvFiles:vt,secretKeys:Object.keys(He).sort(),envCollisions:vn,quarantinedResources:ne,mcpServers:K,historicalSecretFindings:Oe.blockingFindings,skipped:gi(W),environment:Me,totals:{files:X.length,bytes:X.reduce((Y,ie)=>Y+ie.size,0)}},Ws=is(Gs),ga=un("sha256").update(Ws).digest("hex");return{root:N,includedPaths:D,ignoreReport:O.refreshIgnore?B?.report??B?.warning:void 0,uploadWarning:Z,stackFacts:Bs,manifest:Gs,...W.length>5000?{skippedEntries:W}:{},manifestJson:Ws,manifestSha256:ga,secretValues:He,protectedFiles:yt.sort((Y,ie)=>Y.path.localeCompare(ie.path)),blocking:[...new Set(ee)].map((Y)=>`${Y}
|
|
331
|
+
${Ql}`),blockingHistoryFindings:[],gitRemotes:F}}var ls={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 Ld(Fd(j.cwd,j.args[0]??".")),N=r({env:j.env,flags:j.flags,cwd:O});if(N.conflict)throw new e("workspace_mismatch",N.conflict);if(!N.workspaceId)throw Error("No workspace selected. Run `hlix auth login --workspace <id>` first.");let L=j.requireClient(O);await L.projects.list();let F=xt(O),H=typeof j.flags.project==="string"?j.flags.project:void 0;if(H&&F?.projectId&&F.projectId!==H)throw new e("workspace_mismatch",`This folder is bound to project ${F.projectId}; refusing to rebind it to ${H}.`);if(H)await L.projects.get(H);let M={...F??{schemaVersion:1,workspaceId:N.workspaceId,apiUrl:N.baseUrl},...H?{projectId:H}:{}};xn(O,M);let U=await Je(O,{environment:j.env,refreshIgnore:!0}),D={root:O,config:M,ignoreReport:U.ignoreReport,scan:{files:U.manifest.totals.files,bytes:U.manifest.totals.bytes,secretFiles:U.manifest.secretFiles.map((J)=>J.path),quarantinedResources:U.manifest.quarantinedResources.map((J)=>J.path),blocking:U.blocking}};if(j.json)j.stdout(se(oe(ls.name,D)));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((J)=>`- ${J}`).join(`
|
|
339
|
+
`)}
|
|
340
|
+
`)}return 0}};import{basename as gp,resolve as hp}from"node:path";import{realpath as yp}from"node:fs/promises";import{mkdtemp as ip,rm as zn,readFile as ap,writeFile as cp,chmod as lp,symlink as dp,lstat as pp}from"node:fs/promises";import{tmpdir as up}from"node:os";import{join as us}from"node:path";import{createHash as Hd}from"node:crypto";import{createReadStream as Md}from"node:fs";import{chmod as Ui,copyFile as Ud,lstat as Dd,mkdir as ds,mkdtemp as Jd,readdir as Bd,readlink as Gd,rm as ps,symlink as Wd}from"node:fs/promises";import{tmpdir as qd}from"node:os";import{dirname as Di,join as tt}from"node:path";import{spawnSync as Wn}from"node:child_process";var qn=300000;function Fe(j,O){let N=Wn("git",["-c","core.hooksPath=/dev/null","-C",j,...O],{encoding:"utf8",timeout:qn,maxBuffer:20971520,stdio:["ignore","pipe","pipe"]});if(N.status!==0){let L=N.stderr.trim().split(`
|
|
341
|
+
`).at(-1)??"git command failed";throw Error(L)}return N.stdout.trim()}async function zd(j){let O=Hd("sha256");for await(let N of Md(j))O.update(N);return O.digest("hex")}async function Kd(j){for(let O of await Bd(j)){if(O===".git")continue;await ps(tt(j,O),{recursive:!0,force:!0})}}async function Ji(j){if(j.manifest.git.detected&&(j.manifest.historicalSecretFindings.length||!j.manifest.git.historyScanComplete))throw Error("Git history has secrets or could not be fully scanned. Use --history sanitize to import current files.");if(j.uploadWarning)throw Error(j.uploadWarning);if(j.blocking.length>0)throw Error(`Project scan has blocking findings:
|
|
342
|
+
- ${j.blocking.join(`
|
|
343
|
+
- `)}`);let O=await Jd(tt(qd(),"hlix-snapshot-"));await Ui(O,448);let N=tt(O,"repo"),L=tt(O,"source.git");try{if(j.manifest.git.detected){let U=Wn("git",["clone","--mirror","--no-hardlinks",j.root,L],{encoding:"utf8",timeout:qn,stdio:["ignore","pipe","pipe"]});if(U.status!==0)throw Error(U.stderr.trim()||"Could not mirror repository.");let D=new Map(Fe(L,["for-each-ref","--format=%(refname)%00%(objectname)","refs/heads","refs/tags"]).split(`
|
|
344
|
+
`).filter(Boolean).map((B)=>B.split("\x00",2)));for(let B of j.manifest.git.refs)if(D.get(B.name)!==B.oid)throw Error(`Git ref changed after scan: ${B.name}`);let J=Wn("git",["clone","--no-hardlinks",L,N],{encoding:"utf8",timeout:qn,stdio:["ignore","pipe","pipe"]});if(J.status!==0)throw Error(J.stderr.trim()||"Could not create snapshot clone.");if(!j.manifest.git.head)throw Error("Git repository has no HEAD commit.");Fe(N,["checkout","-B","main",j.manifest.git.head])}else await ds(N,{recursive:!0,mode:448}),Fe(N,["init","-b","main"]);await Kd(N);for(let U of j.manifest.files){let D=tt(j.root,...U.path.split("/")),J=await Dd(D);if(!J.isFile()||J.isSymbolicLink())throw Error(`Source changed after scan: ${U.path}`);if(J.size!==U.size||await zd(D)!==U.sha256)throw Error(`Source changed after scan: ${U.path}`);let B=tt(N,...U.path.split("/"));await ds(Di(B),{recursive:!0,mode:493}),await Ud(D,B),await Ui(B,U.executable?493:420)}for(let U of j.manifest.symlinks){let D=tt(j.root,...U.path.split("/"));if(await Gd(D).catch(()=>null)!==U.target)throw Error(`Source changed after scan: ${U.path}`);let J=tt(N,...U.path.split("/"));await ds(Di(J),{recursive:!0,mode:493}),await Wd(U.target,J)}Fe(N,["config","user.name","Hlix Import"]),Fe(N,["config","user.email","import@hlix.ai"]),Fe(N,["read-tree","--empty"]),Fe(N,["add","--force","-A"]),Fe(N,["commit","--allow-empty","-m","chore(hlix): import snapshot"]);let F=Fe(N,["rev-parse","HEAD"]),H=new Set(j.manifest.git.refs.map((U)=>U.name));for(let U of Fe(N,["for-each-ref","--format=%(refname)","refs/heads","refs/tags"]).split(`
|
|
345
|
+
`).filter(Boolean))if(U!=="refs/heads/main"&&!H.has(U))Fe(N,["update-ref","-d",U]);let M=j.manifest.git.refs.filter((U)=>U.name!=="refs/heads/main");if(M.length>0){let U=Wn("git",["-C",N,"update-ref","--stdin"],{encoding:"utf8",timeout:qn,input:M.map((D)=>`update ${D.name} ${D.oid}`).join(`
|
|
346
|
+
`)+`
|
|
347
|
+
`,stdio:["pipe","pipe","pipe"]});if(U.status!==0)throw Error(U.stderr.trim()||"Could not recreate the approved Git refs.")}return{directory:N,commitSha:F,dispose:()=>ps(O,{recursive:!0,force:!0})}}catch(F){throw await ps(O,{recursive:!0,force:!0}),F}}import{lstat as Gi,mkdir as Vd,realpath as Xd}from"node:fs/promises";import{dirname as Yd,join as Zd,relative as Qd,resolve as ep,sep as Bi}from"node:path";function Wi(j,O){let N=j;if(typeof N==="string")try{N=JSON.parse(N)}catch{return[]}if(!N||typeof N!=="object")return[];let L=N[O];if(!Array.isArray(L))return[];return L.filter((F)=>!!F&&typeof F==="object")}function qi(j){return Wi(j,"files").flatMap((O)=>typeof O.path==="string"&&typeof O.sha256==="string"?[{path:O.path,sha256:O.sha256}]:[])}function zi(j){return Wi(j,"symlinks").flatMap((O)=>typeof O.path==="string"&&typeof O.target==="string"?[{path:O.path,target:O.target}]:[])}async function fn(j,O,N){let L=await Xd(j),F=ep(L,...O.split("/"));if(F!==L&&!F.startsWith(L+Bi))throw Error(`Protected path escapes the project: ${O}`);let H=Qd(L,Yd(F)),M=L;for(let U of H.split(Bi).filter(Boolean)){M=Zd(M,U);try{let D=await Gi(M);if(D.isSymbolicLink()&&N){N.push(M);break}if(!D.isDirectory()||D.isSymbolicLink())throw Error(`Protected path crosses a non-directory: ${O}`)}catch(D){if(D.code!=="ENOENT")throw D;if(!N)await Vd(M,{mode:448})}}return F}async function Ki(j,O,N){let L=N.length,F=await fn(j,O,N);if(N.length>L)return;try{let H=await Gi(F);if(H.isSymbolicLink()){N.push(F);return}if(!H.isFile())throw Error(`Refusing to replace non-regular project file: ${O}`)}catch(H){if(H.code!=="ENOENT")throw H}}import{spawnSync as tp}from"node:child_process";import{mkdtemp as np,writeFile as rp,rm as sp}from"node:fs/promises";import{tmpdir as op}from"node:os";import{join as Vi}from"node:path";function Xi(j,O,N){let L=tp("git",["-c","core.hooksPath=/dev/null","-C",j,...O],{encoding:"utf8",timeout:120000,maxBuffer:41943040,env:{PATH:process.env.PATH,GIT_CONFIG_GLOBAL:N??"/dev/null",GIT_CONFIG_NOSYSTEM:"1",GIT_TERMINAL_PROMPT:"0",GIT_AUTHOR_NAME:"HLIX",GIT_AUTHOR_EMAIL:"repos@hlix.ai",GIT_COMMITTER_NAME:"HLIX",GIT_COMMITTER_EMAIL:"repos@hlix.ai"}});if(L.status!==0)throw Error("HLIX Repos Git operation failed. The remote may have changed; refresh and retry.");return L.stdout.trim()}async function Yi(j,O){let N=new URL(j.cloneUrl);if(N.href!==j.cloneUrl||/[\r\n"\\]/.test(j.cloneUrl)||N.protocol!=="https:"||N.username||N.password||N.search||N.hash||N.port||!(N.hostname==="github.com"||/^[a-f0-9]{32}\.artifacts\.cloudflare\.net$/.test(N.hostname)))throw Error("Invalid HLIX Repos remote");if(/[\r\n]/.test(j.token))throw Error("Invalid repository credential");let L=await np(Vi(op(),"hlix-git-auth-")),F=Vi(L,"config"),H=j.token.replace(/\?expires=\d+$/,""),M=Buffer.from(`x-access-token:${H}`).toString("base64");try{return await rp(F,`[http "${j.cloneUrl}"]
|
|
348
|
+
extraHeader = Authorization: Basic ${M}
|
|
349
|
+
followRedirects = false
|
|
350
|
+
`,{mode:384}),await O(F)}finally{await sp(L,{recursive:!0,force:!0})}}function Nt(j){return new Map([...qi(j).map((O)=>[O.path,`blob:${O.sha256}`]),...zi(j).map((O)=>[O.path,`link:${O.target}`])])}var Zi={git:Xi,access:Yi};async function Lt(j){let O=t(j);if(!O?.config.projectId)throw new e("not_initialized","Run hlix import or hlix init to bind this folder to a project.");return{...O,state:i(O.root)}}async function Qi(j,O){let N=await Je(j,{environment:O,historyMode:"sanitize",maxFiles:50000,maxFileBytes:33554432,maxTotalBytes:1073741824});if(N.manifest.files=N.manifest.files.filter((L)=>L.path!==".hlixignore"),N.blocking.length)throw new e("scan_blocked",N.blocking.join(`
|
|
351
|
+
`));return N}function mp(j,O){let N=Object.fromEntries(Nt(j.manifest));return!O?.files?j.manifest.files.length+j.manifest.symlinks.length>0:JSON.stringify(Object.entries(N).sort())!==JSON.stringify(Object.entries(O.files).sort())}async function ms(j,O,N){let L=await j.projects.get(O),F=N?L.repos.find((H)=>H.id===N):L.repos.find((H)=>H.isPrimary)??(L.repos.length===1?L.repos[0]:void 0);if(!F)throw new e("conflict","Select a primary repository for this project before syncing.");return F}async function fs(j,O,N,L,F=!1,H=Zi){let{config:M,state:U}=await Lt(j),D=await ms(O,M.projectId,U?.repoId),J=await O.repos.head(M.projectId,D.id);if((L??U?.commitSha)&&J.commitSha!==(L??U?.commitSha))throw new e("conflict","HLIX Repos changed. Pull or sync before pushing.");let B=await Ji(N);try{let G=await O.repos.access(M.projectId,D.id,"write"),q=await H.access(G,async(Q)=>{H.git(B.directory,["fetch","--no-tags",G.cloneUrl,`refs/heads/${D.defaultBranch}`],Q);let te=H.git(B.directory,["rev-parse","FETCH_HEAD"]);if(te!==J.commitSha)throw new e("conflict","HLIX Repos changed during upload. Retry sync.");let V=H.git(B.directory,["rev-parse",`${B.commitSha}^{tree}`]),z=H.git(B.directory,["commit-tree",V,"-p",te,...F&&N.manifest.git.detected?["-p",B.commitSha]:[],"-m","Update HLIX Repos files"]);return H.git(B.directory,["push",`--force-with-lease=refs/heads/${D.defaultBranch}:${te}`,G.cloneUrl,`${z}:refs/heads/${D.defaultBranch}`],Q),z});return or(j,{schemaVersion:1,repoId:D.id,commitSha:q,files:Object.fromEntries(Nt(N.manifest)),snapshotOnly:!0,rootName:N.manifest.rootName}),{action:"push",commitSha:q}}finally{await B.dispose()}}async function fp(j,O,N,L,F,H){let{config:M}=await Lt(j),U=await ms(O,M.projectId,N),D=await ip(us(up(),"hlix-pull-"));try{let J=await O.repos.access(M.projectId,N,"read");await H.access(J,async(z)=>{H.git(D,["init"]),H.git(D,["fetch","--no-tags",J.cloneUrl,`refs/heads/${U.defaultBranch}`],z),H.git(D,["checkout","--detach",L])});let B=await Qi(D),G=[],q=[...B.manifest.files,...B.manifest.symlinks],Q=[...F.manifest.files,...F.manifest.symlinks].filter((z)=>!q.some((Z)=>Z.path===z.path)),te=new Set([...F.manifest.files,...F.manifest.symlinks].map((z)=>z.path));for(let z of q){let Z=z.path.split("/");for(let X=1;X<=Z.length;X++){let re=Z.slice(0,X).join("/"),ue=await pp(us(j,re)).catch((fe)=>{if(fe.code!=="ENOENT")throw fe;return null});if(ue&&!ue.isDirectory()&&!te.has(re))throw new e("conflict",`Incoming repository file would replace an excluded local file: ${re}`)}}for(let z of[...q,...Q])await Ki(j,z.path,G);let V=await Promise.all(B.manifest.files.map(async(z)=>({...z,bytes:await ap(us(D,z.path))})));for(let z of[...new Set(G)].sort((Z,X)=>Z.length-X.length))await zn(z,{force:!0});for(let z of Q)await zn(await fn(j,z.path),{force:!0});for(let z of V){let Z=await fn(j,z.path);await cp(Z,z.bytes,{mode:z.executable?493:420}),await lp(Z,z.executable?493:420)}for(let z of B.manifest.symlinks){let Z=await fn(j,z.path);await zn(Z,{force:!0}),await dp(z.target,Z)}return or(j,{schemaVersion:1,repoId:N,commitSha:L,files:Object.fromEntries(Nt(B.manifest)),snapshotOnly:!0,rootName:F.manifest.rootName}),{action:"pull",commitSha:L}}finally{await zn(D,{recursive:!0,force:!0})}}async function gs(j,O,N,L="sync",F=!1,H=Zi){let{config:M,state:U}=await Lt(j),D=await ms(O,M.projectId,U?.repoId),[J,B]=await Promise.all([Qi(j,N),O.repos.head(M.projectId,D.id)]),G=mp(J,U),q=U?.commitSha!==B.commitSha,Q=!U&&G&&!B.isEmpty?"conflict":L==="push"?q&&U?"conflict":G?"push":"none":L==="pull"?G?"conflict":q?"pull":"none":G&&q&&U?"conflict":G?"push":q?"pull":"none";if(F)return{action:Q,localChanged:G,cloudChanged:q,commitSha:B.commitSha};if(Q==="conflict")throw new e("conflict","This folder and HLIX Repos have both changed. Resolve the differences before syncing; no files were replaced.");if(Q==="push")return fs(j,O,J,B.commitSha,!1,H);if(Q==="pull")return fp(j,O,D.id,B.commitSha,J,H);return{action:"none",commitSha:B.commitSha}}function hs(j){return{name:j,summary:`${j} files with HLIX Repos`,usage:`Usage: hlix ${j} [--dry-run] [--json]`,supportsJson:!0,options:["dry-run"],async run(O){let{root:N}=await Lt(O.cwd),L=await gs(N,O.requireClient(),O.env,j,O.flags["dry-run"]===!0);return O.stdout(O.json?se(oe(`hlix ${j}`,L)):`HLIX Repos: ${L.action} (${L.commitSha})
|
|
352
|
+
`),L.action==="conflict"?1:0}}}var ea=hs("push"),ta=hs("pull"),na=hs("sync");var ra={name:"import",summary:"Import a local project into HLIX Repos",usage:"Usage: hlix import [folder] [--history preserve|sanitize] [--name name] [--stack stack] [--dry-run] [--yes] [--json]",supportsJson:!0,options:["history","name","stack","dry-run","yes","env-file","include"],args:{min:0,max:1},async run(j){let O=await yp(hp(j.cwd,j.args[0]??".")),N=r({env:j.env,flags:j.flags,cwd:O});if(N.conflict)throw new e("conflict",N.conflict);if(!N.workspaceId||!N.credential)throw new e("workspace_required","Run hlix auth login to select a workspace.");if(xt(O)?.projectId)throw new e("conflict","This folder is already bound to a project. Use hlix push or sync.");let F=j.flags.history??"preserve";if(F!=="preserve"&&F!=="sanitize")throw new e("invalid_usage","--history accepts preserve or sanitize.");let H=await Je(O,{environment:j.env,historyMode:F,envFile:typeof j.flags["env-file"]==="string"?j.flags["env-file"]:void 0,maxFiles:50000,maxFileBytes:33554432,maxTotalBytes:1073741824,include:typeof j.flags.include==="string"?j.flags.include:void 0});if(H.blocking.length)throw new e("scan_blocked",H.blocking.join(`
|
|
353
|
+
`));if(H.manifest.git.detected&&(H.manifest.historicalSecretFindings.length||!H.manifest.git.historyScanComplete))throw new e("scan_blocked","History contains potential secrets or was not completely scanned. Review it or use --history sanitize.");let M={files:H.manifest.totals.files,bytes:H.manifest.totals.bytes,protectedFiles:H.protectedFiles.length,history:F};if(j.flags["dry-run"]===!0)return j.stdout(se(oe("hlix import",M))),0;if(j.flags.yes!==!0&&!await j.confirm?.(`Import ${M.files} files into HLIX Repos and encrypt ${M.protectedFiles} protected files?`))throw new e("invalid_usage","Import requires approval. Review --dry-run, then use --yes.");let U=j.requireClient(O),D=await U.projects.create({name:typeof j.flags.name==="string"?j.flags.name:gp(O),stack:typeof j.flags.stack==="string"?j.flags.stack:H.manifest.stack,repos:[]});xn(O,{schemaVersion:1,projectId:D.id,workspaceId:N.workspaceId,apiUrl:N.baseUrl});for(let B=0;B<H.protectedFiles.length;B+=64)await U.secrets.importFiles(D.id,H.protectedFiles.slice(B,B+64).map((G)=>({path:G.path,contentBase64:G.contentBase64})));let J=await fs(O,U,H,void 0,F==="preserve");return j.stdout(j.json?se(oe("hlix import",{...M,projectId:D.id,commitSha:J.commitSha})):`Imported into HLIX Repos: ${D.name} (${J.commitSha})
|
|
354
|
+
`),0}};import{spawnSync as wp}from"node:child_process";import{existsSync as vp,mkdirSync as bp,writeFileSync as kp}from"node:fs";import{dirname as Sp}from"node:path";function jp(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(`
|
|
355
|
+
`):["# 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(`
|
|
356
|
+
`)}function Ep(j){return j.VISUAL?.trim()||j.EDITOR?.trim()||"vi"}var ys={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 (${h.join(", then ")}).`].join(`
|
|
357
|
+
`),supportsJson:!0,options:["edit","global"],async run(j){let O=w({cwd:j.cwd,configDir:".hlix",env:j.env}),N=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 L=N?$r(j.env):Pr(j.cwd,".hlix")?.path??`${j.cwd}/AGENTS.md`;if(!vp(L))bp(Sp(L),{recursive:!0}),kp(L,jp(N?"global":"project"),"utf8"),j.stdout(`Created ${L}.
|
|
358
|
+
`);let F=Ep(j.env),H=wp(F,[L],{stdio:"inherit"});if(H.error)throw new e("invalid_usage",`Could not run ${F}: ${H.error.message}`);return H.status??0}if(j.json){let L=(F)=>F?{path:F.path,characters:F.content.length}:null;return j.stdout(se(oe(ys.name,{user:L(O.global),project:L(O.project)}))),0}return j.stdout(`${b(O,j.cwd)}
|
|
359
|
+
`),0}};var ws={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(`
|
|
360
|
+
`),supportsJson:!0,async run(j){let O=v(j.cwd,a(j.env),{env:j.env});if(j.json)return j.stdout(se(oe(ws.name,{instructions:O.instructions.map((N)=>({path:N.path,source:N.source,scope:N.scope,characters:N.content.length,...N.note?{note:N.note}:{}})),skills:O.skills,commands:[...O.commands.map((N)=>({path:N.path,source:N.source,scope:N.scope})),...O.generatedCommands.map((N)=>({path:N.path,source:N.source,scope:N.scope,command:N.name}))],mcpServers:O.mcpServers.map((N)=>({path:N.path,source:N.source,scope:N.scope,name:N.name,transport:"command"in N.config?"stdio":"http"})),subagents:O.subagents.map((N)=>({path:N.path,source:N.source,scope:N.scope,name:N.name,description:N.description,...N.model?{model:N.model}:{}})),skipped:O.skipped}))),0;return j.stdout(Uo(O,j.cwd)),0}};var oa=(j)=>j instanceof Error?j.message:String(j),sa=(j)=>j.split(/\s*\n\s*/).join(" ").trim();async function S(j,O,N,L,F){try{let H=await Je(O,{historyMode:N,environment:j.env,rootName:L}),M=i(O)?.files,U=Nt(H.manifest);return{changedFiles:M?[...new Set([...Object.keys(M),...U.keys()])].filter((J)=>M[J]!==U.get(J)).length:null,files:H.manifest.totals.files,manifestSha256:H.manifestSha256,changed:F?H.manifestSha256!==F:null,blocking:H.blocking,error:null}}catch(H){return{changedFiles:null,files:null,manifestSha256:null,changed:null,blocking:[],error:oa(H)}}}var vs={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(`
|
|
361
|
+
`),supportsJson:!0,async run(j){let O=r({env:j.env,flags:j.flags,cwd:j.cwd}),N=O.binding,L=N?i(N.root):null,F=N?await S(j,N.root,L?.snapshotOnly?"sanitize":L?.historyMode??"preserve",L?.rootName,L?.manifestSha256):null,H=null;if(N?.config.projectId&&O.credential&&!O.conflict)try{let J=j.requireClient(),B=await J.projects.get(N.config.projectId),G=L?.repoId??B.repos.find((Q)=>Q.isPrimary)?.id??B.repos[0]?.id;if(!G)throw Error("Select a primary HLIX Repos");let q=await J.repos.head(N.config.projectId,G);H={commitSha:q.commitSha,changed:L?q.commitSha!==L.commitSha:null,error:null,errorMessage:null}}catch(J){H={commitSha:"",changed:null,error:br(J).code,errorMessage:J instanceof at?"no HLIX Repos commit yet — `hlix push` publishes this folder":oa(J)}}let M=Tr(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:N?{root:N.root,projectId:N.config.projectId??null,workspaceId:N.config.workspaceId,apiUrl:N.config.apiUrl}:null,repository:L?{repoId:L.repoId,commitSha:L.commitSha}:null,local:F,cloud:H,install:{channel:M.running?.channel??null,path:M.running?.path??null,copies:M.copies.map(({path:J,channel:B})=>({path:J,channel:B})),duplicate:M.duplicate}};if(j.json)return j.stdout(se(oe(vs.name,U))),0;let D=[["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",N?N.config.projectId??`initialized at ${N.root}, not imported yet`:"none — run `hlix import .` to bind this folder"]];if(L)D.push(["HLIX Repos",L.commitSha]);if(F){if(D.push(["local",F.error?`could not scan: ${F.error}`:F.changed===null?`${F.files} files, no synced base commit`:F.changed?`${F.files} files, modified since the last sync`:`${F.files} files, matches the last sync`]),F.blocking.length>0)D.push(["blocking",F.blocking.join("; ")])}if(H)D.push(["cloud",H.error==="not_found"?sa(H.errorMessage??H.error):H.error?`not checked — ${sa(H.errorMessage??H.error)}`:H.changed?`commit ${H.commitSha} available — run \`hlix pull\``:`commit ${H.commitSha}, up to date`]);if(O.conflict)D.push(["conflict",O.conflict]);if(M.running)D.push(["installed",Tn(M.running)]);if(M.duplicate)D.push(["duplicate",M.duplicate]);return j.stdout(`${Se(D)}
|
|
362
|
+
`),0}};import{spawnSync as ia}from"node:child_process";var bs={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(`
|
|
363
|
+
`),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 N=await j.requireClient().projects.terminal(O);if(j.json)return j.stdout(se(oe(bs.name,N))),N.available?0:1;if(!N.available){let M=N.environmentState?` (environment: ${N.environmentState})`:"";throw new e("not_found",`${N.reason??"Terminal unavailable"}${M}`)}let L=j.flags.print===!0,F=j.flags.web===!0;if(L||F&&!N.webTerminalUrl||!F&&!N.sshCommand)return j.stdout(`${Se([["ssh",N.sshCommand??"not available"],["browser",N.webTerminalUrl??"not available"]])}
|
|
364
|
+
`),0;if(F){if(ia(process.platform==="darwin"?"open":"xdg-open",[N.webTerminalUrl],{stdio:"ignore"}).status!==0)j.stdout(`${N.webTerminalUrl}
|
|
365
|
+
`);return 0}return ia("sh",["-c",N.sshCommand],{stdio:"inherit"}).status??1}};import{rmSync as aa}from"node:fs";import{dirname as xp}from"node:path";var ks={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(`
|
|
366
|
+
`),supportsJson:!0,options:["yes"],async run(j){let O=Ir(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: ${Rr(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 N=Cr(j.env);aa(O.path,{force:!0}),aa(N,{recursive:!0,force:!0});let L=xp(Ue(j.env));if(j.json)j.stdout(se(oe(ks.name,{removed:[O.path,N],kept:L})));else j.stdout(`Removed ${O.path}
|
|
367
|
+
Your login in ${L} is kept.
|
|
368
|
+
`);return 0}};function k(j){return[...j.pulled?[`HLIX Repos: pulled ${j.pulled}`]:[],...j.pushed?[`HLIX Repos: pushed ${j.pushed}`]:[]]}async function E(j,O,N){let L=!1;while(!N.signal?.aborted){try{let F=await gs(j,O.client,O.env);if(N.onReport({conflicts:[],...F.action==="push"?{pushed:F.commitSha}:F.action==="pull"?{pulled:F.commitSha}:{}}),!L)L=!0,N.onCaughtUp?.()}catch(F){N.onError(F)}await Ze(15000,N.signal)}}var ca={name:"mirror",summary:"Follow HLIX Repos using Git",usage:"Usage: hlix mirror [--json]",supportsJson:!0,options:[],agentTool:!1,async run(j){let{root:O}=await Lt(j.cwd);return await E(O,{client:j.requireClient(),env:j.env},{signal:j.signal,onReport:(N)=>{if(j.json)j.stdout(se(oe("hlix mirror",N)));else for(let L of k(N))j.stdout(`${L}
|
|
369
|
+
`)},onError:(N)=>j.stderr(`${N instanceof Error?N.message:String(N)}
|
|
370
|
+
`)}),0}};import{lstat as js,readFile as Pp,realpath as $p}from"node:fs/promises";import{basename as Ss,dirname as _p,extname as Cp,join as Kn,parse as la,resolve as Vn}from"node:path";function Ft(j,O){let N=j.flags[O];return typeof N==="string"&&N.trim()?N.trim():void 0}function Es(j){let O=Ft(j,"project");if(O)return{root:j.cwd,projectId:O};return Ip(j.cwd)}function Ip(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 xs(j,O){let N=await js(j);if(N.isSymbolicLink()||!N.isFile())throw Error(`Refusing to import a non-regular file: ${j}`);if(N.size>O)throw Error(`Import file exceeds ${O} bytes: ${j}`);return{path:await $p(j),content:await Pp(j,"utf8")}}function Ps(j,O,N,L){if(j.json)j.stdout(se(oe(O,N)));else j.stdout(`${L}
|
|
371
|
+
`)}function Rp(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 Tp=[Kn(".claude","skills"),Kn(".agents","skills"),Kn(".hlix","skills")];async function Ap(j,O){let N=[Vn(j,O),...Tp.map((L)=>Vn(j,L,O))];for(let L of N)if(await js(L).then(()=>!0,()=>!1))return L;throw new e("not_found",`No skill at ${O}. Pass the SKILL.md or its folder, for example .claude/skills/${O}.`)}var $s={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=Es(j),N=await Ap(j.cwd,j.args[0]),L=await js(N);if(L.isSymbolicLink())throw Error(`Refusing to import a symlink: ${N}`);let F=L.isDirectory()?Kn(N,"SKILL.md"):N,H=await xs(F,200000),M=L.isDirectory()?Ss(N):Ss(F)==="SKILL.md"?Ss(_p(F)):la(F).name,U=Ft(j,"name")??M;if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(U))throw Error("Skill name must be a lowercase kebab-case slug.");let D=await j.requireClient().resources.importSkill(O.projectId,{slug:U,content:H.content});return Ps(j,$s.name,D.skill,`Imported skill ${U}`),0}},_s={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=Es(j),N=Vn(j.cwd,j.args[0]);if(![".md",".mdx"].includes(Cp(N).toLowerCase()))throw Error("Agent imports must be Markdown files.");let L=await xs(N,20000),F=Ft(j,"runtime")??g;if(!o.includes(F)){let D=new Intl.ListFormat("en",{type:"disjunction"}).format(o);throw Error(`--runtime must be ${D}.`)}let H=Ft(j,"duty")??"executor";if(H!=="executor"&&H!=="intake")throw Error("--duty must be executor or intake.");let M=Ft(j,"name")??Rp(L.content)??la(N).name.replace(/[-_]+/g," "),U=await j.requireClient().resources.importAgent(O.projectId,{name:M,instructions:L.content,runtimeKind:F,duty:H});return Ps(j,_s.name,U.agent,U.agent.duty==="intake"?`Imported agent ${U.agent.name} as this project's intake agent`:`Imported agent ${U.agent.name}`),0}},Cs={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=Es(j),N=await xs(Vn(j.cwd,j.args[0]),200000),L;try{L=JSON.parse(N.content)}catch{throw Error("MCP config is not valid JSON.")}let F=Object.entries(L.mcpServers??{});if(F.length===0)throw Error("MCP config contains no servers.");let H=Ft(j,"server");if(!H&&F.length>1)throw Error("MCP config contains multiple servers; select one with --server <name>.");let M=H?F.find(([V])=>V===H):F[0];if(!M)throw Error(`MCP server not found: ${H}`);let[U,D]=M,J=D.type==="http"||D.type==="sse"?D.type:typeof D.command==="string"?"stdio":typeof D.url==="string"?"http":null;if(!J)throw Error(`MCP server ${U} has no supported transport.`);if(J==="stdio"&&j.flags["allow-stdio"]!==!0)throw Error("Stdio MCP servers execute a local command in the cloud; repeat with --allow-stdio.");let B=D.env&&typeof D.env==="object"&&!Array.isArray(D.env)?D.env:{},G=D.headers&&typeof D.headers==="object"&&!Array.isArray(D.headers)?D.headers:{};if(Object.values(G).some((V)=>typeof V!=="string"))throw Error(`MCP server ${U} headers must be strings.`);for(let[V,z]of Object.entries(B)){if(typeof z!=="string")continue;let Z=/^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(z)?.[1];if(Z&&Z!==V)throw new e("invalid_usage",`MCP server ${U}: env ${V} references \${${Z}}, but a placeholder must be the variable's own name — write "${V}": "\${${V}}" and store the secret as ${V}.`)}let q=Object.values(G).flatMap((V)=>[...V.matchAll(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g)].map((z)=>z[1]));if(Object.keys(G).length>0&&q.length===0)throw Error("MCP remote headers must use ${KEY} placeholders; literal credentials are refused.");let Q=/^(?:(?:Bearer|Basic|Token) )?\$\{[A-Za-z_][A-Za-z0-9_]*\}$/i;if(Object.values(G).some((V)=>!Q.test(V)))throw Error("MCP remote headers must be ${KEY} or an approved auth scheme followed by ${KEY}.");let te=await j.requireClient().resources.importMcp(O.projectId,{name:U,transport:J,...typeof D.command==="string"?{command:D.command}:{},...Array.isArray(D.args)&&D.args.every((V)=>typeof V==="string")?{args:D.args}:{},...typeof D.url==="string"?{url:D.url}:{},...Object.keys(G).length>0?{headers:G}:{},envKeys:[...new Set([...Object.keys(B),...q])].sort()});return Ps(j,Cs.name,te.mcpServer,`Imported MCP server ${U}`),0}};import{spawnSync as Op}from"node:child_process";import{chmod as Np,realpath as Lp,writeFile as Fp}from"node:fs/promises";import{basename as Hp,dirname as Mp,relative as Up,resolve as pa,sep as Dp}from"node:path";var da=64;function hn(j){let O=t(j.cwd),L=(typeof j.flags.project==="string"?j.flags.project:void 0)??O?.config.projectId;if(!L)throw new e("not_initialized","This folder is not bound to a Hlix project. Run `hlix import .`, or pass --project <id>.");return{projectId:L,root:O?.root??j.cwd}}var gn=(j,O)=>typeof j[O]==="string"?j[O]:void 0,Is={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(`
|
|
372
|
+
`),supportsJson:!0,options:["project"],async run(j){let{projectId:O}=hn(j),N=await j.requireClient().secrets.listEntries(O);if(j.json)return j.stdout(se(oe(Is.name,N))),0;if(N.entries.length===0)j.stdout(`No secrets stored for this project.
|
|
373
|
+
`);else j.stdout(`${Be(["key","source","format","value","updated"],N.entries.map((L)=>[L.key,L.source,L.format||"-",L.maskedValue,L.updatedAt?.slice(0,10)??"-"]))}
|
|
374
|
+
`);for(let L of N.warnings)j.stderr(`warning: ${L}
|
|
375
|
+
`);return 0}},Rs={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(`
|
|
376
|
+
`),supportsJson:!0,options:["from-stdin","source","project"],args:{min:1,max:2},async run(j){let{projectId:O}=hn(j),N=j.args[0],L=j.flags["from-stdin"]===!0;if(L&&j.args.length>1)throw new e("invalid_usage","Pass the value as an argument or with --from-stdin, not both.");if(!L&&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 F;if(L){if(!j.readStdin)throw new e("invalid_usage","--from-stdin is not available in this context.");F=(await j.readStdin()).replace(/\r?\n$/,"")}else F=j.args[1];let H=gn(j.flags,"source"),M=await j.requireClient().secrets.upsertEntries(O,{entries:[{key:N,value:F,...H?{source:H}:{}}]});if(j.json)return j.stdout(se(oe(Rs.name,M))),M.written>0?0:1;if(M.written===0)throw new e("bad_request",`The store refused ${N}: --source must be a project-relative file path.`);return j.stdout(`${Se([["key",N],["source",H??".env"]])}
|
|
377
|
+
`),0}},Ts={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(`
|
|
378
|
+
`),supportsJson:!0,options:["source","project"],args:{min:1,max:1},async run(j){let{projectId:O}=hn(j),N=j.args[0],L=gn(j.flags,"source"),F=await j.requireClient().secrets.deleteEntry(O,N,L);if(j.json)return j.stdout(se(oe(Ts.name,F))),F.removed>0?0:1;if(F.removed===0)return j.stderr(`No stored secret named ${N}${L?` in ${L}`:""}.
|
|
379
|
+
`),1;return j.stdout(`Removed ${F.removed} entr${F.removed===1?"y":"ies"} for ${N}.
|
|
380
|
+
`),0}},Xn={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(`
|
|
381
|
+
`),supportsJson:!0,options:["project"],args:{min:0,max:64},async run(j){let{projectId:O,root:N}=hn(j),L=await Je(N,{historyMode:"preserve",environment:j.env}),F=L.blocking.filter((G)=>!G.startsWith(as));if(F.length>0)throw new e("scan_blocked",`Project scan blocked the import:
|
|
382
|
+
- ${F.join(`
|
|
383
|
+
- `)}`);let H=L.protectedFiles.filter((G)=>G.kind==="dotenv"||G.kind==="credential"),M=await Lp(j.cwd),U=j.args.map((G)=>Up(L.root,pa(M,G)).split(Dp).join("/")),D=U.filter((G)=>!H.some((q)=>q.path===G));if(D.length>0)throw new e("invalid_usage",`Not a secret file in this project: ${D.join(", ")}`);let J=U.length>0?H.filter((G)=>U.includes(G.path)):H;if(J.length===0)return j.stdout(j.json?se(oe(Xn.name,{imported:[],skipped:[],warnings:[],written:0,rejected:[]})):`No secret files found in this project.
|
|
384
|
+
`),0;if(J.length>da)throw new e("invalid_usage",`${J.length} secret files exceeds the ${da} the store accepts in one request. Name the files to import, a batch at a time.`);let B=await j.requireClient().secrets.importFiles(O,J.map((G)=>({path:G.path,contentBase64:G.contentBase64})));if(j.json)return j.stdout(se(oe(Xn.name,B))),0;if(B.imported.length>0)j.stdout(`${Be(["source","format","stored"],B.imported.map((G)=>[G.path,G.format||"-",G.kind==="file"?"as file":`${G.entries} entr${G.entries===1?"y":"ies"}`]))}
|
|
385
|
+
`);if(j.stdout(`${B.written} value${B.written===1?"":"s"} stored.
|
|
386
|
+
`),B.imported.some((G)=>G.kind!=="file"))j.stdout(`Each imported file replaced what the store held under its path; keys the file no longer has are gone.
|
|
387
|
+
`);for(let G of B.skipped)j.stderr(`skipped ${G.path}: ${G.reason}
|
|
388
|
+
`);for(let G of B.warnings)j.stderr(`warning: ${G}
|
|
389
|
+
`);for(let G of B.rejected)j.stderr(`rejected ${G}: the store refused its source path
|
|
390
|
+
`);return 0}};function Jp(j){return Op("git",["-C",Mp(j),"ls-files","--error-unmatch","--",Hp(j)],{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).status===0}var As={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(`
|
|
391
|
+
`),supportsJson:!0,options:["source","format","out","project"],async run(j){let{projectId:O}=hn(j),N=gn(j.flags,"source"),L=gn(j.flags,"format"),F=gn(j.flags,"out"),H=F===void 0?void 0:pa(j.cwd,F);if(H!==void 0&&Jp(H))throw new e("invalid_usage",`Refusing to overwrite a git-tracked file with secret values: ${H}`);let M=await j.requireClient().secrets.exportEntries(O,{...N?{source:N}:{},...L?{format:L}:{}});if(H!==void 0)await Fp(H,M,{mode:384}),await Np(H,384);if(j.json)return j.stdout(se(oe(As.name,{source:N??null,format:L??null,out:H??null,bytes:Buffer.byteLength(M),...H===void 0?{content:M}:{}}))),0;if(H===void 0)j.stdout(M);else j.stdout(`${Se([["wrote",H],["mode","0600"],["bytes",String(Buffer.byteLength(M))]])}
|
|
392
|
+
`);return 0}};function Ns(j){let O=j.flags.project;if(typeof O==="string"&&O)return O;return t(j.cwd)?.config.projectId??void 0}function Os(j,O){let N=j[O];if(typeof N!=="string"||N.trim()==="")throw new e("missing_argument",`--${O} is required.`);return N}var Ls={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(`
|
|
393
|
+
`),supportsJson:!0,options:["title","description"],args:{min:1,max:1},async run(j){let O=j.args[0],N=Os(j.flags,"title"),L=Os(j.flags,"description"),F=await j.requireClient().cycles.propose({projectId:O,title:N,description:L});if(j.json)return j.stdout(se(oe(Ls.name,F))),0;return j.stdout(`${Se([["project",O],["title",N],["status",F.adopted?"adopted — the project is planning it now":"recorded — it will be planned on the next pass"]])}
|
|
394
|
+
`),0}},Fs={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(`
|
|
395
|
+
`),supportsJson:!0,options:["title","description"],args:{min:1,max:1},async run(j){let O=j.args[0],N=Os(j.flags,"description"),L=typeof j.flags.title==="string"?j.flags.title:void 0,F=await j.requireClient().tasks.create({projectId:O,description:N,...L?{title:L}:{}});if(j.json)return j.stdout(se(oe(Fs.name,F))),0;return j.stdout(`${Se([["task",F.id],["project",O],["status",F.status??"queued"],["note","not started — dispatch with `hlix cycles create`"]])}
|
|
396
|
+
`),0}},Hs={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(`
|
|
397
|
+
`),supportsJson:!0,options:["project"],args:{min:0,max:1},async run(j){let O=j.args[0]??Ns(j),N=j.requireClient(),L=O?await N.modelConfig.resolvedProjectHarness(O):await N.modelConfig.resolvedHarness();if(j.json)return j.stdout(se(oe(Hs.name,L))),0;return j.stdout(`${Se([["scope",O?`project ${O}`:"workspace"],["harness",L.harness],["source",L.source]])}
|
|
398
|
+
`),0}},Ms={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(`
|
|
399
|
+
`),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 N=j.flags.org===!0,L=j.args[1]??(N?void 0:Ns(j));if(L&&N)throw new e("invalid_usage","Name a project or pass --org, not both: they are different scopes.");if(!L&&!N)throw new e("invalid_usage","Name the project to set, or pass --org for the whole workspace.");let F=j.requireClient(),H=L?await F.modelConfig.setProjectHarness(L,O):await F.modelConfig.setHarness(O);if(j.json)return j.stdout(se(oe(Ms.name,H))),0;return j.stdout(`${Se([["scope",L?`project ${L}`:"workspace"],["harness",O]])}
|
|
400
|
+
`),0}},Us={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(`
|
|
401
|
+
`),supportsJson:!0,options:["org"],args:{min:0,max:1},async run(j){let O=j.flags.org===!0,N=j.args[0]??(O?void 0:Ns(j));if(N&&O)throw new e("invalid_usage","Name a project or pass --org, not both: they are different scopes.");if(!N&&!O)throw new e("invalid_usage","Name the project to clear, or pass --org for the whole workspace.");let L=j.requireClient(),F=N?await L.modelConfig.clearProjectHarness(N):await L.modelConfig.clearHarness();if(j.json)return j.stdout(se(oe(Us.name,F))),0;return j.stdout(`${Se([["scope",N?`project ${N}`:"workspace"],["harness","cleared — the scope below decides now"]])}
|
|
402
|
+
`),0}};var p=[Ar,Or,Tt,vs,ks,bs,ws,ys,Nr,Lr,Fr,ls,ra,na,ta,ea,ca,$s,_s,Cs,Is,Rs,Ts,Xn,As,Hr,Mr,Ur,Dr,Jr,Gr,Wr,qr,zr,Fs,Ls,Hs,Ms,Us];
|
|
403
|
+
export{e,s,R,i,u,t,r,n,c,m,l,o,g,f,x,y,d,a,_,h,w,A,b,v,I,C,P,T,S,k,E,p};
|