infra-kit 0.3.11 → 0.3.13

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.
@@ -1,4 +1,4 @@
1
- import M from"node:process";import j from"pino";import pe from"pino-pretty";var O="/tmp/mcp-infra-kit.log",F=["token","*.token","serviceToken","*.serviceToken","DOPPLER_TOKEN","*.DOPPLER_TOKEN","INFRA_KIT_ENV_TOKEN","*.INFRA_KIT_ENV_TOKEN"],It=()=>{let e=M.argv.includes("--debug")?"debug":"info",t=j({level:e,redact:F},j.destination({dest:O}));return t.info(`Logger initialized with level: ${e}. Logging to: ${O}`),t},le=()=>{let e=M.argv.includes("--debug")?"debug":"info",t=["time","pid","hostname"];return e==="debug"&&t.push("level"),j({level:e,redact:F},pe({destination:2,ignore:t.join(","),colorize:!0}))},Dt=le();import*as p from"node:fs";import*as a from"node:path";function ue(e){let t=e;for(let r=0;r<10;r++){let n=a.join(t,"pnpm-workspace.yaml");if(p.existsSync(n))return t;t=a.dirname(t)}throw new Error("Could not find monorepo root (pnpm-workspace.yaml)")}function G(e,t){let r=a.join(e,"package.json");if(!p.existsSync(r))return t;try{let n=JSON.parse(p.readFileSync(r,"utf-8"));return typeof n.name=="string"?n.name:t}catch{return t}}function $t(e){let t=a.join(e,"apps"),r=[];if(!p.existsSync(t))throw new Error(`Apps directory not found: ${t}`);let n=p.readdirSync(t,{withFileTypes:!0}).filter(o=>o.isDirectory()).map(o=>o.name);for(let o of n){let i=a.join(t,o,"api"),c=a.join(i,"serverless.yml");p.existsSync(c)&&r.push({name:o,packageName:G(i,o),path:i})}return r}var B=["vite.config.ts","vite.config.mts","vite.config.cts","vite.config.js","vite.config.mjs","vite.config.cjs"],fe=["@slip-stream-kit/vite","@slip-stream-kit/config/vite","infra-kit/vite"];function de(e){for(let t of B){let r=a.join(e,t);if(p.existsSync(r))try{let n=p.readFileSync(r,"utf-8");return fe.some(o=>n.includes(o))}catch{return!1}}return!1}function Tt(e){for(let t of B){let r=a.join(e,t);if(p.existsSync(r))try{return p.readFileSync(r,"utf-8").includes("infraKit(")}catch{return!1}}return!1}function ge(e){let t=a.join(e,"package.json");if(!p.existsSync(t))return!1;try{let r=JSON.parse(p.readFileSync(t,"utf-8"));return typeof r.scripts?.dev=="string"&&r.scripts.dev.length>0}catch{return!1}}function Nt(e){let t=a.join(e,"apps"),r=[];if(!p.existsSync(t))return r;let n=p.readdirSync(t,{withFileTypes:!0}).filter(o=>o.isDirectory()).map(o=>o.name);for(let o of n){let i=a.join(t,o,"ui");p.existsSync(i)&&ge(i)&&r.push({name:o,packageName:G(i,o),path:i,managedPort:de(i)})}return r}function _t(e){let t=e?.filter(Boolean)??[];return t.length>0?t:null}function Lt(e){let t=ue(e),r=a.relative(a.join(t,"apps"),e),n=r.split(a.sep)[0];if(r===""||r.startsWith("..")||a.isAbsolute(r)||!n)throw new Error(`--self: not inside an apps/<app> directory (cwd: ${e}). Run from an app folder or use --app=<name>.`);return n}var me=new Set(["api","ui"]),W=e=>{let t=a.join(e,"dist");return p.existsSync(t)&&p.statSync(t).isDirectory()?t:void 0},I=e=>p.existsSync(e)?p.readdirSync(e,{withFileTypes:!0}).filter(t=>t.isDirectory()).map(t=>t.name):[];function Kt(e){let t=[];for(let n of I(a.join(e,"packages"))){let o=W(a.join(e,"packages",n));o!==void 0&&t.push(o)}let r=a.join(e,"apps");for(let n of I(r))for(let o of I(a.join(r,n))){if(me.has(o))continue;let i=a.join(r,n,o);if(!p.existsSync(a.join(i,"package.json")))continue;let c=W(i);c!==void 0&&t.push(c)}return t}function Ot(e){return e.map(t=>a.join(t.path,"dist")).filter(t=>p.existsSync(t))}function Mt(e,t,r){let n=a.normalize(e),o=r.find(c=>n.startsWith(a.normalize(c)));return o?{kind:"package",packageDir:o}:{kind:"app",app:t.find(c=>n.startsWith(a.normalize(c)))}}var he={"*/api":{},"*/ui":{}},V=e=>{let t=e.split("/"),[r,n]=t;return t.length!==2||!r?`devServersPresets: invalid target "${e}" (expected "<app>/api" or "<app>/ui")`:n!=="api"&&n!=="ui"?`devServersPresets: invalid target part "${n}" in "${e}" (expected "api" or "ui")`:null},ve=e=>{let t=V(e);if(t)throw new Error(t);let[r,n]=e.split("/");return{appGlob:r,part:n}},Wt=e=>{let t=[];for(let[r,n]of Object.entries(e))for(let o of Object.keys(n.apps??{})){let i=V(o);i&&t.push({preset:r,key:o,message:`preset "${r}": ${i}`})}return t},ye=(e,t)=>t==="api"?e.api:e.ui,ke=e=>[...new Set([...e.api,...e.ui])].sort(),z=(e,t)=>`${e}/${t}`,xe=e=>e?0:1,be=(e,t)=>t.watchDeps===void 0?e??{watchDeps:!0,rank:t.rank,explicitValue:!1}:!e||!e.explicitValue?{watchDeps:t.watchDeps,rank:t.rank,explicitValue:!0}:t.rank>e.rank?{watchDeps:t.watchDeps,rank:t.rank,explicitValue:!0}:e,we=(e,t,r)=>{let{app:n,part:o,watchDeps:i,isGlob:c}=r;if(!ye(t,o).includes(n)){c||e.unmatched.push(z(n,o));return}let l=z(n,o),u=be(e.targets.get(l),{watchDeps:i,rank:xe(c)});e.targets.set(l,{app:n,part:o,...u})},Pe=(e,t)=>{let r=Object.entries(e.apps??he),n={targets:new Map,proxy:{},unmatched:[]};for(let[c,l]of r){let{appGlob:u,part:g}=ve(c),m=u==="*",P=m?ke(t):[u];for(let C of P)we(n,t,{app:C,part:g,watchDeps:l.watchDeps,isGlob:m}),l.proxy&&(n.proxy[C]={...n.proxy[C]??{},...l.proxy})}let o=[...n.targets.values()].map(({app:c,part:l,watchDeps:u})=>({app:c,part:l,watchDeps:u})),i=[...new Set(o.filter(c=>c.part==="api").map(c=>c.app))];return{targets:o,cmux:e.cmux??!1,proxy:n.proxy,localApps:i,unmatched:n.unmatched}},Gt=e=>{if(e.preset!=null)return e.preset;if(e.running.length===0)return"nothing";let t=new Set(e.running);return e.discovered.every(n=>t.has(n))?"*":[...t].sort().join(" + ")},Re=(e,t)=>Object.keys(e).find(r=>e[r]===t),Ee=({preset:e,app:t,route:r,launchedPkgs:n,ctx:o})=>{let i=o.routePkg(t,r);if(i===void 0)return{preset:e,app:t,route:r,kind:"unknown-route",message:`preset "${e}": proxy override "${r}" on "${t}" names a route not declared in ${t}'s infra-kit.config.ts dev.proxy.routes`};if(n.has(i))return null;let c=Re(o.apiPkgByApp,i),l=c?`add "${c}/api" to the preset`:`launch the api whose package is "${i}"`;return{preset:e,app:t,route:r,pkg:i,kind:"backend-not-launched",message:`preset "${e}": proxy override "${r}" \u2192 "local" requires backend "${i}" to run locally, but the preset does not launch it \u2014 ${l}, or set "${r}" to "cloud"`}},Bt=(e,t)=>{let r=[];for(let[n,o]of Object.entries(e)){let i=Pe(o,t.discovered),c=new Set(i.localApps.map(l=>t.apiPkgByApp[l]).filter(l=>l!==void 0));for(let[l,u]of Object.entries(i.proxy))for(let[g,m]of Object.entries(u)){if(m!=="local")continue;let P=Ee({preset:n,app:l,route:g,launchedPkgs:c,ctx:t});P&&r.push(P)}}return r};import L from"node:fs/promises";import ne from"node:os";import b from"node:path";import Ve from"node:process";import{z as s}from"zod";import y from"node:path";import Q from"node:process";import{$ as f}from"zx";var E=e=>{if(e===null||typeof e!="object")return;let t=e.stderr;return typeof t=="string"&&t.length>0?t:void 0},Se=(e,t)=>{let r=t.stderrExcerpt??E(e),n=[`failed to ${t.operation}`];return r&&n.push(`stderr: ${r.slice(0,200).trim()}`),t.remediation&&n.push(`try: ${t.remediation}`),n.join(" \u2014 ")},R=class extends Error{operation;remediation;constructor(t,r){super(Se(t,r),{cause:t}),this.name="OperationError",this.operation=r.operation,this.remediation=r.remediation}};var U={enabled:!1},k=()=>U.enabled;var Ce=/^v?(\d+)\.(\d+)\.(\d+)$/,je=/^(\d+)\.(\d+)\.(\d+)$/,Ie=/^[a-z0-9]+(?:-[a-z0-9]+)*$/,S="release/",D="release/v",X="refs/heads/",De="next";var H=new Set(["dev","main","next","hotfix","regular","release"]),h=class extends Error{constructor(t){super(t),this.name="InvalidReleaseNameError"}},v=class extends Error{constructor(t){super(t),this.name="InvalidReleaseRefError"}},J=e=>e.startsWith(X)?e.slice(X.length):e,Y=(e,t,r)=>({kind:"version",semver:{major:e,minor:t,patch:r},raw:`${e}.${t}.${r}`}),A=e=>{if(e.length===0)throw new h('Release name is empty. Provide a kebab-case name like "checkout-redesign".');if(e.length>50)throw new h(`Release name "${e}" is ${e.length} characters; the maximum is 50.`);if(!Ie.test(e))throw new h(`Release name "${e}" is not kebab-case. Use lowercase letters, digits, and single hyphens, e.g. "checkout-redesign".`);if(H.has(e))throw new h(`Release name "${e}" is reserved. Reserved names: ${[...H].join(", ")}.`)},$=e=>{let t=J(e.trim());if(!t.startsWith(S))return null;if(t.startsWith(D)){let n=t.slice(D.length),o=je.exec(n);if(o)return Y(Number(o[1]),Number(o[2]),Number(o[3]))}let r=t.slice(S.length);try{A(r)}catch{return null}return{kind:"name",name:r,raw:r}},Ae=e=>{let t=e.trim();if(J(t).startsWith(S)){let o=$(t);if(!o)throw new v(`"${e}" looks like a release branch but is not a valid release/v<semver> or release/<name> ref.`);return o}let n=Ce.exec(t);if(n)return Y(Number(n[1]),Number(n[2]),Number(n[3]));if(t.toLowerCase()===De)throw new v('The "next" token must be resolved to a concrete version (via computeNextVersion) before parsing a release ref.');try{A(t)}catch(o){let i=o instanceof Error?o.message:String(o);throw new v(`Cannot parse "${e}" as a release ref: ${i}`)}return{kind:"name",name:t,raw:t}},$e=e=>e.kind==="version"?`${D}${e.raw}`:`${S}${e.name}`,Te=(e,t)=>{let r=t==="hotfix"?"Hotfix":"Release";return e.kind==="version"?`${r} v${e.raw}`:`${r} ${e.name}`},Ne=e=>e.kind==="version"?`Release v${e.raw} (RC)`:`Release ${e.name} (RC)`,_e=e=>e.kind==="version"?`v${e.raw}`:e.name,Le=e=>e.raw,T=e=>e==null?!1:$(e)!==null,q=e=>{if(e===void 0)return null;let t=e instanceof Date?e.getTime():new Date(e).getTime();return Number.isNaN(t)?null:t},Ke=(e,t,r)=>{if(e.kind==="version"&&t.kind==="version")return e.semver.major!==t.semver.major?e.semver.major-t.semver.major:e.semver.minor!==t.semver.minor?e.semver.minor-t.semver.minor:e.semver.patch-t.semver.patch;if(e.kind==="version")return-1;if(t.kind==="version")return 1;let n=q(r?.a),o=q(r?.b);return n!==null&&o!==null&&n!==o?n-o:e.name<t.name?-1:e.name>t.name?1:0};var Z=async e=>{let t=await f({cwd:e})`git worktree list --porcelain`,r=[],n=null;for(let o of t.stdout.split(`
2
- `)){if(o.startsWith("worktree ")){n&&r.push(n),n={path:o.slice(9),branch:null,detached:!1,bare:!1,prunable:!1,locked:!1};continue}n&&(o.startsWith("branch ")?n.branch=o.slice(7).replace(/^refs\/heads\//,""):o==="detached"?n.detached=!0:o==="bare"?n.bare=!0:o==="locked"||o.startsWith("locked ")?n.locked=!0:(o==="prunable"||o.startsWith("prunable "))&&(n.prunable=!0))}return n&&r.push(n),r},Oe=async e=>{let t=await Z(Q.cwd()),r=n=>e==="release"?T(n):n.startsWith("feature/");return t.map(n=>n.branch).filter(n=>n!==null&&r(n))},Me=e=>{let t=E(e);return t&&/not a git repository/i.test(t)?"not a git repository":void 0},Fe=({hasStderr:e})=>{if(k())return"the infra-kit MCP server resolves its project from the working directory it was launched in; the operator must relaunch the server with its working directory set to an infra-kit project repo";let t="run infra-kit from inside an infra-kit project repo (or one of its git worktrees)";return e?`${t}; if you are already in one, the stderr in this message is the real cause`:t},x=async()=>{try{return(await f({quiet:!0})`git rev-parse --show-toplevel`).stdout.trim()}catch(e){let t=Me(e)??E(e);throw new R(e,{operation:`resolve the project root from ${Q.cwd()}`,stderrExcerpt:t,remediation:Fe({hasStderr:t!==void 0})})}},N=async e=>{let t=e??await x(),r=(await f({cwd:t,quiet:!0})`git rev-parse --git-common-dir`).stdout.trim(),n=y.resolve(t,r);return n.includes(`${y.sep}.git${y.sep}modules${y.sep}`)?t:y.dirname(n)},ee=async()=>(await f`git rev-parse --abbrev-ref HEAD`).stdout.trim(),We=async()=>(await f`git status --porcelain`).stdout.trim().length===0,Ge=async()=>{let e=await x(),[t,r]=await Promise.all([f({cwd:e})`git rev-parse --absolute-git-dir`,f({cwd:e})`git rev-parse --git-common-dir`]),n=t.stdout.trim(),o=y.resolve(e,r.stdout.trim());return n!==o};var Be=async e=>{(await f`git branch --list ${e}`).stdout.trim().length!==0&&await ee()!==e&&await f`git branch -D ${e}`},ze=async e=>{(await f`git ls-remote --heads origin ${e}`).stdout.trim().length!==0&&await f`git push origin --delete ${e}`};var te="infra-kit.json",oe=".infra-kit",Ue="infra-kit.json",Xe="projects",He=s.object({provider:s.literal("doppler"),config:s.object({name:s.string().min(1)})}),qe=s.discriminatedUnion("provider",[He]),Je=s.object({workspaceConfigPath:s.string().min(1)}),Ye=s.object({provider:s.literal("cursor"),config:Je}),Qe=s.object({}),Ze=s.object({provider:s.literal("zed"),config:Qe}),re=s.discriminatedUnion("provider",[Ye,Ze]),et=s.union([re,s.array(re).min(1)]),tt=s.object({provider:s.literal("jira"),config:s.object({baseUrl:s.string().url(),projectId:s.number().int().positive()})}),rt=s.discriminatedUnion("provider",[tt]),nt=["two-columns","three-pane"],ot=s.object({layout:s.enum(nt).optional()}),st=s.object({openInGithubDesktop:s.boolean().optional(),openInCmux:s.boolean().optional(),cmux:ot.optional()}),it=s.object({port:s.number().int().positive().optional(),prefixUrl:s.string().min(1).optional()}).strict(),at=s.record(s.string().min(1),it),ct=s.enum(["local","cloud"]),pt=s.object({watchDeps:s.boolean().optional(),proxy:s.record(s.string().min(1),ct).optional()}).strict(),lt=s.object({apps:s.record(s.string().min(1),pt).optional(),cmux:s.boolean().optional()}).strict(),ut=s.record(s.string().min(1),lt),ft=s.object({port:s.number().int().positive().optional()}).strict(),dt=s.object({trigger:s.enum(["shell-startup","cli-invocation"]),config:s.string().min(1)}).strict(),K=s.object({envManagement:qe,ide:et.optional(),taskManager:rt.optional(),worktrees:st.optional(),envAutoLoad:dt.optional(),dev:at.optional(),devServersPresets:ut.optional(),devProxy:ft.optional()}).strict(),gt=443,se=K.superRefine((e,t)=>{if(!Array.isArray(e.ide))return;let r=new Set;for(let n of e.ide){if(r.has(n.provider)){t.addIssue({code:"custom",message:"each IDE provider may appear at most once",path:["ide"]});return}r.add(n.provider)}}),ie=K.partial(),mt=e=>{let t=e.ide;return t?Array.isArray(t)?t:[t]:[]},ht="two-columns",vt=e=>e.worktrees?.cmux?.layout??ht,d=null,w=null,ae=()=>`${Ve.cwd()} ${ne.homedir()}`,ce=async()=>{let e=ae();if(w&&w.key===e)return w.value;let t=await x(),r=await N(t),n=b.basename(r),o=b.join(ne.homedir(),oe),i={main:b.join(t,te),userGlobal:b.join(o,Ue),userProject:b.join(o,Xe,n,te),projectName:n};return w={key:e,value:i},i},yt=async()=>{let e=ae(),t=await ce(),r;try{r=await L.stat(t.main)}catch{d=null;let g=t.main.replace(/\.json$/,".yml");throw await _(g)?new Error(`infra-kit.json not found at ${t.main}. A legacy infra-kit.yml exists \u2014 run \`infra-kit init\` to convert it.`):new Error(k()?`infra-kit.json not found at ${t.main} \u2014 the directory the infra-kit MCP server was launched in is not an infra-kit project. The operator must relaunch the server with its working directory set to an infra-kit project repo.`:`infra-kit.json not found at ${t.main} \u2014 this git repo is not an infra-kit project. Run \`infra-kit init\` here to create it, cd into an infra-kit project repo, or check out a branch that has infra-kit.json.`)}let[n,o]=await Promise.all([_(t.userGlobal),_(t.userProject)]),i={main:Number(r.mtimeMs),userGlobal:n?Number(n.mtimeMs):null,userProject:o?Number(o.mtimeMs):null};if(d&&d.key===e&&wt(d.mtimes,i))return d.value;let c=[{label:"infra-kit.json",path:t.main,required:!0},{label:"~/.infra-kit/infra-kit.json",path:t.userGlobal,required:!1},{label:`~/.infra-kit/projects/${t.projectName}/infra-kit.json`,path:t.userProject,required:!1}],l={};for(let g of c){let m=await Pt(g);m!==null&&(l={...l,...m})}let u=se.safeParse(l);if(!u.success)throw new Error(`Invalid merged infra-kit config: ${s.prettifyError(u.error)}`);return d={key:e,mtimes:i,value:u.data},u.data},kt=()=>{d=null},xt=()=>{d=null,w=null},_=async e=>{try{return await L.stat(e)}catch{return null}},bt=async e=>{try{return await L.readFile(e,"utf-8")}catch{return null}},wt=(e,t)=>{let r=Object.keys(e);return r.length!==Object.keys(t).length?!1:r.every(n=>e[n]===t[n])},Pt=async e=>{let t=await bt(e.path);if(t===null){if(e.required)throw new Error(`${e.label} not found at ${e.path}`);return null}let r;try{r=t.trim()===""?{}:JSON.parse(t)}catch(o){throw new Error(`Invalid JSON in ${e.label} at ${e.path}: ${o.message}`)}if(Rt(r)&&"envTokens"in r)throw new Error(Et(e));let n=ie.safeParse(r);if(!n.success)throw new Error(`Invalid ${e.label} at ${e.path}: ${s.prettifyError(n.error)}`);return n.data},Rt=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),Et=e=>[`Refusing to load ${e.label} \u2014 \`envTokens\` is not a config key.`,"A service token in a config file can be committed, backed up by your editor, or shared."," 1. REVOKE the token in Doppler now \u2014 treat it as compromised.",` 2. Remove the \`envTokens\` key from ${e.path}.`," 3. Re-add it privately: `infra-kit env-token-set <env>`"," (it is written to ~/.infra-kit/projects/<repo>/tokens.json, mode 0600, never to the repo)."].join(`
3
- `);export{E as a,R as b,U as c,k as d,h as e,A as f,$ as g,Ae as h,$e as i,Te as j,Ne as k,_e as l,Le as m,T as n,Ke as o,Z as p,Oe as q,x as r,N as s,We as t,Ge as u,Be as v,ze as w,O as x,It as y,Dt as z,ue as A,$t as B,Tt as C,Nt as D,_t as E,Lt as F,Kt as G,Ot as H,Mt as I,V as J,Wt as K,Pe as L,Gt as M,Bt as N,oe as O,gt as P,se as Q,ie as R,mt as S,vt as T,ce as U,yt as V,kt as W,xt as X};
4
- //# sourceMappingURL=chunk-M46KGMQ6.js.map
1
+ import M from"node:process";import j from"pino";import pe from"pino-pretty";var O="/tmp/mcp-infra-kit.log",F=["token","*.token","serviceToken","*.serviceToken","DOPPLER_TOKEN","*.DOPPLER_TOKEN","INFRA_KIT_ENV_TOKEN","*.INFRA_KIT_ENV_TOKEN"],At=()=>{let e=M.argv.includes("--debug")?"debug":"info",t=j({level:e,redact:F},j.destination({dest:O}));return t.info(`Logger initialized with level: ${e}. Logging to: ${O}`),t},le=()=>{let e=M.argv.includes("--debug")?"debug":"info",t=["time","pid","hostname"];return e==="debug"&&t.push("level"),j({level:e,redact:F},pe({destination:2,ignore:t.join(","),colorize:!0}))},$t=le();import*as p from"node:fs";import*as a from"node:path";function ue(e){let t=e;for(let r=0;r<10;r++){let n=a.join(t,"pnpm-workspace.yaml");if(p.existsSync(n))return t;t=a.dirname(t)}throw new Error("Could not find monorepo root (pnpm-workspace.yaml)")}function G(e,t){let r=a.join(e,"package.json");if(!p.existsSync(r))return t;try{let n=JSON.parse(p.readFileSync(r,"utf-8"));return typeof n.name=="string"?n.name:t}catch{return t}}function Nt(e){let t=a.join(e,"apps"),r=[];if(!p.existsSync(t))throw new Error(`Apps directory not found: ${t}`);let n=p.readdirSync(t,{withFileTypes:!0}).filter(o=>o.isDirectory()).map(o=>o.name);for(let o of n){let i=a.join(t,o,"api"),c=a.join(i,"serverless.yml");p.existsSync(c)&&r.push({name:o,packageName:G(i,o),path:i})}return r}var B=["vite.config.ts","vite.config.mts","vite.config.cts","vite.config.js","vite.config.mjs","vite.config.cjs"],fe=["@slip-stream-kit/vite","@slip-stream-kit/config/vite","infra-kit/vite"];function de(e){for(let t of B){let r=a.join(e,t);if(p.existsSync(r))try{let n=p.readFileSync(r,"utf-8");return fe.some(o=>n.includes(o))}catch{return!1}}return!1}function _t(e){for(let t of B){let r=a.join(e,t);if(p.existsSync(r))try{return p.readFileSync(r,"utf-8").includes("infraKit(")}catch{return!1}}return!1}function ge(e){let t=a.join(e,"package.json");if(!p.existsSync(t))return!1;try{let r=JSON.parse(p.readFileSync(t,"utf-8"));return typeof r.scripts?.dev=="string"&&r.scripts.dev.length>0}catch{return!1}}function Lt(e){let t=a.join(e,"apps"),r=[];if(!p.existsSync(t))return r;let n=p.readdirSync(t,{withFileTypes:!0}).filter(o=>o.isDirectory()).map(o=>o.name);for(let o of n){let i=a.join(t,o,"ui");p.existsSync(i)&&ge(i)&&r.push({name:o,packageName:G(i,o),path:i,managedPort:de(i)})}return r}function Kt(e){let t=e?.filter(Boolean)??[];return t.length>0?t:null}function Ot(e){let t=ue(e),r=a.relative(a.join(t,"apps"),e),n=r.split(a.sep)[0];if(r===""||r.startsWith("..")||a.isAbsolute(r)||!n)throw new Error(`--self: not inside an apps/<app> directory (cwd: ${e}). Run from an app folder or use --app=<name>.`);return n}var me=new Set(["api","ui"]),W=e=>{let t=a.join(e,"dist");return p.existsSync(t)&&p.statSync(t).isDirectory()?t:void 0},I=e=>p.existsSync(e)?p.readdirSync(e,{withFileTypes:!0}).filter(t=>t.isDirectory()).map(t=>t.name):[];function Mt(e){let t=[];for(let n of I(a.join(e,"packages"))){let o=W(a.join(e,"packages",n));o!==void 0&&t.push(o)}let r=a.join(e,"apps");for(let n of I(r))for(let o of I(a.join(r,n))){if(me.has(o))continue;let i=a.join(r,n,o);if(!p.existsSync(a.join(i,"package.json")))continue;let c=W(i);c!==void 0&&t.push(c)}return t}function Ft(e){return e.map(t=>a.join(t.path,"dist")).filter(t=>p.existsSync(t))}function Wt(e,t,r){let n=a.normalize(e),o=r.find(c=>n.startsWith(a.normalize(c)));return o?{kind:"package",packageDir:o}:{kind:"app",app:t.find(c=>n.startsWith(a.normalize(c)))}}var he={"*/api":{},"*/ui":{}},V=e=>{let t=e.split("/"),[r,n]=t;return t.length!==2||!r?`devServersPresets: invalid target "${e}" (expected "<app>/api" or "<app>/ui")`:n!=="api"&&n!=="ui"?`devServersPresets: invalid target part "${n}" in "${e}" (expected "api" or "ui")`:null},ve=e=>{let t=V(e);if(t)throw new Error(t);let[r,n]=e.split("/");return{appGlob:r,part:n}},Bt=e=>{let t=[];for(let[r,n]of Object.entries(e))for(let o of Object.keys(n.apps??{})){let i=V(o);i&&t.push({preset:r,key:o,message:`preset "${r}": ${i}`})}return t},ye=(e,t)=>t==="api"?e.api:e.ui,ke=e=>[...new Set([...e.api,...e.ui])].sort(),z=(e,t)=>`${e}/${t}`,xe=e=>e?0:1,we=(e,t)=>t.watchDeps===void 0?e??{watchDeps:!0,rank:t.rank,explicitValue:!1}:!e||!e.explicitValue?{watchDeps:t.watchDeps,rank:t.rank,explicitValue:!0}:t.rank>e.rank?{watchDeps:t.watchDeps,rank:t.rank,explicitValue:!0}:e,be=(e,t,r)=>{let{app:n,part:o,watchDeps:i,isGlob:c}=r;if(!ye(t,o).includes(n)){c||e.unmatched.push(z(n,o));return}let l=z(n,o),u=we(e.targets.get(l),{watchDeps:i,rank:xe(c)});e.targets.set(l,{app:n,part:o,...u})},Pe=(e,t)=>{let r=Object.entries(e.apps??he),n={targets:new Map,proxy:{},unmatched:[]};for(let[c,l]of r){let{appGlob:u,part:g}=ve(c),m=u==="*",P=m?ke(t):[u];for(let C of P)be(n,t,{app:C,part:g,watchDeps:l.watchDeps,isGlob:m}),l.proxy&&(n.proxy[C]={...n.proxy[C]??{},...l.proxy})}let o=[...n.targets.values()].map(({app:c,part:l,watchDeps:u})=>({app:c,part:l,watchDeps:u})),i=[...new Set(o.filter(c=>c.part==="api").map(c=>c.app))];return{targets:o,cmux:e.cmux??!1,proxy:n.proxy,localApps:i,unmatched:n.unmatched}},zt=e=>{if(e.preset!=null)return e.preset;if(e.running.length===0)return"nothing";let t=new Set(e.running);return e.discovered.every(n=>t.has(n))?"*":[...t].sort().join(" + ")},Re=(e,t)=>Object.keys(e).find(r=>e[r]===t),Ee=({preset:e,app:t,route:r,launchedPkgs:n,ctx:o})=>{let i=o.routePkg(t,r);if(i===void 0)return{preset:e,app:t,route:r,kind:"unknown-route",message:`preset "${e}": proxy override "${r}" on "${t}" names a route not declared in ${t}'s infra-kit.config.ts dev.proxy.routes`};if(n.has(i))return null;let c=Re(o.apiPkgByApp,i),l=c?`add "${c}/api" to the preset`:`launch the api whose package is "${i}"`;return{preset:e,app:t,route:r,pkg:i,kind:"backend-not-launched",message:`preset "${e}": proxy override "${r}" \u2192 "local" requires backend "${i}" to run locally, but the preset does not launch it \u2014 ${l}, or set "${r}" to "cloud"`}},Vt=(e,t)=>{let r=[];for(let[n,o]of Object.entries(e)){let i=Pe(o,t.discovered),c=new Set(i.localApps.map(l=>t.apiPkgByApp[l]).filter(l=>l!==void 0));for(let[l,u]of Object.entries(i.proxy))for(let[g,m]of Object.entries(u)){if(m!=="local")continue;let P=Ee({preset:n,app:l,route:g,launchedPkgs:c,ctx:t});P&&r.push(P)}}return r};import L from"node:fs/promises";import ne from"node:os";import w from"node:path";import Ue from"node:process";import{z as s}from"zod";import v from"node:path";import Q from"node:process";import{$ as f}from"zx";var E=e=>{if(e===null||typeof e!="object")return;let t=e.stderr;return typeof t=="string"&&t.length>0?t:void 0},Se=(e,t)=>{let r=t.stderrExcerpt??E(e),n=[`failed to ${t.operation}`];return r&&n.push(`stderr: ${r.slice(0,200).trim()}`),t.remediation&&n.push(`try: ${t.remediation}`),n.join(" \u2014 ")},R=class extends Error{operation;remediation;constructor(t,r){super(Se(t,r),{cause:t}),this.name="OperationError",this.operation=r.operation,this.remediation=r.remediation}};var U={enabled:!1},x=()=>U.enabled;var Ce=/^v?(\d+)\.(\d+)\.(\d+)$/,je=/^(\d+)\.(\d+)\.(\d+)$/,Ie=/^[a-z0-9]+(?:-[a-z0-9]+)*$/,S="release/",D="release/v",X="refs/heads/",De="next";var H=new Set(["dev","main","next","hotfix","regular","release"]),h=class extends Error{constructor(t){super(t),this.name="InvalidReleaseNameError"}},y=class extends Error{constructor(t){super(t),this.name="InvalidReleaseRefError"}},J=e=>e.startsWith(X)?e.slice(X.length):e,Y=(e,t,r)=>({kind:"version",semver:{major:e,minor:t,patch:r},raw:`${e}.${t}.${r}`}),A=e=>{if(e.length===0)throw new h('Release name is empty. Provide a kebab-case name like "checkout-redesign".');if(e.length>50)throw new h(`Release name "${e}" is ${e.length} characters; the maximum is 50.`);if(!Ie.test(e))throw new h(`Release name "${e}" is not kebab-case. Use lowercase letters, digits, and single hyphens, e.g. "checkout-redesign".`);if(H.has(e))throw new h(`Release name "${e}" is reserved. Reserved names: ${[...H].join(", ")}.`)},$=e=>{let t=J(e.trim());if(!t.startsWith(S))return null;if(t.startsWith(D)){let n=t.slice(D.length),o=je.exec(n);if(o)return Y(Number(o[1]),Number(o[2]),Number(o[3]))}let r=t.slice(S.length);try{A(r)}catch{return null}return{kind:"name",name:r,raw:r}},Ae=e=>{let t=e.trim();if(J(t).startsWith(S)){let o=$(t);if(!o)throw new y(`"${e}" looks like a release branch but is not a valid release/v<semver> or release/<name> ref.`);return o}let n=Ce.exec(t);if(n)return Y(Number(n[1]),Number(n[2]),Number(n[3]));if(t.toLowerCase()===De)throw new y('The "next" token must be resolved to a concrete version (via computeNextVersion) before parsing a release ref.');try{A(t)}catch(o){let i=o instanceof Error?o.message:String(o);throw new y(`Cannot parse "${e}" as a release ref: ${i}`)}return{kind:"name",name:t,raw:t}},$e=e=>e.kind==="version"?`${D}${e.raw}`:`${S}${e.name}`,Te=(e,t)=>{let r=t==="hotfix"?"Hotfix":"Release";return e.kind==="version"?`${r} v${e.raw}`:`${r} ${e.name}`},Ne=e=>e.kind==="version"?`Release v${e.raw} (RC)`:`Release ${e.name} (RC)`,_e=e=>e.kind==="version"?`v${e.raw}`:e.name,Le=e=>e.raw,T=e=>e==null?!1:$(e)!==null,q=e=>{if(e===void 0)return null;let t=e instanceof Date?e.getTime():new Date(e).getTime();return Number.isNaN(t)?null:t},Ke=(e,t,r)=>{if(e.kind==="version"&&t.kind==="version")return e.semver.major!==t.semver.major?e.semver.major-t.semver.major:e.semver.minor!==t.semver.minor?e.semver.minor-t.semver.minor:e.semver.patch-t.semver.patch;if(e.kind==="version")return-1;if(t.kind==="version")return 1;let n=q(r?.a),o=q(r?.b);return n!==null&&o!==null&&n!==o?n-o:e.name<t.name?-1:e.name>t.name?1:0};var Z=async e=>{let t=await f({cwd:e})`git worktree list --porcelain`,r=[],n=null;for(let o of t.stdout.split(`
2
+ `)){if(o.startsWith("worktree ")){n&&r.push(n),n={path:o.slice(9),branch:null,detached:!1,bare:!1,prunable:!1,locked:!1};continue}n&&(o.startsWith("branch ")?n.branch=o.slice(7).replace(/^refs\/heads\//,""):o==="detached"?n.detached=!0:o==="bare"?n.bare=!0:o==="locked"||o.startsWith("locked ")?n.locked=!0:(o==="prunable"||o.startsWith("prunable "))&&(n.prunable=!0))}return n&&r.push(n),r},Oe=async e=>{let t=await Z(Q.cwd()),r=n=>e==="release"?T(n):n.startsWith("feature/");return t.map(n=>n.branch).filter(n=>n!==null&&r(n))},Me=e=>{let t=E(e);return t&&/not a git repository/i.test(t)?"not a git repository":void 0},Fe=({hasStderr:e})=>{if(x())return"the infra-kit MCP server resolves its project from the working directory it was launched in; the operator must relaunch the server with its working directory set to an infra-kit project repo";let t="run infra-kit from inside an infra-kit project repo (or one of its git worktrees)";return e?`${t}; if you are already in one, the stderr in this message is the real cause`:t},k=async()=>{try{return(await f({quiet:!0})`git rev-parse --show-toplevel`).stdout.trim()}catch(e){let t=Me(e)??E(e);throw new R(e,{operation:`resolve the project root from ${Q.cwd()}`,stderrExcerpt:t,remediation:Fe({hasStderr:t!==void 0})})}},N=async e=>{let t=e??await k(),r=(await f({cwd:t,quiet:!0})`git rev-parse --git-common-dir`).stdout.trim(),n=v.resolve(t,r);return n.includes(`${v.sep}.git${v.sep}modules${v.sep}`)?t:v.dirname(n)},ee=async()=>(await f`git rev-parse --abbrev-ref HEAD`).stdout.trim(),We=async()=>(await f`git status --porcelain`).stdout.trim().length===0,Ge=async()=>{let e=await k(),[t,r]=await Promise.all([f({cwd:e})`git rev-parse --absolute-git-dir`,f({cwd:e})`git rev-parse --git-common-dir`]),n=t.stdout.trim(),o=v.resolve(e,r.stdout.trim());return n!==o},Be=async()=>{let e=await k();return v.basename(e)},ze=async e=>{(await f`git branch --list ${e}`).stdout.trim().length!==0&&await ee()!==e&&await f`git branch -D ${e}`},Ve=async e=>{(await f`git ls-remote --heads origin ${e}`).stdout.trim().length!==0&&await f`git push origin --delete ${e}`};var te="infra-kit.json",oe=".infra-kit",Xe="infra-kit.json",He="projects",qe=s.object({provider:s.literal("doppler"),config:s.object({name:s.string().min(1)})}),Je=s.discriminatedUnion("provider",[qe]),Ye=s.object({workspaceConfigPath:s.string().min(1)}),Qe=s.object({provider:s.literal("cursor"),config:Ye}),Ze=s.object({}),et=s.object({provider:s.literal("zed"),config:Ze}),re=s.discriminatedUnion("provider",[Qe,et]),tt=s.union([re,s.array(re).min(1)]),rt=s.object({provider:s.literal("jira"),config:s.object({baseUrl:s.string().url(),projectId:s.number().int().positive()})}),nt=s.discriminatedUnion("provider",[rt]),ot=["two-columns","three-pane"],st=s.object({layout:s.enum(ot).optional()}),it=s.object({openInGithubDesktop:s.boolean().optional(),openInCmux:s.boolean().optional(),cmux:st.optional()}),at=s.object({port:s.number().int().positive().optional(),prefixUrl:s.string().min(1).optional()}).strict(),ct=s.record(s.string().min(1),at),pt=s.enum(["local","cloud"]),lt=s.object({watchDeps:s.boolean().optional(),proxy:s.record(s.string().min(1),pt).optional()}).strict(),ut=s.object({apps:s.record(s.string().min(1),lt).optional(),cmux:s.boolean().optional()}).strict(),ft=s.record(s.string().min(1),ut),dt=s.object({port:s.number().int().positive().optional()}).strict(),gt=s.object({trigger:s.enum(["shell-startup","cli-invocation"]),config:s.string().min(1)}).strict(),mt=s.enum(["disallow","allow","cli-only"]),K=s.object({envManagement:Je,ide:tt.optional(),taskManager:nt.optional(),worktrees:it.optional(),envAutoLoad:gt.optional(),dev:ct.optional(),devServersPresets:ft.optional(),devProxy:dt.optional(),protectedEnvs:mt.optional()}).strict(),ht=443,se=K.superRefine((e,t)=>{if(!Array.isArray(e.ide))return;let r=new Set;for(let n of e.ide){if(r.has(n.provider)){t.addIssue({code:"custom",message:"each IDE provider may appear at most once",path:["ide"]});return}r.add(n.provider)}}),ie=K.partial(),vt=e=>{let t=e.ide;return t?Array.isArray(t)?t:[t]:[]},yt="two-columns",kt=e=>e.worktrees?.cmux?.layout??yt,d=null,b=null,ae=()=>`${Ue.cwd()} ${ne.homedir()}`,ce=async()=>{let e=ae();if(b&&b.key===e)return b.value;let t=await k(),r=await N(t),n=w.basename(r),o=w.join(ne.homedir(),oe),i={main:w.join(t,te),userGlobal:w.join(o,Xe),userProject:w.join(o,He,n,te),projectName:n};return b={key:e,value:i},i},xt=async()=>{let e=ae(),t=await ce(),r;try{r=await L.stat(t.main)}catch{d=null;let g=t.main.replace(/\.json$/,".yml");throw await _(g)?new Error(`infra-kit.json not found at ${t.main}. A legacy infra-kit.yml exists \u2014 run \`infra-kit init\` to convert it.`):new Error(x()?`infra-kit.json not found at ${t.main} \u2014 the directory the infra-kit MCP server was launched in is not an infra-kit project. The operator must relaunch the server with its working directory set to an infra-kit project repo.`:`infra-kit.json not found at ${t.main} \u2014 this git repo is not an infra-kit project. Run \`infra-kit init\` here to create it, cd into an infra-kit project repo, or check out a branch that has infra-kit.json.`)}let[n,o]=await Promise.all([_(t.userGlobal),_(t.userProject)]),i={main:Number(r.mtimeMs),userGlobal:n?Number(n.mtimeMs):null,userProject:o?Number(o.mtimeMs):null};if(d&&d.key===e&&Rt(d.mtimes,i))return d.value;let c=[{label:"infra-kit.json",path:t.main,required:!0},{label:"~/.infra-kit/infra-kit.json",path:t.userGlobal,required:!1},{label:`~/.infra-kit/projects/${t.projectName}/infra-kit.json`,path:t.userProject,required:!1}],l={};for(let g of c){let m=await Et(g);m!==null&&(l={...l,...m})}let u=se.safeParse(l);if(!u.success)throw new Error(`Invalid merged infra-kit config: ${s.prettifyError(u.error)}`);return d={key:e,mtimes:i,value:u.data},u.data},wt=()=>{d=null},bt=()=>{d=null,b=null},_=async e=>{try{return await L.stat(e)}catch{return null}},Pt=async e=>{try{return await L.readFile(e,"utf-8")}catch{return null}},Rt=(e,t)=>{let r=Object.keys(e);return r.length!==Object.keys(t).length?!1:r.every(n=>e[n]===t[n])},Et=async e=>{let t=await Pt(e.path);if(t===null){if(e.required)throw new Error(`${e.label} not found at ${e.path}`);return null}let r;try{r=t.trim()===""?{}:JSON.parse(t)}catch(o){throw new Error(`Invalid JSON in ${e.label} at ${e.path}: ${o.message}`)}if(St(r)&&"envTokens"in r)throw new Error(Ct(e));let n=ie.safeParse(r);if(!n.success)throw new Error(`Invalid ${e.label} at ${e.path}: ${s.prettifyError(n.error)}`);return n.data},St=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),Ct=e=>[`Refusing to load ${e.label} \u2014 \`envTokens\` is not a config key.`,"A service token in a config file can be committed, backed up by your editor, or shared."," 1. REVOKE the token in Doppler now \u2014 treat it as compromised.",` 2. Remove the \`envTokens\` key from ${e.path}.`," 3. Re-add it privately: `infra-kit env-token-set <env>`"," (it is written to ~/.infra-kit/projects/<repo>/tokens.json, mode 0600, never to the repo)."].join(`
3
+ `);export{E as a,R as b,U as c,x as d,h as e,A as f,$ as g,Ae as h,$e as i,Te as j,Ne as k,_e as l,Le as m,T as n,Ke as o,Z as p,Oe as q,k as r,N as s,ee as t,We as u,Ge as v,Be as w,ze as x,Ve as y,O as z,At as A,$t as B,ue as C,Nt as D,_t as E,Lt as F,Kt as G,Ot as H,Mt as I,Ft as J,Wt as K,V as L,Bt as M,Pe as N,zt as O,Vt as P,oe as Q,ht as R,se as S,ie as T,vt as U,kt as V,ce as W,xt as X,wt as Y,bt as Z};
4
+ //# sourceMappingURL=chunk-SSBYKOHY.js.map