From 7ba2397be37ca5453c9384b78ec046e74f6db30d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 10 Nov 2026 04:24:43 +0000 Subject: [PATCH 1/5] fix(autofix): standalone adapter conflict resolution and vite-plus detection - F-01: Include standalone adapters in capability conflict resolution by reusing processCandidateTools and sharing coveredCapabilities. - F-02: Make Vite+ detection resistant to false positives using parseCommandInvocations. - Rebuild dist/autofix.mjs bundle. - Add changeset and comprehensive regression tests. --- ...apter-conflicts-and-vite-plus-detection.md | 5 + dist/autofix.mjs | 12 +- src/autofix/adapters/javascript/tools.ts | 14 +- src/autofix/planner.ts | 36 +- tests/autofix-architecture.test.ts | 373 ++++++++++++++++++ 5 files changed, 421 insertions(+), 19 deletions(-) create mode 100644 .changeset/fix-standalone-adapter-conflicts-and-vite-plus-detection.md diff --git a/.changeset/fix-standalone-adapter-conflicts-and-vite-plus-detection.md b/.changeset/fix-standalone-adapter-conflicts-and-vite-plus-detection.md new file mode 100644 index 00000000..fee7c66f --- /dev/null +++ b/.changeset/fix-standalone-adapter-conflicts-and-vite-plus-detection.md @@ -0,0 +1,5 @@ +--- +"@area44/workflows": patch +--- + +Fix standalone adapter capability conflict resolution and prevent false-positive Vite+ detection. diff --git a/dist/autofix.mjs b/dist/autofix.mjs index 85bad52b..1b5bf8d0 100644 --- a/dist/autofix.mjs +++ b/dist/autofix.mjs @@ -303,11 +303,11 @@ const Vn=[`uv`,`pip`],Hn=[`.git`,`.venv`,`venv`,`env`,`.env`,`virtualenv`,`.virt `?` `:` `,i++;return i=t+1&&e[a]===`\\`;)n++,a--;if(n%2==0)return r+=` `,[r,i+1]}r+=` `,i++}return[r,i]}function dr(e,t,n){let r=` `,i=t+1;for(;i!Un(e))}function mr(e,t){if(!Un(e[`build-system`]))return!1;if(typeof t==`string`){let e=fr(t);return/(?:^|\n)\s*\[\s*build-system\s*\]\s*(?:\n|$)/.test(e)}let n=Object.entries(e[`build-system`]);return n.length===0||n.some(([,e])=>!Un(e))}function hr(e,t){if(pr(e,t)||mr(e,t))return!0;if(Un(e.tool)&&Un(e.tool.uv)){let t=e.tool.uv;return Yn(t.workspace)||Array.isArray(t[`dev-dependencies`])}return!1}function gr(e){return Un(e.tool)&&Un(e.tool.uv)}function _r(e,t){return pr(e,t)||mr(e,t)}function vr(e,t){return p.relative(e,t)||`.`}function yr(e,t){if(!t)throw Error(`Invalid Python project configuration: 'uv.lock' was detected without a valid 'pyproject.toml' project or workspace configuration ('[project]', '[build-system]', or '[tool.uv.workspace]'). 'uv sync' requires a valid 'pyproject.toml' file.`);return{name:`uv`,lockfile:`uv.lock`,configFile:`pyproject.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}}function br(e,t){if(e.hasRequirementsTxt&&e.requirementsDir){let t=vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`));return{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`pip`,`install`,`-r`,t]}],execPrefix:`uv run`}}return t?{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}:null}function xr(e){let t=e.pyprojectToml?.success===!0&&hr(e.pyprojectToml.data,e.pyprojectToml.rawContent),n=e.workspaceRootToml?.success===!0&&hr(e.workspaceRootToml.data,e.workspaceRootToml.rawContent),r=t||n,i=e.uvToml?.success===!0,a=e.pyprojectToml?.success===!0&&gr(e.pyprojectToml.data)||e.workspaceRootToml?.success===!0&&gr(e.workspaceRootToml.data);return e.hasUvLock?yr(e,r):a||i?br(e,r):null}function Sr(e){let t=e.pyprojectToml?.success===!0&&_r(e.pyprojectToml.data,e.pyprojectToml.rawContent);if(!(e.hasRequirementsTxt||e.hasSetupPy||e.hasSetupCfg||t))return null;let n;t?n=`pyproject.toml`:e.hasSetupPy?n=`setup.py`:e.hasSetupCfg&&(n=`setup.cfg`);let r=[],i,a=e.hasSetupPy||e.hasSetupCfg||t,o=e.requirementsDir?vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`)):`requirements.txt`,s=vr(e.cwd,e.projectDir);return e.hasRequirementsTxt&&a?(r=[{executable:`pip`,args:[`install`,`-r`,o]},{executable:`pip`,args:[`install`,`-e`,s]}],i=`requirements.txt`):e.hasRequirementsTxt?(r=[{executable:`pip`,args:[`install`,`-r`,o]}],i=`requirements.txt`):a&&(r=[{executable:`pip`,args:[`install`,`-e`,s]}]),{name:`pip`,lockfile:i,configFile:n,installCommands:r,execPrefix:``}}function Cr(e=process.cwd(),t){if(t?.hasSource??or(e))return!0;let n=t?.ctx??ir(e);if(n.projectDir===n.cwd&&tr(n.cwd)&&(n.pyprojectToml?.success===!0&&hr(n.pyprojectToml.data,n.pyprojectToml.rawContent)||n.hasUvLock||n.hasRequirementsTxt||n.hasSetupPy||n.hasSetupCfg))return!0;if(n.workspaceRootDir&&n.workspaceRootToml?.success===!0){let t=Zn(n.workspaceRootDir);if(t&&Xn(n.workspaceRootDir,p.resolve(e),t.config))return!0}return!1}function wr(e,t){t!=null&&(e.pyprojectToml=t);for(let t of Vn)if(t===`uv`){let t=xr(e);if(t)return t}else if(t===`pip`){let t=Sr(e);if(t)return t}return{name:`pip`,installCommands:[],execPrefix:``,isStandalone:!0}}function Tr(e=process.cwd(),t,n){let r=n?.ctx??ir(e);return n?.isProject??Cr(e,{ctx:r,hasSource:n?.hasSource})?wr(r,t):null}function Er(e){if(!Array.isArray(e))throw Error(`Invalid Python environment: "pmInfo.installCommands" must be an array`);for(let t of e){if(!t||typeof t!=`object`)throw Error(`Invalid Python environment: malformed "installCommands" item`);let e=t;if(typeof e.executable!=`string`||!e.executable.trim()||!Array.isArray(e.args)||!e.args.every(e=>typeof e==`string`))throw Error(`Invalid Python environment: malformed "installCommands" item`)}}function Dr(e,t=`Invalid Python environment: "pmInfo" must be an object`){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(t);let n=e;if(n.name!==`uv`&&n.name!==`pip`)throw Error(`Invalid Python environment: pmInfo name must be "uv" or "pip"`);return Er(n.installCommands),n}function Or(e){if(!process.argv[1])return!1;try{return l(e)===f.realpathSync(process.argv[1])}catch{return!1}}async function kr(e,t,n=process.platform){let r=p.join(e,`node_modules`,`.bin`),i=/* @__PURE__ */ new Set([`.cmd`,`.bat`,`.exe`]);if(n===`win32`){let e=p.extname(t).toLowerCase();if(e){if(!i.has(e))return;let n=p.join(r,t);if(f.existsSync(n))return n}else for(let e of[`.cmd`,`.bat`,`.exe`,``]){let n=p.join(r,`${t}${e}`);if(f.existsSync(n))return n}}else{let e=p.join(r,t);if(f.existsSync(e))return e}let a=await Vt(t,!1);if(a){if(n===`win32`){let e=p.extname(a).toLowerCase();if(e&&!i.has(e))return}return a}}var Ar=class{platform;constructor(e=process.platform){this.platform=e}async resolveTaskExecutable(e){if(e.toolId===`npm-scripts`)return e.executable;if(e.toolId===`ruff`){if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);return`ruff`}let t=await kr(e.cwd,e.executable,this.platform);if(!t){let t=e.toolName||e.toolId,n=e.requiredPackage||e.executable;throw Error(`Configured tool "${t}" could not run: executable "${e.executable}" is not available in node_modules/.bin or PATH. Please install "${n}" in project dependencies.`)}return t}async executeTasks(e){let t=[];for(let n of e){let e=`${n.executable} ${n.args.join(` `)}`.trim();try{let r=await this.resolveTaskExecutable(n);en(`Executing: ${e}`);let i=n.env?Object.fromEntries(Object.entries({...process.env,...n.env}).filter(e=>e[1]!==void 0)):void 0,a=await Yt(r,n.args,{cwd:n.cwd,env:i,ignoreReturnCode:!0});if(a!==0){let r=n.toolId===`ruff`?`Ruff command "${e}" failed. Check Python and Ruff configuration.`:n.toolId===`npm-scripts`?`Script "${n.args[1]||e}" failed while executing "${e}".`:`Task "${n.id}" (${e}) failed with exit code ${a}.`;t.push({task:n,exitCode:a,error:Error(r)})}else t.push({task:n,exitCode:a})}catch(e){let r=e instanceof Error?e:Error(String(e));t.push({task:n,exitCode:1,error:r})}}return t}};function jr(e,t){return t.has(`autofix`)?!0:e===`autofix`?t.has(`format`)&&t.has(`lint`)&&t.has(`assist`):t.has(e)}function Mr(e,t){let n=[],r=[];for(let i of e)jr(i.capability,t)?r.push(i):n.push(i);return{kept:n,skipped:r}}async function Nr(e,t,n,r,i,a,o){for(let s of e){let e=s.adapter,c=await e.plan(n,r);if(c.length===0)continue;let{kept:l,skipped:u}=Mr(c,t);if(l.length===0)a.push({id:e.id,name:e.name,reason:`all capabilities already covered by higher priority tool`});else{i.push({id:e.id,name:e.name,reason:s.reason});for(let e of l)if(t.add(e.capability),e.capabilities)for(let n of e.capabilities)t.add(n);if(o.push(...l),u.length>0){let t=Array.from(new Set(u.map(e=>e.capability))).join(`, `);a.push({id:e.id,name:e.name,reason:`partially skipped (${t} covered by higher priority tool)`})}}}}async function Pr(e,t,n,r,i){for(let a of e.getStandaloneAdapters()){let e=await a.detect(t);if(e.detected){r.push({id:a.id,name:a.name,reason:e.reason});let o=await a.plan(t,n);i.push(...o)}}}function Fr(e){let t=[],n=/* @__PURE__ */ new Set;for(let r of e)n.has(r.id)||(n.add(r.id),t.push(r));return t}async function Ir(e,t,n=`fix`){let r=t.hasPythonSource??or(t.cwd),i=t.jsEnv??fn(t.cwd),a={...t,jsEnv:i,hasPythonSource:r},o=[],s=[],c=[],l=e.getProviders(),u=/* @__PURE__ */ new Map;for(let e of l){if(!await e.detect(a))continue;let t=/* @__PURE__ */ new Set;u.set(e.id,t);let r=e.getAdapters(a),i=[];for(let e of r){let t=await e.detect(a);t.detected?i.push({adapter:e,reason:t.reason}):t.reason&&!t.reason.startsWith(`no `)&&s.push({id:e.id,name:e.name,reason:t.reason})}await Nr(i,t,a,n,o,s,c)}await Pr(e,a,n,o,c);let d=Fr(c);return{tasks:d,selectedTools:o,skippedTools:s,summary:Lr(e,a,o,s,d)}}function Lr(e,t,n,r,i){let a=[];a.push(`Detected environments:`);let o=t.hasPythonSource??!1,s=t.jsEnv?.hasPackageJson??!1;if(a.push(` Python: ${o}`),a.push(` JavaScript: ${s}`),o&&(a.push(``),a.push(`Python toolchain:`),n.filter(e=>e.id===`ruff`).length>0?a.push(` Ruff: default tool`):a.push(` None`)),s){a.push(``),a.push(`JavaScript toolchain:`);let e=n.filter(e=>e.id!==`ruff`);for(let t of e)a.push(` ${t.name}: selected`);let t=r.filter(e=>e.id!==`ruff`);for(let e of t)a.push(` ${e.name}: skipped (${e.reason})`)}if(a.push(``),a.push(`Execution plan:`),i.length===0?a.push(` (no tasks to execute)`):i.forEach((e,t)=>{let n=e.description||`${e.executable} ${e.args.join(` `)}`;a.push(` ${t+1}. ${n}`)}),r.length>0){a.push(``),a.push(`Skipped:`);for(let e of r)a.push(` - ${e.name}: ${e.reason}`)}return a.join(` +`&&e[i]!==`\r`;)r+=` `,i++;return i!Un(e))}function mr(e,t){if(!Un(e[`build-system`]))return!1;if(typeof t==`string`){let e=fr(t);return/(?:^|\n)\s*\[\s*build-system\s*\]\s*(?:\n|$)/.test(e)}let n=Object.entries(e[`build-system`]);return n.length===0||n.some(([,e])=>!Un(e))}function hr(e,t){if(pr(e,t)||mr(e,t))return!0;if(Un(e.tool)&&Un(e.tool.uv)){let t=e.tool.uv;return Yn(t.workspace)||Array.isArray(t[`dev-dependencies`])}return!1}function gr(e){return Un(e.tool)&&Un(e.tool.uv)}function _r(e,t){return pr(e,t)||mr(e,t)}function vr(e,t){return p.relative(e,t)||`.`}function yr(e,t){if(!t)throw Error(`Invalid Python project configuration: 'uv.lock' was detected without a valid 'pyproject.toml' project or workspace configuration ('[project]', '[build-system]', or '[tool.uv.workspace]'). 'uv sync' requires a valid 'pyproject.toml' file.`);return{name:`uv`,lockfile:`uv.lock`,configFile:`pyproject.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}}function br(e,t){if(e.hasRequirementsTxt&&e.requirementsDir){let t=vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`));return{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`pip`,`install`,`-r`,t]}],execPrefix:`uv run`}}return t?{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}:null}function xr(e){let t=e.pyprojectToml?.success===!0&&hr(e.pyprojectToml.data,e.pyprojectToml.rawContent),n=e.workspaceRootToml?.success===!0&&hr(e.workspaceRootToml.data,e.workspaceRootToml.rawContent),r=t||n,i=e.uvToml?.success===!0,a=e.pyprojectToml?.success===!0&&gr(e.pyprojectToml.data)||e.workspaceRootToml?.success===!0&&gr(e.workspaceRootToml.data);return e.hasUvLock?yr(e,r):a||i?br(e,r):null}function Sr(e){let t=e.pyprojectToml?.success===!0&&_r(e.pyprojectToml.data,e.pyprojectToml.rawContent);if(!(e.hasRequirementsTxt||e.hasSetupPy||e.hasSetupCfg||t))return null;let n;t?n=`pyproject.toml`:e.hasSetupPy?n=`setup.py`:e.hasSetupCfg&&(n=`setup.cfg`);let r=[],i,a=e.hasSetupPy||e.hasSetupCfg||t,o=e.requirementsDir?vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`)):`requirements.txt`,s=vr(e.cwd,e.projectDir);return e.hasRequirementsTxt&&a?(r=[{executable:`pip`,args:[`install`,`-r`,o]},{executable:`pip`,args:[`install`,`-e`,s]}],i=`requirements.txt`):e.hasRequirementsTxt?(r=[{executable:`pip`,args:[`install`,`-r`,o]}],i=`requirements.txt`):a&&(r=[{executable:`pip`,args:[`install`,`-e`,s]}]),{name:`pip`,lockfile:i,configFile:n,installCommands:r,execPrefix:``}}function Cr(e=process.cwd(),t){if(t?.hasSource??or(e))return!0;let n=t?.ctx??ir(e);if(n.projectDir===n.cwd&&tr(n.cwd)&&(n.pyprojectToml?.success===!0&&hr(n.pyprojectToml.data,n.pyprojectToml.rawContent)||n.hasUvLock||n.hasRequirementsTxt||n.hasSetupPy||n.hasSetupCfg))return!0;if(n.workspaceRootDir&&n.workspaceRootToml?.success===!0){let t=Zn(n.workspaceRootDir);if(t&&Xn(n.workspaceRootDir,p.resolve(e),t.config))return!0}return!1}function wr(e,t){t!=null&&(e.pyprojectToml=t);for(let t of Vn)if(t===`uv`){let t=xr(e);if(t)return t}else if(t===`pip`){let t=Sr(e);if(t)return t}return{name:`pip`,installCommands:[],execPrefix:``,isStandalone:!0}}function Tr(e=process.cwd(),t,n){let r=n?.ctx??ir(e);return n?.isProject??Cr(e,{ctx:r,hasSource:n?.hasSource})?wr(r,t):null}function Er(e){if(!Array.isArray(e))throw Error(`Invalid Python environment: "pmInfo.installCommands" must be an array`);for(let t of e){if(!t||typeof t!=`object`)throw Error(`Invalid Python environment: malformed "installCommands" item`);let e=t;if(typeof e.executable!=`string`||!e.executable.trim()||!Array.isArray(e.args)||!e.args.every(e=>typeof e==`string`))throw Error(`Invalid Python environment: malformed "installCommands" item`)}}function Dr(e,t=`Invalid Python environment: "pmInfo" must be an object`){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(t);let n=e;if(n.name!==`uv`&&n.name!==`pip`)throw Error(`Invalid Python environment: pmInfo name must be "uv" or "pip"`);return Er(n.installCommands),n}function Or(e){if(!process.argv[1])return!1;try{return l(e)===f.realpathSync(process.argv[1])}catch{return!1}}async function kr(e,t,n=process.platform){let r=p.join(e,`node_modules`,`.bin`),i=/* @__PURE__ */ new Set([`.cmd`,`.bat`,`.exe`]);if(n===`win32`){let e=p.extname(t).toLowerCase();if(e){if(!i.has(e))return;let n=p.join(r,t);if(f.existsSync(n))return n}else for(let e of[`.cmd`,`.bat`,`.exe`,``]){let n=p.join(r,`${t}${e}`);if(f.existsSync(n))return n}}else{let e=p.join(r,t);if(f.existsSync(e))return e}let a=await Vt(t,!1);if(a){if(n===`win32`){let e=p.extname(a).toLowerCase();if(e&&!i.has(e))return}return a}}var Ar=class{platform;constructor(e=process.platform){this.platform=e}async resolveTaskExecutable(e){if(e.toolId===`npm-scripts`)return e.executable;if(e.toolId===`ruff`){if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);return`ruff`}let t=await kr(e.cwd,e.executable,this.platform);if(!t){let t=e.toolName||e.toolId,n=e.requiredPackage||e.executable;throw Error(`Configured tool "${t}" could not run: executable "${e.executable}" is not available in node_modules/.bin or PATH. Please install "${n}" in project dependencies.`)}return t}async executeTasks(e){let t=[];for(let n of e){let e=`${n.executable} ${n.args.join(` `)}`.trim();try{let r=await this.resolveTaskExecutable(n);en(`Executing: ${e}`);let i=n.env?Object.fromEntries(Object.entries({...process.env,...n.env}).filter(e=>e[1]!==void 0)):void 0,a=await Yt(r,n.args,{cwd:n.cwd,env:i,ignoreReturnCode:!0});if(a!==0){let r=n.toolId===`ruff`?`Ruff command "${e}" failed. Check Python and Ruff configuration.`:n.toolId===`npm-scripts`?`Script "${n.args[1]||e}" failed while executing "${e}".`:`Task "${n.id}" (${e}) failed with exit code ${a}.`;t.push({task:n,exitCode:a,error:Error(r)})}else t.push({task:n,exitCode:a})}catch(e){let r=e instanceof Error?e:Error(String(e));t.push({task:n,exitCode:1,error:r})}}return t}};function jr(e,t){return t.has(`autofix`)?!0:e===`autofix`?t.has(`format`)&&t.has(`lint`)&&t.has(`assist`):t.has(e)}function Mr(e,t){let n=[],r=[];for(let i of e)jr(i.capability,t)?r.push(i):n.push(i);return{kept:n,skipped:r}}async function Nr(e,t,n,r,i,a,o){for(let s of e){let e=s.adapter,c=await e.plan(n,r);if(c.length===0)continue;let{kept:l,skipped:u}=Mr(c,t);if(l.length===0)a.push({id:e.id,name:e.name,reason:`all capabilities already covered by higher priority tool`});else{i.push({id:e.id,name:e.name,reason:s.reason});for(let e of l)if(t.add(e.capability),e.capabilities)for(let n of e.capabilities)t.add(n);if(o.push(...l),u.length>0){let t=Array.from(new Set(u.map(e=>e.capability))).join(`, `);a.push({id:e.id,name:e.name,reason:`partially skipped (${t} covered by higher priority tool)`})}}}}async function Pr(e,t,n,r,i,a,o){let s=[];for(let t of e.getStandaloneAdapters()){let e=await t.detect(n);e.detected?s.push({adapter:t,reason:e.reason}):e.reason&&!e.reason.startsWith(`no `)&&a.push({id:t.id,name:t.name,reason:e.reason})}await Nr(s,t,n,r,i,a,o)}function Fr(e){let t=[],n=/* @__PURE__ */ new Set;for(let r of e)n.has(r.id)||(n.add(r.id),t.push(r));return t}async function Ir(e,t,n=`fix`){let r=t.hasPythonSource??or(t.cwd),i=t.jsEnv??fn(t.cwd),a={...t,jsEnv:i,hasPythonSource:r},o=[],s=[],c=[],l=e.getProviders(),u=/* @__PURE__ */ new Set;for(let e of l){if(!await e.detect(a))continue;let t=e.getAdapters(a),r=[];for(let e of t){let t=await e.detect(a);t.detected?r.push({adapter:e,reason:t.reason}):t.reason&&!t.reason.startsWith(`no `)&&s.push({id:e.id,name:e.name,reason:t.reason})}await Nr(r,u,a,n,o,s,c)}await Pr(e,u,a,n,o,s,c);let d=Fr(c);return{tasks:d,selectedTools:o,skippedTools:s,summary:Lr(e,a,o,s,d)}}function Lr(e,t,n,r,i){let a=[];a.push(`Detected environments:`);let o=t.hasPythonSource??!1,s=t.jsEnv?.hasPackageJson??!1;if(a.push(` Python: ${o}`),a.push(` JavaScript: ${s}`),o&&(a.push(``),a.push(`Python toolchain:`),n.filter(e=>e.id===`ruff`).length>0?a.push(` Ruff: default tool`):a.push(` None`)),s){a.push(``),a.push(`JavaScript toolchain:`);let e=n.filter(e=>e.id!==`ruff`);for(let t of e)a.push(` ${t.name}: selected`);let t=r.filter(e=>e.id!==`ruff`);for(let e of t)a.push(` ${e.name}: skipped (${e.reason})`)}if(a.push(``),a.push(`Execution plan:`),i.length===0?a.push(` (no tasks to execute)`):i.forEach((e,t)=>{let n=e.description||`${e.executable} ${e.args.join(` `)}`;a.push(` ${t+1}. ${n}`)}),r.length>0){a.push(``),a.push(`Skipped:`);for(let e of r)a.push(` - ${e.name}: ${e.reason}`)}return a.join(` `)}function Rr(e){for(let t of[`format:write`,`format:fix`,`format`,`fmt`])if(e[t]&&qi(e[t],e))return t}function zr(e){if(e[`format:check`]&&Ki(e[`format:check`],e)===`read-only`)return`format:check`;if(e[`fmt:check`]&&Ki(e[`fmt:check`],e)===`read-only`)return`fmt:check`}function Br(e,t){return t===`fix`?Rr(e):zr(e)}function Vr(e,t){if(t===`fix`)return e[`lint:fix`]?`lint:fix`:e[`lint:write`]?`lint:write`:void 0;if(e[`lint:check`]&&Ki(e[`lint:check`],e)===`read-only`)return`lint:check`;if(e.lint&&Ki(e.lint,e)===`read-only`)return`lint`}function Hr(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped)return 0;let r=e[t];return r===`;`||r===` `?1:r===`&`&&e[t+1]===`&`||r===`|`&&e[t+1]===`|`?2:+(r===`|`)}function Ur(e,t){let n=t;for(;nt?n-1:t}function Wr(e,t){return t.inSingleQuote||t.inDoubleQuote||t.isEscaped?!1:e.length===0||/\s/.test(e[e.length-1])}function Gr(e,t){return t.isEscaped=!1,{ch:e,advance:!0}}function Kr(e,t,n,r){let i=e[t];if(n.isEscaped)return{newCmd:r+Gr(i,n).ch,nextIndex:t,sepLen:0};if(i===`\\`&&!n.inSingleQuote)return n.isEscaped=!0,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`'`&&!n.inDoubleQuote)return n.inSingleQuote=!n.inSingleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`"`&&!n.inSingleQuote)return n.inDoubleQuote=!n.inDoubleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`#`&&Wr(r,n))return{newCmd:r,nextIndex:Ur(e,t),sepLen:0};let a=Hr(e,t,n);return{newCmd:r+(a===0?i:``),nextIndex:t,sepLen:a}}function qr(e){let t=[],n=``,r={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1,hasSyntaxError:!1};for(let i=0;i0?(n.trim()&&t.push(n.trim()),n=``,i+=a.sepLen-1):(n=a.newCmd,i=a.nextIndex)}return(r.inSingleQuote||r.inDoubleQuote||r.isEscaped)&&(r.hasSyntaxError=!0),n.trim()&&t.push(n.trim()),{commands:t,hasSyntaxError:r.hasSyntaxError}}function Jr(e){return qr(e).commands}function Yr(e,t,n){return t.isEscaped=!1,n+e}function Xr(e,t){return e===`'`&&!t.inDoubleQuote?(t.inSingleQuote=!t.inSingleQuote,!0):e===`"`&&!t.inSingleQuote&&(t.inDoubleQuote=!t.inDoubleQuote,!0)}const Zr=/* @__PURE__ */ new Set([`@`,`*`,`#`,`?`,`-`,`$`,`!`,`0`]);function Qr(e,t,n){if(n.inSingleQuote||n.isEscaped||e[t]!==`$`||t+1>=e.length)return!1;let r=e[t+1];return!!(r===`{`||Zr.has(r)||r>=`1`&&r<=`9`||r===`_`||r>=`a`&&r<=`z`||r>=`A`&&r<=`Z`)}function $r(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped||e[t]!==`&`)return!1;let r=t>0?e[t-1]:``,i=t+1`}function ei(e,t,n){if(n.inSingleQuote||n.isEscaped)return!1;let r=e[t];return r==="`"||r===`$`&&t+1`)&&t+1`||r===`<`||r===`&`&&t+1`}function ri(e,t,n){return $r(e,t,n.state)||Qr(e,t,n.state)||ei(e,t,n.state)||ti(e,t,n.state)?(n.inspection.hasUnsupportedSyntax=!0,!0):ni(e,t,n.state)?(n.inspection.hasRedirection=!0,n.inspection.hasUnsupportedSyntax=!0,!0):!1}function ii(e,t,n,r){let i=e[t];return n.state.isEscaped?{word:Yr(i,n.state,r),hasChars:!0,skipped:!1}:i===`\\`&&!n.state.inSingleQuote?(n.state.isEscaped=!0,{word:r,hasChars:!1,skipped:!0}):(ri(e,t,n),Xr(i,n.state)?{word:r,hasChars:!0,skipped:!0}:{word:r+i,hasChars:!0,skipped:!1})}function ai(e){let t={tokens:[],hasUnsupportedSyntax:!1,hasRedirection:!1},n={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1},r={inspection:t,state:n},i=``,a=!1;for(let o=0;o0&&n.push(t)}return n}function fi(e,t,n={},r=/* @__PURE__ */ new Set){if(!e||!t)return!1;let i=di(n[e]===void 0?e:n[e]);for(let e of i){if(ui(e,t))return!0;let i=Bi(e);if(i){if(i===t)return!0;if(!r.has(i)&&n[i]!==void 0){r.add(i);try{if(fi(n[i],t,n,r))return!0}finally{r.delete(i)}}}let a=Vi(e);if(a!==void 0&&fi(a,t,n,r))return!0}return!1}function pi(e,t,n){return!n||n===t?!1:!fi(e[t]||``,n,e)}function mi(e,t,n){return!n||n===t?!1:!fi(e[t]||``,n,e)}function hi(e){let[t]=e;return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||(e===`--fix`||e.startsWith(`--fix=`))&&(t!==`eslint`||e!==`--fix-dry-run`))}function gi(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function _i(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function vi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function yi(e){let[t]=e;return t===`eslint`&&e.some(e=>(e===`--fix`||e.startsWith(`--fix=`))&&e!==`--fix-dry-run`)}function bi(e){let[t]=e;return t===`oxlint`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function xi(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Si(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Ci(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:!e.some(e=>e===`--check`||e===`-c`)}function wi(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Ti(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)&&e!==`--fix-dry-run`||e===`-o`||e.startsWith(`-o=`)||e===`--output-file`||e.startsWith(`--output-file=`)||e===`--cache`||e===`--cache-file`||e.startsWith(`--cache-file=`)||e===`--cache-location`||e.startsWith(`--cache-location=`))}function Ei(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--cache`||e===`--cache-location`||e.startsWith(`--cache-location=`)||e===`--insert-pragma`)}function Di(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`)||e===`--reporter-file`||e.startsWith(`--reporter-file=`)||e===`--log-file`||e.startsWith(`--log-file=`))}function Oi(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)||e===`--fix-suggestions`||e===`--fix-dangerously`||e===`--init`)}function ki(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--init`||e===`--migrate`||e.startsWith(`--migrate=`))}function Ai(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`--check`||e===`-c`||e===`--list-different`||e===`-l`)&&!Ei(e)}function ji(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`--check`||e===`-c`)&&!ki(e)}function Mi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:!Di(e)}function Ni(e){let[t]=e;return t===`eslint`&&!Ti(e)}function Pi(e){let[t]=e;return t===`oxlint`&&!Oi(e)}function Fi(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:!Di(e)}function Ii(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:!Di(e)}function Li(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:e.some(e=>e===`--check`||e===`-c`)&&!ki(e)}function Ri(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:!Oi(e)}function zi(e){let[t,n]=e;return t!==`vp`||n!==`check`?!1:!e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Bi(e){if(e.length===0)return;let[t,n,r]=e;if((t===`npm`||t===`pnpm`||t===`yarn`||t===`bun`)&&n===`run`&&r)return r;if((t===`pnpm`||t===`bun`||t===`yarn`)&&n&&!n.startsWith(`-`))return n}function Vi(e){if(e.length>=3&&(e[0]===`sh`||e[0]===`bash`)&&e[1]===`-c`)return e[2]}function Hi(e){return gi(e)||_i(e)||vi(e)||yi(e)||bi(e)||xi(e)||Si(e)||Ci(e)||wi(e)}function Ui(e){return Ai(e)||ji(e)||Mi(e)||Ni(e)||Pi(e)||Fi(e)||Ii(e)||Li(e)||Ri(e)||zi(e)}function Wi(e,t,n){if(e.length===0)return`unknown`;if(hi(e))return`write-capable`;let r=Vi(e);if(r!==void 0)return Gi(r,t,n);let i=Bi(e);if(i){if(n.has(i))return`unknown`;let e=t[i];if(!e)return`unknown`;n.add(i);try{return Gi(e,t,n)}finally{n.delete(i)}}return Hi(e)?`write-capable`:Ui(e)?`read-only`:`unknown`}function Gi(e,t,n){let r=qr(e);if(r.hasSyntaxError)return`unknown`;let{commands:i}=r;if(i.length===0)return`unknown`;let a=!1;for(let e of i){let r=ai(e),i=Wi(li(r.tokens),t,n);if(i===`write-capable`)return`write-capable`;if(r.hasUnsupportedSyntax||i===`unknown`)return`unknown`;i===`read-only`&&(a=!0)}return a?`read-only`:`unknown`}function Ki(e,t={}){return Gi(e,t,/* @__PURE__ */ new Set)}function qi(e,t={},n=/* @__PURE__ */ new Set){return di(e).some(e=>{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return qi(e,t,n)}finally{n.delete(r)}}let i=Vi(e);return i===void 0?gi(e)||_i(e)||vi(e)||Ci(e):qi(i,t,n)})}function Ji(e,t={},n=/* @__PURE__ */ new Set){return di(e).some(e=>{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Ji(e,t,n)}finally{n.delete(r)}}let i=Vi(e);return i===void 0?yi(e)||bi(e)||xi(e)||wi(e):Ji(i,t,n)})}function Yi(e,t={},n=/* @__PURE__ */ new Set){return di(e).some(e=>{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Yi(e,t,n)}finally{n.delete(r)}}let i=Vi(e);if(i!==void 0)return Yi(i,t,n);if(Si(e))return!0;let[a,o]=e;return a===`vp`&&o===`check`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))})}function Xi(e,t,n,r){return t&&fi(e,t,n)?!0:r(e)}function Zi(e,t,n,r,i){let a=Xi(t,r,e,t=>qi(t,e)),o=Xi(t,i,e,t=>Ji(t,e)),s=Yi(t,e);return a&&o?[{capability:`format`,capabilities:[`format`,`lint`],scriptName:n}]:a&&!s?[{capability:`format`,scriptName:n}]:o&&!s?[{capability:`lint`,scriptName:n}]:s?[{capability:`autofix`,scriptName:n}]:[{capability:`typecheck`,capabilities:[],scriptName:n}]}function Qi(e,t){return qi(t[e],t)?{capability:`format`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function $i(e,t){return Ji(t[e],t)?{capability:`lint`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function ea(e,t,n){let r=[];return e&&r.push(Qi(e,n)),t&&r.push($i(t,n)),r}function ta(e,t,n,r,i){r&&pi(t,n,r)&&e.push(Qi(r,t)),i&&mi(t,n,i)&&e.push($i(i,t))}function na(e){let t=e.fix?`fix`:e[`check:fix`]?`check:fix`:void 0,n=Br(e,`fix`),r=Vr(e,`fix`);if(!t)return ea(n,r,e);let i=Zi(e,e[t]||``,t,n,r);return ta(i,e,t,n,r),i}function ra(e){let t=[],n=Br(e,`check`),r=Vr(e,`check`);return n&&t.push({capability:`format`,scriptName:n}),r&&t.push({capability:`lint`,scriptName:r}),t}function ia(e,t){return t===`fix`?na(e):ra(e)}var aa=class{id=`npm-scripts`;name=`package.json scripts`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson?.scripts;if(!t||Object.keys(t).length===0)return{detected:!1,reason:`no scripts declared in package.json`};let n=ia(t,`fix`),r=ia(t,`check`),i=[...n,...r];return i.length>0?{detected:!0,reason:`found supported scripts: ${Array.from(new Set(i.map(e=>`"${e.scriptName}"`))).join(`, `)}`}:{detected:!1,reason:`no supported autofix or check scripts found in package.json`}}plan(e,t){let n=ia(e.jsEnv?.packageJson?.scripts||{},t),r=cn(e.jsPm||`npm`);return n.map(n=>({id:`script-${n.scriptName}`,toolId:this.id,capability:n.capability,capabilities:n.capabilities,executable:r,args:[`run`,n.scriptName],cwd:e.cwd,mode:t,description:`package.json script: ${r} run ${n.scriptName}`}))}};function oa(e,t){return e?!!(e.dependencies?.[t]||e.devDependencies?.[t]||e.peerDependencies?.[t]||e.optionalDependencies?.[t]):!1}function sa(e,t){for(let n of t)if(f.existsSync(p.join(e,n)))return!0;return!1}var ca=class{id=`vite-plus`;name=`Vite+`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sn(t),r=sa(e.cwd,[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.cjs`]);return n||r&&t?.scripts&&Object.values(t.scripts).some(e=>e.includes(`vp `))?{detected:!0,reason:`Vite+ dependency and/or configuration detected`}:{detected:!1,reason:`no Vite+ dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`vite-plus-fmt`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp fmt`},{id:`vite-plus-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`,`--fix`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp lint --fix`}]:[{id:`vite-plus-fmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`,`--check`],cwd:e.cwd,mode:`check`,description:`Vite+: vp fmt --check`},{id:`vite-plus-lint`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`],cwd:e.cwd,mode:`check`,description:`Vite+: vp lint`}]}},la=class{id=`biome`;name=`Biome`;capabilities=[`format`,`lint`,`assist`];detect(e){let t=e.jsEnv?.packageJson,n=oa(t,`@biomejs/biome`),r=sa(e.cwd,[`biome.json`,`biome.jsonc`]);return n&&r?{detected:!0,reason:`Biome dependency and configuration detected`}:r?{detected:!0,reason:`Biome configuration detected`}:n?{detected:!1,reason:`Biome dependency present without configuration file`}:{detected:!1,reason:`no Biome dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`biome-format-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: format --write .`},{id:`biome-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: lint --write .`},{id:`biome-assist-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--write`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: safe assist actions (--write)`}]:[{id:`biome-format-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: format .`},{id:`biome-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: lint .`},{id:`biome-assist-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: check assist actions`}]}},ua=class{id=`prettier`;name=`Prettier`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=oa(t,`prettier`),r=!!t?.prettier,i=sa(e.cwd,[`.prettierrc`,`.prettierrc.json`,`.prettierrc.yml`,`.prettierrc.yaml`,`.prettierrc.json5`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`]);return n&&(r||i)?{detected:!0,reason:`Prettier dependency and configuration detected`}:r||i?{detected:!0,reason:`Prettier configuration detected`}:n?{detected:!1,reason:`Prettier dependency present without configuration`}:{detected:!1,reason:`no Prettier dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`prettier-format`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Prettier: format`}]:[{id:`prettier-check`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Prettier: format check`}]}},da=class{id=`eslint`;name=`ESLint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=oa(t,`eslint`),r=!!t?.eslintConfig,i=sa(e.cwd,[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yaml`,`.eslintrc.yml`]);return n&&(r||i)?{detected:!0,reason:`ESLint dependency and configuration detected`}:r||i?{detected:!0,reason:`ESLint configuration detected`}:n?{detected:!1,reason:`ESLint dependency present without configuration`}:{detected:!1,reason:`no ESLint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`eslint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`ESLint: lint autofix`}]:[{id:`eslint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`ESLint: lint check`}]}},fa=class{id=`oxlint`;name=`Oxlint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=oa(t,`oxlint`),r=sa(e.cwd,[`.oxlintrc.json`,`oxlint.json`,`oxlint.config.ts`,`oxlint.config.js`]);return n&&r?{detected:!0,reason:`Oxlint dependency and configuration detected`}:r?{detected:!0,reason:`Oxlint configuration detected`}:n?{detected:!1,reason:`Oxlint dependency present without configuration`}:{detected:!1,reason:`no Oxlint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxlint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxlint: lint autofix`}]:[{id:`oxlint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`Oxlint: lint check`}]}},pa=class{id=`oxfmt`;name=`Oxfmt`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=oa(t,`oxfmt`),r=sa(e.cwd,[`.oxfmtrc.json`,`oxfmt.json`,`oxfmt.config.ts`,`oxfmt.config.js`]);return n&&r?{detected:!0,reason:`Oxfmt dependency and configuration detected`}:r?{detected:!0,reason:`Oxfmt configuration detected`}:n?{detected:!1,reason:`Oxfmt dependency present without configuration`}:{detected:!1,reason:`no Oxfmt dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxfmt-format`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxfmt: format`}]:[{id:`oxfmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Oxfmt: format check`}]}},ma=class{id=`javascript`;name=`JavaScript/TypeScript`;scriptAdapter=new aa;vitePlusAdapter=new ca;biomeAdapter=new la;prettierAdapter=new ua;eslintAdapter=new da;oxlintAdapter=new fa;oxfmtAdapter=new pa;detect(e){return!!e.jsEnv?.hasPackageJson}getAdapters(e){return[this.scriptAdapter,this.vitePlusAdapter,this.biomeAdapter,this.oxfmtAdapter,this.prettierAdapter,this.oxlintAdapter,this.eslintAdapter]}},ha=class{id=`ruff`;name=`Ruff`;capabilities=[`lint`,`format`];detect(e){return e.hasPythonSource??or(e.cwd)?{detected:!0,reason:`default Python toolchain`}:{detected:!1,reason:`no Python source files detected`}}plan(e,t){let n=[];return t===`fix`?n.push({id:`ruff-lint-fix`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: lint autofix`},{id:`ruff-format`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: format`}):n.push({id:`ruff-lint-check`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: lint check`},{id:`ruff-format-check`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: format check`}),n}},ga=class{id=`python`;name=`Python`;ruffAdapter=new ha;detect(e){return e.hasPythonSource??or(e.cwd)}getAdapters(e){return[this.ruffAdapter]}},_a=class{providers=/* @__PURE__ */ new Map;standaloneAdapters=/* @__PURE__ */ new Map;registerProvider(e){this.providers.set(e.id,e)}getProvider(e){return this.providers.get(e)}getProviders(){return Array.from(this.providers.values())}registerAdapter(e){this.standaloneAdapters.set(e.id,e)}getAdapter(e){return this.standaloneAdapters.get(e)}getStandaloneAdapters(){return Array.from(this.standaloneAdapters.values())}clear(){this.providers.clear(),this.standaloneAdapters.clear()}};function va(){let e=new _a;return e.registerProvider(new ga),e.registerProvider(new ma),e}const ya=va();async function ba(e,t=process.cwd()){let n=`${e.command} ${e.args.join(` `)}`.trim();if(en(`Installing JS dependencies: ${n}`),await Yt(e.command,e.args,{cwd:t,ignoreReturnCode:!0})!==0)throw Error(`JS dependency installation failed executing "${n}". Check dependency constraints or lockfile compatibility.`)}async function xa(e=process.cwd()){let t=fn(e);if(!t.hasPackageJson){en(`No package.json found. Skipping scripts.`);return}if(t.packageJsonError)throw Error(t.packageJsonError);let n=cn(process.env.PACKAGE_MANAGER||_n(t).name),r=(await Ir(ya,{cwd:e,jsEnv:t,jsPm:n,hasPythonSource:!1},`fix`)).tasks.filter(e=>e.toolId!==`ruff`);if(r.length===0){en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`);return}await ba(vn(n),e);let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}}async function Sa(e,t,n=process.cwd()){let r=`${e} ${t.join(` `)}`.trim();if(en(`Executing: ${r}`),await Yt(e,t,{cwd:n,ignoreReturnCode:!0})!==0)throw Error(`Python command "${r}" failed. Check Python environment and dependency configuration.`)}async function Ca(e,t=process.cwd()){Dr(e,`Invalid Python environment: "pmInfo" must be an object`);let n=e.name===`pip`?`pip`:e.name;if(!await Vt(n,!1)&&!e.isStandalone){let e=`Required Python package manager '${n}' is not available in PATH.`;throw Error(e)}if(!e.isStandalone&&e.installCommands.length>0){let n=e.installCommands;en(`Installing Python dependencies: ${n.map(e=>`${e.executable} ${e.args.join(` `)}`).join(` && `)}`);for(let{executable:e,args:r}of n)await Sa(e,r,t)}}async function wa(e=process.cwd(),t,n){if(!(t??or(e)))return;let r;if(n)r=n;else{if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);r=(await Ir(ya,{cwd:e,hasPythonSource:!0},`fix`)).tasks.filter(e=>e.toolId===`ruff`)}let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}}async function Ta(e,t){if(process.env.JS_SETUP_OUTCOME===`failure`||process.env.NODE_SETUP_OUTCOME===`failure`||process.env.BUN_SETUP_OUTCOME===`failure`||process.env.PNPM_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`JavaScript runtime or package manager setup failed.`);try{if(t){let n=fn(e);if(!n.hasPackageJson)return en(`No package.json found. Skipping scripts.`),null;if(n.packageJsonError)throw Error(n.packageJsonError);if(t.length===0)return en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`),null;await ba(vn(cn(process.env.PACKAGE_MANAGER||_n(n).name)),e);let r=(await new Ar().executeTasks(t)).filter(e=>e.error);if(r.length>0){let e=r.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}return null}return await xa(e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Ea(e,t){if(process.env.PYTHON_SETUP_OUTCOME===`failure`||process.env.UV_SETUP_OUTCOME===`failure`||process.env.PY_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Python runtime or package manager setup failed.`);let n=t&&`pmInfo`in t?t.pmInfo:Tr(e,void 0,{ctx:t?.ctx,hasSource:t?.hasSource});if(!n)return null;try{return await Ca(n,e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Da(e,t,n){if(process.env.RUFF_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Ruff setup failed.`);try{return await wa(e,t,n),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Oa(e,t,n){let r=t??or(e);if(!r)return[];let i=[],a=ir(e),o=await Ea(e,{ctx:a,hasSource:!0,pmInfo:Tr(e,void 0,{ctx:a,hasSource:!0,isProject:!0})});o&&i.push(o);let s=await Da(e,r,n);return s&&i.push(s),i}async function ka(e=process.cwd()){let t=or(e),n;try{let r=fn(e),i={cwd:e,jsEnv:r,jsPm:cn(process.env.PACKAGE_MANAGER||_n(r).name),hasPythonSource:t};n=await Ir(ya,i,`fix`),en(n.summary)}catch{}let r=[],i=n?n.tasks.filter(e=>e.toolId!==`ruff`):void 0,a=n?n.tasks.filter(e=>e.toolId===`ruff`):void 0,o=await Ta(e,i);o&&r.push(o);let s=await Oa(e,t,a);r.push(...s),r.length>0&&(Zt(`Failed to run scripts: ${r.map(e=>e.message).join(` -`)}`),process.env.NODE_ENV!==`test`&&process.exit(1))}process.env.NODE_ENV!==`test`&&Or(import.meta.url)&&ka();export{xa as executeJsWorkflow,Ca as executePythonWorkflow,wa as executeRuffAutofix,ka as run,cn as sanitizePackageManager}; \ No newline at end of file +`;)n++;return n>t?n-1:t}function Wr(e,t){return t.inSingleQuote||t.inDoubleQuote||t.isEscaped?!1:e.length===0||/\s/.test(e[e.length-1])}function Gr(e,t){return t.isEscaped=!1,{ch:e,advance:!0}}function Kr(e,t,n,r){let i=e[t];if(n.isEscaped)return{newCmd:r+Gr(i,n).ch,nextIndex:t,sepLen:0};if(i===`\\`&&!n.inSingleQuote)return n.isEscaped=!0,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`'`&&!n.inDoubleQuote)return n.inSingleQuote=!n.inSingleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`"`&&!n.inSingleQuote)return n.inDoubleQuote=!n.inDoubleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`#`&&Wr(r,n))return{newCmd:r,nextIndex:Ur(e,t),sepLen:0};let a=Hr(e,t,n);return{newCmd:r+(a===0?i:``),nextIndex:t,sepLen:a}}function qr(e){let t=[],n=``,r={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1,hasSyntaxError:!1};for(let i=0;i0?(n.trim()&&t.push(n.trim()),n=``,i+=a.sepLen-1):(n=a.newCmd,i=a.nextIndex)}return(r.inSingleQuote||r.inDoubleQuote||r.isEscaped)&&(r.hasSyntaxError=!0),n.trim()&&t.push(n.trim()),{commands:t,hasSyntaxError:r.hasSyntaxError}}function Jr(e){return qr(e).commands}function Yr(e,t,n){return t.isEscaped=!1,n+e}function Xr(e,t){return e===`'`&&!t.inDoubleQuote?(t.inSingleQuote=!t.inSingleQuote,!0):e===`"`&&!t.inSingleQuote&&(t.inDoubleQuote=!t.inDoubleQuote,!0)}const Zr=/* @__PURE__ */ new Set([`@`,`*`,`#`,`?`,`-`,`$`,`!`,`0`]);function Qr(e,t,n){if(n.inSingleQuote||n.isEscaped||e[t]!==`$`||t+1>=e.length)return!1;let r=e[t+1];return!!(r===`{`||Zr.has(r)||r>=`1`&&r<=`9`||r===`_`||r>=`a`&&r<=`z`||r>=`A`&&r<=`Z`)}function $r(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped||e[t]!==`&`)return!1;let r=t>0?e[t-1]:``,i=t+1`}function ei(e,t,n){if(n.inSingleQuote||n.isEscaped)return!1;let r=e[t];return r==="`"||r===`$`&&t+1`)&&t+1`||r===`<`||r===`&`&&t+1`}function ri(e,t,n){return $r(e,t,n.state)||Qr(e,t,n.state)||ei(e,t,n.state)||ti(e,t,n.state)?(n.inspection.hasUnsupportedSyntax=!0,!0):ni(e,t,n.state)?(n.inspection.hasRedirection=!0,n.inspection.hasUnsupportedSyntax=!0,!0):!1}function ii(e,t,n,r){let i=e[t];return n.state.isEscaped?{word:Yr(i,n.state,r),hasChars:!0,skipped:!1}:i===`\\`&&!n.state.inSingleQuote?(n.state.isEscaped=!0,{word:r,hasChars:!1,skipped:!0}):(ri(e,t,n),Xr(i,n.state)?{word:r,hasChars:!0,skipped:!0}:{word:r+i,hasChars:!0,skipped:!1})}function ai(e){let t={tokens:[],hasUnsupportedSyntax:!1,hasRedirection:!1},n={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1},r={inspection:t,state:n},i=``,a=!1;for(let o=0;o0&&n.push(t)}return n}function fi(e,t,n={},r=/* @__PURE__ */ new Set){if(!e||!t)return!1;let i=di(n[e]===void 0?e:n[e]);for(let e of i){if(ui(e,t))return!0;let i=Bi(e);if(i){if(i===t)return!0;if(!r.has(i)&&n[i]!==void 0){r.add(i);try{if(fi(n[i],t,n,r))return!0}finally{r.delete(i)}}}let a=Vi(e);if(a!==void 0&&fi(a,t,n,r))return!0}return!1}function pi(e,t,n){return!n||n===t?!1:!fi(e[t]||``,n,e)}function mi(e,t,n){return!n||n===t?!1:!fi(e[t]||``,n,e)}function hi(e){let[t]=e;return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||(e===`--fix`||e.startsWith(`--fix=`))&&(t!==`eslint`||e!==`--fix-dry-run`))}function gi(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function _i(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function vi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function yi(e){let[t]=e;return t===`eslint`&&e.some(e=>(e===`--fix`||e.startsWith(`--fix=`))&&e!==`--fix-dry-run`)}function bi(e){let[t]=e;return t===`oxlint`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function xi(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Si(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Ci(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:!e.some(e=>e===`--check`||e===`-c`)}function wi(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Ti(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)&&e!==`--fix-dry-run`||e===`-o`||e.startsWith(`-o=`)||e===`--output-file`||e.startsWith(`--output-file=`)||e===`--cache`||e===`--cache-file`||e.startsWith(`--cache-file=`)||e===`--cache-location`||e.startsWith(`--cache-location=`))}function Ei(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--cache`||e===`--cache-location`||e.startsWith(`--cache-location=`)||e===`--insert-pragma`)}function Di(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`)||e===`--reporter-file`||e.startsWith(`--reporter-file=`)||e===`--log-file`||e.startsWith(`--log-file=`))}function Oi(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)||e===`--fix-suggestions`||e===`--fix-dangerously`||e===`--init`)}function ki(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--init`||e===`--migrate`||e.startsWith(`--migrate=`))}function Ai(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`--check`||e===`-c`||e===`--list-different`||e===`-l`)&&!Ei(e)}function ji(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`--check`||e===`-c`)&&!ki(e)}function Mi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:!Di(e)}function Ni(e){let[t]=e;return t===`eslint`&&!Ti(e)}function Pi(e){let[t]=e;return t===`oxlint`&&!Oi(e)}function Fi(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:!Di(e)}function Ii(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:!Di(e)}function Li(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:e.some(e=>e===`--check`||e===`-c`)&&!ki(e)}function Ri(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:!Oi(e)}function zi(e){let[t,n]=e;return t!==`vp`||n!==`check`?!1:!e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Bi(e){if(e.length===0)return;let[t,n,r]=e;if((t===`npm`||t===`pnpm`||t===`yarn`||t===`bun`)&&n===`run`&&r)return r;if((t===`pnpm`||t===`bun`||t===`yarn`)&&n&&!n.startsWith(`-`))return n}function Vi(e){if(e.length>=3&&(e[0]===`sh`||e[0]===`bash`)&&e[1]===`-c`)return e[2]}function Hi(e){return gi(e)||_i(e)||vi(e)||yi(e)||bi(e)||xi(e)||Si(e)||Ci(e)||wi(e)}function Ui(e){return Ai(e)||ji(e)||Mi(e)||Ni(e)||Pi(e)||Fi(e)||Ii(e)||Li(e)||Ri(e)||zi(e)}function Wi(e,t,n){if(e.length===0)return`unknown`;if(hi(e))return`write-capable`;let r=Vi(e);if(r!==void 0)return Gi(r,t,n);let i=Bi(e);if(i){if(n.has(i))return`unknown`;let e=t[i];if(!e)return`unknown`;n.add(i);try{return Gi(e,t,n)}finally{n.delete(i)}}return Hi(e)?`write-capable`:Ui(e)?`read-only`:`unknown`}function Gi(e,t,n){let r=qr(e);if(r.hasSyntaxError)return`unknown`;let{commands:i}=r;if(i.length===0)return`unknown`;let a=!1;for(let e of i){let r=ai(e),i=Wi(li(r.tokens),t,n);if(i===`write-capable`)return`write-capable`;if(r.hasUnsupportedSyntax||i===`unknown`)return`unknown`;i===`read-only`&&(a=!0)}return a?`read-only`:`unknown`}function Ki(e,t={}){return Gi(e,t,/* @__PURE__ */ new Set)}function qi(e,t={},n=/* @__PURE__ */ new Set){return di(e).some(e=>{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return qi(e,t,n)}finally{n.delete(r)}}let i=Vi(e);return i===void 0?gi(e)||_i(e)||vi(e)||Ci(e):qi(i,t,n)})}function Ji(e,t={},n=/* @__PURE__ */ new Set){return di(e).some(e=>{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Ji(e,t,n)}finally{n.delete(r)}}let i=Vi(e);return i===void 0?yi(e)||bi(e)||xi(e)||wi(e):Ji(i,t,n)})}function Yi(e,t={},n=/* @__PURE__ */ new Set){return di(e).some(e=>{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Yi(e,t,n)}finally{n.delete(r)}}let i=Vi(e);if(i!==void 0)return Yi(i,t,n);if(Si(e))return!0;let[a,o]=e;return a===`vp`&&o===`check`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))})}function Xi(e,t,n,r){return t&&fi(e,t,n)?!0:r(e)}function Zi(e,t,n,r,i){let a=Xi(t,r,e,t=>qi(t,e)),o=Xi(t,i,e,t=>Ji(t,e)),s=Yi(t,e);return a&&o?[{capability:`format`,capabilities:[`format`,`lint`],scriptName:n}]:a&&!s?[{capability:`format`,scriptName:n}]:o&&!s?[{capability:`lint`,scriptName:n}]:s?[{capability:`autofix`,scriptName:n}]:[{capability:`typecheck`,capabilities:[],scriptName:n}]}function Qi(e,t){return qi(t[e],t)?{capability:`format`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function $i(e,t){return Ji(t[e],t)?{capability:`lint`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function ea(e,t,n){let r=[];return e&&r.push(Qi(e,n)),t&&r.push($i(t,n)),r}function ta(e,t,n,r,i){r&&pi(t,n,r)&&e.push(Qi(r,t)),i&&mi(t,n,i)&&e.push($i(i,t))}function na(e){let t=e.fix?`fix`:e[`check:fix`]?`check:fix`:void 0,n=Br(e,`fix`),r=Vr(e,`fix`);if(!t)return ea(n,r,e);let i=Zi(e,e[t]||``,t,n,r);return ta(i,e,t,n,r),i}function ra(e){let t=[],n=Br(e,`check`),r=Vr(e,`check`);return n&&t.push({capability:`format`,scriptName:n}),r&&t.push({capability:`lint`,scriptName:r}),t}function ia(e,t){return t===`fix`?na(e):ra(e)}var aa=class{id=`npm-scripts`;name=`package.json scripts`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson?.scripts;if(!t||Object.keys(t).length===0)return{detected:!1,reason:`no scripts declared in package.json`};let n=ia(t,`fix`),r=ia(t,`check`),i=[...n,...r];return i.length>0?{detected:!0,reason:`found supported scripts: ${Array.from(new Set(i.map(e=>`"${e.scriptName}"`))).join(`, `)}`}:{detected:!1,reason:`no supported autofix or check scripts found in package.json`}}plan(e,t){let n=ia(e.jsEnv?.packageJson?.scripts||{},t),r=cn(e.jsPm||`npm`);return n.map(n=>({id:`script-${n.scriptName}`,toolId:this.id,capability:n.capability,capabilities:n.capabilities,executable:r,args:[`run`,n.scriptName],cwd:e.cwd,mode:t,description:`package.json script: ${r} run ${n.scriptName}`}))}};function oa(e){return e?Object.values(e).some(e=>di(e).some(e=>e[0]===`vp`)):!1}function sa(e,t){return e?!!(e.dependencies?.[t]||e.devDependencies?.[t]||e.peerDependencies?.[t]||e.optionalDependencies?.[t]):!1}function ca(e,t){for(let n of t)if(f.existsSync(p.join(e,n)))return!0;return!1}var la=class{id=`vite-plus`;name=`Vite+`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sn(t),r=ca(e.cwd,[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.cjs`]);return n||r&&oa(t?.scripts)?{detected:!0,reason:`Vite+ dependency and/or configuration detected`}:{detected:!1,reason:`no Vite+ dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`vite-plus-fmt`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp fmt`},{id:`vite-plus-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`,`--fix`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp lint --fix`}]:[{id:`vite-plus-fmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`,`--check`],cwd:e.cwd,mode:`check`,description:`Vite+: vp fmt --check`},{id:`vite-plus-lint`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`],cwd:e.cwd,mode:`check`,description:`Vite+: vp lint`}]}},ua=class{id=`biome`;name=`Biome`;capabilities=[`format`,`lint`,`assist`];detect(e){let t=e.jsEnv?.packageJson,n=sa(t,`@biomejs/biome`),r=ca(e.cwd,[`biome.json`,`biome.jsonc`]);return n&&r?{detected:!0,reason:`Biome dependency and configuration detected`}:r?{detected:!0,reason:`Biome configuration detected`}:n?{detected:!1,reason:`Biome dependency present without configuration file`}:{detected:!1,reason:`no Biome dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`biome-format-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: format --write .`},{id:`biome-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: lint --write .`},{id:`biome-assist-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--write`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: safe assist actions (--write)`}]:[{id:`biome-format-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: format .`},{id:`biome-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: lint .`},{id:`biome-assist-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: check assist actions`}]}},da=class{id=`prettier`;name=`Prettier`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=sa(t,`prettier`),r=!!t?.prettier,i=ca(e.cwd,[`.prettierrc`,`.prettierrc.json`,`.prettierrc.yml`,`.prettierrc.yaml`,`.prettierrc.json5`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`]);return n&&(r||i)?{detected:!0,reason:`Prettier dependency and configuration detected`}:r||i?{detected:!0,reason:`Prettier configuration detected`}:n?{detected:!1,reason:`Prettier dependency present without configuration`}:{detected:!1,reason:`no Prettier dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`prettier-format`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Prettier: format`}]:[{id:`prettier-check`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Prettier: format check`}]}},fa=class{id=`eslint`;name=`ESLint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sa(t,`eslint`),r=!!t?.eslintConfig,i=ca(e.cwd,[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yaml`,`.eslintrc.yml`]);return n&&(r||i)?{detected:!0,reason:`ESLint dependency and configuration detected`}:r||i?{detected:!0,reason:`ESLint configuration detected`}:n?{detected:!1,reason:`ESLint dependency present without configuration`}:{detected:!1,reason:`no ESLint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`eslint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`ESLint: lint autofix`}]:[{id:`eslint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`ESLint: lint check`}]}},pa=class{id=`oxlint`;name=`Oxlint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sa(t,`oxlint`),r=ca(e.cwd,[`.oxlintrc.json`,`oxlint.json`,`oxlint.config.ts`,`oxlint.config.js`]);return n&&r?{detected:!0,reason:`Oxlint dependency and configuration detected`}:r?{detected:!0,reason:`Oxlint configuration detected`}:n?{detected:!1,reason:`Oxlint dependency present without configuration`}:{detected:!1,reason:`no Oxlint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxlint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxlint: lint autofix`}]:[{id:`oxlint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`Oxlint: lint check`}]}},ma=class{id=`oxfmt`;name=`Oxfmt`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=sa(t,`oxfmt`),r=ca(e.cwd,[`.oxfmtrc.json`,`oxfmt.json`,`oxfmt.config.ts`,`oxfmt.config.js`]);return n&&r?{detected:!0,reason:`Oxfmt dependency and configuration detected`}:r?{detected:!0,reason:`Oxfmt configuration detected`}:n?{detected:!1,reason:`Oxfmt dependency present without configuration`}:{detected:!1,reason:`no Oxfmt dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxfmt-format`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxfmt: format`}]:[{id:`oxfmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Oxfmt: format check`}]}},ha=class{id=`javascript`;name=`JavaScript/TypeScript`;scriptAdapter=new aa;vitePlusAdapter=new la;biomeAdapter=new ua;prettierAdapter=new da;eslintAdapter=new fa;oxlintAdapter=new pa;oxfmtAdapter=new ma;detect(e){return!!e.jsEnv?.hasPackageJson}getAdapters(e){return[this.scriptAdapter,this.vitePlusAdapter,this.biomeAdapter,this.oxfmtAdapter,this.prettierAdapter,this.oxlintAdapter,this.eslintAdapter]}},ga=class{id=`ruff`;name=`Ruff`;capabilities=[`lint`,`format`];detect(e){return e.hasPythonSource??or(e.cwd)?{detected:!0,reason:`default Python toolchain`}:{detected:!1,reason:`no Python source files detected`}}plan(e,t){let n=[];return t===`fix`?n.push({id:`ruff-lint-fix`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: lint autofix`},{id:`ruff-format`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: format`}):n.push({id:`ruff-lint-check`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: lint check`},{id:`ruff-format-check`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: format check`}),n}},_a=class{id=`python`;name=`Python`;ruffAdapter=new ga;detect(e){return e.hasPythonSource??or(e.cwd)}getAdapters(e){return[this.ruffAdapter]}},va=class{providers=/* @__PURE__ */ new Map;standaloneAdapters=/* @__PURE__ */ new Map;registerProvider(e){this.providers.set(e.id,e)}getProvider(e){return this.providers.get(e)}getProviders(){return Array.from(this.providers.values())}registerAdapter(e){this.standaloneAdapters.set(e.id,e)}getAdapter(e){return this.standaloneAdapters.get(e)}getStandaloneAdapters(){return Array.from(this.standaloneAdapters.values())}clear(){this.providers.clear(),this.standaloneAdapters.clear()}};function ya(){let e=new va;return e.registerProvider(new _a),e.registerProvider(new ha),e}const ba=ya();async function xa(e,t=process.cwd()){let n=`${e.command} ${e.args.join(` `)}`.trim();if(en(`Installing JS dependencies: ${n}`),await Yt(e.command,e.args,{cwd:t,ignoreReturnCode:!0})!==0)throw Error(`JS dependency installation failed executing "${n}". Check dependency constraints or lockfile compatibility.`)}async function Sa(e=process.cwd()){let t=fn(e);if(!t.hasPackageJson){en(`No package.json found. Skipping scripts.`);return}if(t.packageJsonError)throw Error(t.packageJsonError);let n=cn(process.env.PACKAGE_MANAGER||_n(t).name),r=(await Ir(ba,{cwd:e,jsEnv:t,jsPm:n,hasPythonSource:!1},`fix`)).tasks.filter(e=>e.toolId!==`ruff`);if(r.length===0){en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`);return}await xa(vn(n),e);let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}}async function Ca(e,t,n=process.cwd()){let r=`${e} ${t.join(` `)}`.trim();if(en(`Executing: ${r}`),await Yt(e,t,{cwd:n,ignoreReturnCode:!0})!==0)throw Error(`Python command "${r}" failed. Check Python environment and dependency configuration.`)}async function wa(e,t=process.cwd()){Dr(e,`Invalid Python environment: "pmInfo" must be an object`);let n=e.name===`pip`?`pip`:e.name;if(!await Vt(n,!1)&&!e.isStandalone){let e=`Required Python package manager '${n}' is not available in PATH.`;throw Error(e)}if(!e.isStandalone&&e.installCommands.length>0){let n=e.installCommands;en(`Installing Python dependencies: ${n.map(e=>`${e.executable} ${e.args.join(` `)}`).join(` && `)}`);for(let{executable:e,args:r}of n)await Ca(e,r,t)}}async function Ta(e=process.cwd(),t,n){if(!(t??or(e)))return;let r;if(n)r=n;else{if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);r=(await Ir(ba,{cwd:e,hasPythonSource:!0},`fix`)).tasks.filter(e=>e.toolId===`ruff`)}let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}}async function Ea(e,t){if(process.env.JS_SETUP_OUTCOME===`failure`||process.env.NODE_SETUP_OUTCOME===`failure`||process.env.BUN_SETUP_OUTCOME===`failure`||process.env.PNPM_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`JavaScript runtime or package manager setup failed.`);try{if(t){let n=fn(e);if(!n.hasPackageJson)return en(`No package.json found. Skipping scripts.`),null;if(n.packageJsonError)throw Error(n.packageJsonError);if(t.length===0)return en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`),null;await xa(vn(cn(process.env.PACKAGE_MANAGER||_n(n).name)),e);let r=(await new Ar().executeTasks(t)).filter(e=>e.error);if(r.length>0){let e=r.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}return null}return await Sa(e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Da(e,t){if(process.env.PYTHON_SETUP_OUTCOME===`failure`||process.env.UV_SETUP_OUTCOME===`failure`||process.env.PY_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Python runtime or package manager setup failed.`);let n=t&&`pmInfo`in t?t.pmInfo:Tr(e,void 0,{ctx:t?.ctx,hasSource:t?.hasSource});if(!n)return null;try{return await wa(n,e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Oa(e,t,n){if(process.env.RUFF_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Ruff setup failed.`);try{return await Ta(e,t,n),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function ka(e,t,n){let r=t??or(e);if(!r)return[];let i=[],a=ir(e),o=await Da(e,{ctx:a,hasSource:!0,pmInfo:Tr(e,void 0,{ctx:a,hasSource:!0,isProject:!0})});o&&i.push(o);let s=await Oa(e,r,n);return s&&i.push(s),i}async function Aa(e=process.cwd()){let t=or(e),n;try{let r=fn(e),i={cwd:e,jsEnv:r,jsPm:cn(process.env.PACKAGE_MANAGER||_n(r).name),hasPythonSource:t};n=await Ir(ba,i,`fix`),en(n.summary)}catch{}let r=[],i=n?n.tasks.filter(e=>e.toolId!==`ruff`):void 0,a=n?n.tasks.filter(e=>e.toolId===`ruff`):void 0,o=await Ea(e,i);o&&r.push(o);let s=await ka(e,t,a);r.push(...s),r.length>0&&(Zt(`Failed to run scripts: ${r.map(e=>e.message).join(` +`)}`),process.env.NODE_ENV!==`test`&&process.exit(1))}process.env.NODE_ENV!==`test`&&Or(import.meta.url)&&Aa();export{Sa as executeJsWorkflow,wa as executePythonWorkflow,Ta as executeRuffAutofix,Aa as run,cn as sanitizePackageManager}; \ No newline at end of file diff --git a/src/autofix/adapters/javascript/tools.ts b/src/autofix/adapters/javascript/tools.ts index 69885a22..1452499e 100644 --- a/src/autofix/adapters/javascript/tools.ts +++ b/src/autofix/adapters/javascript/tools.ts @@ -11,6 +11,15 @@ import type { } from "../../types.js"; import { hasVitePlusDependency, type JsPackageManifest } from "../../../javascript-env.js"; +import { parseCommandInvocations } from "./script-adapter.js"; + +function hasVitePlusScript(scripts?: Record): boolean { + if (!scripts) return false; + return Object.values(scripts).some((scriptBody) => { + const invocations = parseCommandInvocations(scriptBody); + return invocations.some((tokens) => tokens[0] === "vp"); + }); +} function hasDependency(pkg: JsPackageManifest | undefined, depName: string): boolean { if (!pkg) return false; @@ -47,10 +56,7 @@ export class VitePlusAdapter implements ToolAdapter { "vite.config.cjs", ]); - if ( - hasDep || - (hasConfig && pkg?.scripts && Object.values(pkg.scripts).some((s) => s.includes("vp "))) - ) { + if (hasDep || (hasConfig && hasVitePlusScript(pkg?.scripts))) { return { detected: true, reason: "Vite+ dependency and/or configuration detected" }; } return { detected: false, reason: "no Vite+ dependency or configuration" }; diff --git a/src/autofix/planner.ts b/src/autofix/planner.ts index bc379347..eceb44f9 100644 --- a/src/autofix/planner.ts +++ b/src/autofix/planner.ts @@ -106,19 +106,32 @@ async function processCandidateTools( async function processStandaloneAdapters( registry: AutofixRegistry, + coveredCapabilities: Set, context: ProjectContext, mode: ExecutionMode, selectedTools: Array<{ id: string; name: string; reason?: string }>, + skippedTools: Array<{ id: string; name: string; reason: string }>, tasks: ExecutionTask[], ): Promise { + const candidateTools: CandidateTool[] = []; for (const adapter of registry.getStandaloneAdapters()) { const result = await adapter.detect(context); if (result.detected) { - selectedTools.push({ id: adapter.id, name: adapter.name, reason: result.reason }); - const toolTasks = await adapter.plan(context, mode); - tasks.push(...toolTasks); + candidateTools.push({ adapter, reason: result.reason }); + } else if (result.reason && !result.reason.startsWith("no ")) { + skippedTools.push({ id: adapter.id, name: adapter.name, reason: result.reason }); } } + + await processCandidateTools( + candidateTools, + coveredCapabilities, + context, + mode, + selectedTools, + skippedTools, + tasks, + ); } function deduplicateTasks(tasks: ExecutionTask[]): ExecutionTask[] { @@ -161,7 +174,7 @@ export async function planExecution( const tasks: ExecutionTask[] = []; const providers = registry.getProviders(); - const coveredCapabilities = new Map>(); + const coveredCapabilities = new Set(); for (const provider of providers) { const isDetected = await provider.detect(effectiveContext); @@ -169,9 +182,6 @@ export async function planExecution( continue; } - const providerCapabilities = new Set(); - coveredCapabilities.set(provider.id, providerCapabilities); - const adapters = provider.getAdapters(effectiveContext); const candidateTools: CandidateTool[] = []; @@ -187,7 +197,7 @@ export async function planExecution( await processCandidateTools( candidateTools, - providerCapabilities, + coveredCapabilities, effectiveContext, mode, selectedTools, @@ -196,7 +206,15 @@ export async function planExecution( ); } - await processStandaloneAdapters(registry, effectiveContext, mode, selectedTools, tasks); + await processStandaloneAdapters( + registry, + coveredCapabilities, + effectiveContext, + mode, + selectedTools, + skippedTools, + tasks, + ); const deduplicatedTasks = deduplicateTasks(tasks); diff --git a/tests/autofix-architecture.test.ts b/tests/autofix-architecture.test.ts index 862e9605..c0c52138 100644 --- a/tests/autofix-architecture.test.ts +++ b/tests/autofix-architecture.test.ts @@ -1668,6 +1668,379 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { }); }); + describe("Vite+ Detection & False-Positive Prevention", () => { + it("detects Vite+ when package script invokes vp command directly", async () => { + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + fmt: "vp fmt", + }, + }), + ); + fs.writeFileSync(path.join(tempDir, "vite.config.ts"), "export default {};"); + + const registry = createDefaultRegistry(); + const plan = await planExecution(registry, { cwd: tempDir }, "fix"); + // Script fmt runs, and VitePlusAdapter is detected (and fmt script covers format) + expect(plan.selectedTools.map((t) => t.id)).toContain("vite-plus"); + }); + + it("detects Vite+ when package script invokes vp in chained command or with env prefix", async () => { + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + build: "echo ready && vp build", + check: "NODE_ENV=production vp check", + }, + }), + ); + fs.writeFileSync(path.join(tempDir, "vite.config.ts"), "export default {};"); + + const registry = createDefaultRegistry(); + const plan = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(plan.selectedTools.map((t) => t.id)).toContain("vite-plus"); + expect(plan.tasks.map((t) => t.id)).toContain("vite-plus-fmt"); + expect(plan.tasks.map((t) => t.id)).toContain("vite-plus-lint-fix"); + }); + + it("prevents false positive when 'vp ' only appears inside echo or descriptive string", async () => { + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + help: 'echo "vp is not installed"', + }, + }), + ); + fs.writeFileSync(path.join(tempDir, "vite.config.ts"), "export default {};"); + + const registry = createDefaultRegistry(); + const plan = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(plan.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + expect(plan.tasks.map((t) => t.id)).not.toContain("vite-plus-fmt"); + expect(plan.tasks.map((t) => t.id)).not.toContain("vite-plus-lint-fix"); + }); + + it("prevents false positive when 'vp ' only appears in a comment", async () => { + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + test: "node test.js # vp fmt", + }, + }), + ); + fs.writeFileSync(path.join(tempDir, "vite.config.ts"), "export default {};"); + + const registry = createDefaultRegistry(); + const plan = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(plan.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + }); + + it("prevents false positive when 'vp' appears as an argument to an unrelated command", async () => { + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + search: "grep vp file.txt", + }, + }), + ); + fs.writeFileSync(path.join(tempDir, "vite.config.ts"), "export default {};"); + + const registry = createDefaultRegistry(); + const plan = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(plan.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + }); + + it("prevents false positive when project has vite.config.ts but scripts do not invoke vp", async () => { + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + build: "vite build", + test: "vitest run", + }, + }), + ); + fs.writeFileSync(path.join(tempDir, "vite.config.ts"), "export default {};"); + + const registry = createDefaultRegistry(); + const plan = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(plan.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + }); + }); + + describe("Standalone Adapter Conflict Resolution", () => { + it("skips a standalone adapter task when its capability is already covered by a regular adapter", async () => { + const registry = createDefaultRegistry(); + + class StandaloneFormatAdapter implements ToolAdapter { + id = "standalone-fmt"; + name = "Standalone Formatter"; + capabilities: ["format"] = ["format"]; + detect() { + return { detected: true, reason: "standalone formatter config detected" }; + } + plan(ctx: ProjectContext, mode: ExecutionMode): ExecutionTask[] { + return [ + { + id: "standalone-fmt-task", + toolId: this.id, + capability: "format", + executable: "standalone-fmt", + args: ["."], + cwd: ctx.cwd, + mode, + }, + ]; + } + } + + registry.registerAdapter(new StandaloneFormatAdapter()); + + // Configure explicit script covering format + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + "format:write": "prettier --write .", + }, + }), + ); + + const plan = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(plan.tasks.map((t) => t.id)).toEqual(["script-format:write"]); + expect(plan.skippedTools).toContainEqual( + expect.objectContaining({ + id: "standalone-fmt", + reason: "all capabilities already covered by higher priority tool", + }), + ); + }); + + it("skips a lower-priority adapter when a higher-priority standalone adapter ran first and covered the capability", async () => { + const customRegistry = new AutofixRegistry(); + + class StandaloneFormatAdapter implements ToolAdapter { + id = "standalone-fmt"; + name = "Standalone Formatter"; + capabilities: ["format"] = ["format"]; + detect() { + return { detected: true, reason: "standalone formatter config detected" }; + } + plan(ctx: ProjectContext, mode: ExecutionMode): ExecutionTask[] { + return [ + { + id: "standalone-fmt-task", + toolId: this.id, + capability: "format", + executable: "standalone-fmt", + args: ["."], + cwd: ctx.cwd, + mode, + }, + ]; + } + } + + // Test two standalone adapters where first standalone adapter conflicts with second standalone adapter: + class SecondStandaloneFormatAdapter implements ToolAdapter { + id = "second-fmt"; + name = "Second Formatter"; + capabilities: ["format"] = ["format"]; + detect() { + return { detected: true, reason: "second formatter config detected" }; + } + plan(ctx: ProjectContext, mode: ExecutionMode): ExecutionTask[] { + return [ + { + id: "second-fmt-task", + toolId: this.id, + capability: "format", + executable: "second-fmt", + args: ["."], + cwd: ctx.cwd, + mode, + }, + ]; + } + } + + customRegistry.registerAdapter(new StandaloneFormatAdapter()); + customRegistry.registerAdapter(new SecondStandaloneFormatAdapter()); + + const plan = await planExecution(customRegistry, { cwd: tempDir }, "fix"); + expect(plan.tasks.map((t) => t.id)).toEqual(["standalone-fmt-task"]); + expect(plan.skippedTools).toContainEqual( + expect.objectContaining({ + id: "second-fmt", + reason: "all capabilities already covered by higher priority tool", + }), + ); + }); + + it("retains tasks when standalone and regular adapters produce independent capabilities", async () => { + const registry = createDefaultRegistry(); + + class StandaloneTypecheckAdapter implements ToolAdapter { + id = "standalone-typecheck"; + name = "Standalone Typechecker"; + capabilities: ["typecheck"] = ["typecheck"]; + detect() { + return { detected: true, reason: "typecheck config detected" }; + } + plan(ctx: ProjectContext, mode: ExecutionMode): ExecutionTask[] { + return [ + { + id: "standalone-typecheck-task", + toolId: this.id, + capability: "typecheck", + executable: "tsc", + args: ["--noEmit"], + cwd: ctx.cwd, + mode, + }, + ]; + } + } + + registry.registerAdapter(new StandaloneTypecheckAdapter()); + + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + "format:write": "prettier --write .", + }, + }), + ); + + const plan = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(plan.tasks.map((t) => t.id)).toEqual([ + "script-format:write", + "standalone-typecheck-task", + ]); + expect(plan.selectedTools.map((t) => t.id)).toContain("standalone-typecheck"); + }); + + it("partially skips overlapping capabilities between standalone and regular adapters", async () => { + const registry = createDefaultRegistry(); + + class StandaloneMultiToolAdapter implements ToolAdapter { + id = "standalone-multi"; + name = "Standalone Multi Tool"; + capabilities: ["format", "assist"] = ["format", "assist"]; + detect() { + return { detected: true, reason: "multi tool config detected" }; + } + plan(ctx: ProjectContext, mode: ExecutionMode): ExecutionTask[] { + return [ + { + id: "standalone-multi-fmt", + toolId: this.id, + capability: "format", + executable: "standalone-multi", + args: ["fmt"], + cwd: ctx.cwd, + mode, + }, + { + id: "standalone-multi-assist", + toolId: this.id, + capability: "assist", + executable: "standalone-multi", + args: ["assist"], + cwd: ctx.cwd, + mode, + }, + ]; + } + } + + registry.registerAdapter(new StandaloneMultiToolAdapter()); + + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + "format:write": "prettier --write .", + }, + }), + ); + + const plan = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(plan.tasks.map((t) => t.id)).toEqual([ + "script-format:write", + "standalone-multi-assist", + ]); + expect(plan.skippedTools).toContainEqual( + expect.objectContaining({ + id: "standalone-multi", + reason: "partially skipped (format covered by higher priority tool)", + }), + ); + }); + + it("preserves task ID deduplication behavior", async () => { + const customRegistry = new AutofixRegistry(); + + class StandaloneAdapter1 implements ToolAdapter { + id = "adapter-1"; + name = "Adapter 1"; + capabilities: ["typecheck"] = ["typecheck"]; + detect() { + return { detected: true, reason: "adapter 1 detected" }; + } + plan(ctx: ProjectContext, mode: ExecutionMode): ExecutionTask[] { + return [ + { + id: "shared-task-id", + toolId: this.id, + capability: "typecheck", + executable: "check-1", + args: [], + cwd: ctx.cwd, + mode, + }, + ]; + } + } + + class StandaloneAdapter2 implements ToolAdapter { + id = "adapter-2"; + name = "Adapter 2"; + capabilities: ["assist"] = ["assist"]; + detect() { + return { detected: true, reason: "adapter 2 detected" }; + } + plan(ctx: ProjectContext, mode: ExecutionMode): ExecutionTask[] { + return [ + { + id: "shared-task-id", + toolId: this.id, + capability: "assist", + executable: "check-2", + args: [], + cwd: ctx.cwd, + mode, + }, + ]; + } + } + + customRegistry.registerAdapter(new StandaloneAdapter1()); + customRegistry.registerAdapter(new StandaloneAdapter2()); + + const plan = await planExecution(customRegistry, { cwd: tempDir }, "fix"); + // Even though capabilities are independent (typecheck vs assist), task IDs are identical, so second is deduplicated + expect(plan.tasks).toHaveLength(1); + expect(plan.tasks[0].executable).toBe("check-1"); + }); + }); + describe("Registry Extensibility", () => { it("resolves project binaries and Windows executable shims cleanly", async () => { const binDir = path.join(tempDir, "node_modules", ".bin"); From 6f9c13fb84b1de62f86127d66c9c12c3b497ec7e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 10 Nov 2026 05:10:33 +0000 Subject: [PATCH 2/5] fix(autofix): provider capability isolation and vite-plus wrapper detection - F-01: Preserve capability isolation across language providers using scope-based capability tracking (adapter.scope ?? provider.id / 'standalone'), preventing unrelated language providers from suppressing each other's execution tasks. - F-02: Support Vite+ detection through command wrappers (cross-env, sh -c, bash -c, package-manager runners, script delegations) via unwrapEnvironmentWrapper and hasVitePlusCommand. - Rebuild dist/autofix.mjs bundle. - Add changeset and comprehensive regression tests. --- ...apter-conflicts-and-vite-plus-detection.md | 2 +- dist/autofix.mjs | 16 +-- .../adapters/javascript/script-adapter.ts | 88 +++++++++++- src/autofix/adapters/javascript/tools.ts | 5 +- src/autofix/planner.ts | 41 ++++-- src/autofix/types.ts | 1 + tests/autofix-architecture.test.ts | 129 +++++++++++++++++- 7 files changed, 256 insertions(+), 26 deletions(-) diff --git a/.changeset/fix-standalone-adapter-conflicts-and-vite-plus-detection.md b/.changeset/fix-standalone-adapter-conflicts-and-vite-plus-detection.md index fee7c66f..457b3ec1 100644 --- a/.changeset/fix-standalone-adapter-conflicts-and-vite-plus-detection.md +++ b/.changeset/fix-standalone-adapter-conflicts-and-vite-plus-detection.md @@ -2,4 +2,4 @@ "@area44/workflows": patch --- -Fix standalone adapter capability conflict resolution and prevent false-positive Vite+ detection. +Fix provider capability isolation in multi-language monorepos and support wrapped Vite+ command detection. diff --git a/dist/autofix.mjs b/dist/autofix.mjs index 1b5bf8d0..3f5ecc45 100644 --- a/dist/autofix.mjs +++ b/dist/autofix.mjs @@ -303,11 +303,11 @@ const Vn=[`uv`,`pip`],Hn=[`.git`,`.venv`,`venv`,`env`,`.env`,`virtualenv`,`.virt `?` `:` `,i++;return i=t+1&&e[a]===`\\`;)n++,a--;if(n%2==0)return r+=` `,[r,i+1]}r+=` `,i++}return[r,i]}function dr(e,t,n){let r=` `,i=t+1;for(;i!Un(e))}function mr(e,t){if(!Un(e[`build-system`]))return!1;if(typeof t==`string`){let e=fr(t);return/(?:^|\n)\s*\[\s*build-system\s*\]\s*(?:\n|$)/.test(e)}let n=Object.entries(e[`build-system`]);return n.length===0||n.some(([,e])=>!Un(e))}function hr(e,t){if(pr(e,t)||mr(e,t))return!0;if(Un(e.tool)&&Un(e.tool.uv)){let t=e.tool.uv;return Yn(t.workspace)||Array.isArray(t[`dev-dependencies`])}return!1}function gr(e){return Un(e.tool)&&Un(e.tool.uv)}function _r(e,t){return pr(e,t)||mr(e,t)}function vr(e,t){return p.relative(e,t)||`.`}function yr(e,t){if(!t)throw Error(`Invalid Python project configuration: 'uv.lock' was detected without a valid 'pyproject.toml' project or workspace configuration ('[project]', '[build-system]', or '[tool.uv.workspace]'). 'uv sync' requires a valid 'pyproject.toml' file.`);return{name:`uv`,lockfile:`uv.lock`,configFile:`pyproject.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}}function br(e,t){if(e.hasRequirementsTxt&&e.requirementsDir){let t=vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`));return{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`pip`,`install`,`-r`,t]}],execPrefix:`uv run`}}return t?{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}:null}function xr(e){let t=e.pyprojectToml?.success===!0&&hr(e.pyprojectToml.data,e.pyprojectToml.rawContent),n=e.workspaceRootToml?.success===!0&&hr(e.workspaceRootToml.data,e.workspaceRootToml.rawContent),r=t||n,i=e.uvToml?.success===!0,a=e.pyprojectToml?.success===!0&&gr(e.pyprojectToml.data)||e.workspaceRootToml?.success===!0&&gr(e.workspaceRootToml.data);return e.hasUvLock?yr(e,r):a||i?br(e,r):null}function Sr(e){let t=e.pyprojectToml?.success===!0&&_r(e.pyprojectToml.data,e.pyprojectToml.rawContent);if(!(e.hasRequirementsTxt||e.hasSetupPy||e.hasSetupCfg||t))return null;let n;t?n=`pyproject.toml`:e.hasSetupPy?n=`setup.py`:e.hasSetupCfg&&(n=`setup.cfg`);let r=[],i,a=e.hasSetupPy||e.hasSetupCfg||t,o=e.requirementsDir?vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`)):`requirements.txt`,s=vr(e.cwd,e.projectDir);return e.hasRequirementsTxt&&a?(r=[{executable:`pip`,args:[`install`,`-r`,o]},{executable:`pip`,args:[`install`,`-e`,s]}],i=`requirements.txt`):e.hasRequirementsTxt?(r=[{executable:`pip`,args:[`install`,`-r`,o]}],i=`requirements.txt`):a&&(r=[{executable:`pip`,args:[`install`,`-e`,s]}]),{name:`pip`,lockfile:i,configFile:n,installCommands:r,execPrefix:``}}function Cr(e=process.cwd(),t){if(t?.hasSource??or(e))return!0;let n=t?.ctx??ir(e);if(n.projectDir===n.cwd&&tr(n.cwd)&&(n.pyprojectToml?.success===!0&&hr(n.pyprojectToml.data,n.pyprojectToml.rawContent)||n.hasUvLock||n.hasRequirementsTxt||n.hasSetupPy||n.hasSetupCfg))return!0;if(n.workspaceRootDir&&n.workspaceRootToml?.success===!0){let t=Zn(n.workspaceRootDir);if(t&&Xn(n.workspaceRootDir,p.resolve(e),t.config))return!0}return!1}function wr(e,t){t!=null&&(e.pyprojectToml=t);for(let t of Vn)if(t===`uv`){let t=xr(e);if(t)return t}else if(t===`pip`){let t=Sr(e);if(t)return t}return{name:`pip`,installCommands:[],execPrefix:``,isStandalone:!0}}function Tr(e=process.cwd(),t,n){let r=n?.ctx??ir(e);return n?.isProject??Cr(e,{ctx:r,hasSource:n?.hasSource})?wr(r,t):null}function Er(e){if(!Array.isArray(e))throw Error(`Invalid Python environment: "pmInfo.installCommands" must be an array`);for(let t of e){if(!t||typeof t!=`object`)throw Error(`Invalid Python environment: malformed "installCommands" item`);let e=t;if(typeof e.executable!=`string`||!e.executable.trim()||!Array.isArray(e.args)||!e.args.every(e=>typeof e==`string`))throw Error(`Invalid Python environment: malformed "installCommands" item`)}}function Dr(e,t=`Invalid Python environment: "pmInfo" must be an object`){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(t);let n=e;if(n.name!==`uv`&&n.name!==`pip`)throw Error(`Invalid Python environment: pmInfo name must be "uv" or "pip"`);return Er(n.installCommands),n}function Or(e){if(!process.argv[1])return!1;try{return l(e)===f.realpathSync(process.argv[1])}catch{return!1}}async function kr(e,t,n=process.platform){let r=p.join(e,`node_modules`,`.bin`),i=/* @__PURE__ */ new Set([`.cmd`,`.bat`,`.exe`]);if(n===`win32`){let e=p.extname(t).toLowerCase();if(e){if(!i.has(e))return;let n=p.join(r,t);if(f.existsSync(n))return n}else for(let e of[`.cmd`,`.bat`,`.exe`,``]){let n=p.join(r,`${t}${e}`);if(f.existsSync(n))return n}}else{let e=p.join(r,t);if(f.existsSync(e))return e}let a=await Vt(t,!1);if(a){if(n===`win32`){let e=p.extname(a).toLowerCase();if(e&&!i.has(e))return}return a}}var Ar=class{platform;constructor(e=process.platform){this.platform=e}async resolveTaskExecutable(e){if(e.toolId===`npm-scripts`)return e.executable;if(e.toolId===`ruff`){if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);return`ruff`}let t=await kr(e.cwd,e.executable,this.platform);if(!t){let t=e.toolName||e.toolId,n=e.requiredPackage||e.executable;throw Error(`Configured tool "${t}" could not run: executable "${e.executable}" is not available in node_modules/.bin or PATH. Please install "${n}" in project dependencies.`)}return t}async executeTasks(e){let t=[];for(let n of e){let e=`${n.executable} ${n.args.join(` `)}`.trim();try{let r=await this.resolveTaskExecutable(n);en(`Executing: ${e}`);let i=n.env?Object.fromEntries(Object.entries({...process.env,...n.env}).filter(e=>e[1]!==void 0)):void 0,a=await Yt(r,n.args,{cwd:n.cwd,env:i,ignoreReturnCode:!0});if(a!==0){let r=n.toolId===`ruff`?`Ruff command "${e}" failed. Check Python and Ruff configuration.`:n.toolId===`npm-scripts`?`Script "${n.args[1]||e}" failed while executing "${e}".`:`Task "${n.id}" (${e}) failed with exit code ${a}.`;t.push({task:n,exitCode:a,error:Error(r)})}else t.push({task:n,exitCode:a})}catch(e){let r=e instanceof Error?e:Error(String(e));t.push({task:n,exitCode:1,error:r})}}return t}};function jr(e,t){return t.has(`autofix`)?!0:e===`autofix`?t.has(`format`)&&t.has(`lint`)&&t.has(`assist`):t.has(e)}function Mr(e,t){let n=[],r=[];for(let i of e)jr(i.capability,t)?r.push(i):n.push(i);return{kept:n,skipped:r}}async function Nr(e,t,n,r,i,a,o){for(let s of e){let e=s.adapter,c=await e.plan(n,r);if(c.length===0)continue;let{kept:l,skipped:u}=Mr(c,t);if(l.length===0)a.push({id:e.id,name:e.name,reason:`all capabilities already covered by higher priority tool`});else{i.push({id:e.id,name:e.name,reason:s.reason});for(let e of l)if(t.add(e.capability),e.capabilities)for(let n of e.capabilities)t.add(n);if(o.push(...l),u.length>0){let t=Array.from(new Set(u.map(e=>e.capability))).join(`, `);a.push({id:e.id,name:e.name,reason:`partially skipped (${t} covered by higher priority tool)`})}}}}async function Pr(e,t,n,r,i,a,o){let s=[];for(let t of e.getStandaloneAdapters()){let e=await t.detect(n);e.detected?s.push({adapter:t,reason:e.reason}):e.reason&&!e.reason.startsWith(`no `)&&a.push({id:t.id,name:t.name,reason:e.reason})}await Nr(s,t,n,r,i,a,o)}function Fr(e){let t=[],n=/* @__PURE__ */ new Set;for(let r of e)n.has(r.id)||(n.add(r.id),t.push(r));return t}async function Ir(e,t,n=`fix`){let r=t.hasPythonSource??or(t.cwd),i=t.jsEnv??fn(t.cwd),a={...t,jsEnv:i,hasPythonSource:r},o=[],s=[],c=[],l=e.getProviders(),u=/* @__PURE__ */ new Set;for(let e of l){if(!await e.detect(a))continue;let t=e.getAdapters(a),r=[];for(let e of t){let t=await e.detect(a);t.detected?r.push({adapter:e,reason:t.reason}):t.reason&&!t.reason.startsWith(`no `)&&s.push({id:e.id,name:e.name,reason:t.reason})}await Nr(r,u,a,n,o,s,c)}await Pr(e,u,a,n,o,s,c);let d=Fr(c);return{tasks:d,selectedTools:o,skippedTools:s,summary:Lr(e,a,o,s,d)}}function Lr(e,t,n,r,i){let a=[];a.push(`Detected environments:`);let o=t.hasPythonSource??!1,s=t.jsEnv?.hasPackageJson??!1;if(a.push(` Python: ${o}`),a.push(` JavaScript: ${s}`),o&&(a.push(``),a.push(`Python toolchain:`),n.filter(e=>e.id===`ruff`).length>0?a.push(` Ruff: default tool`):a.push(` None`)),s){a.push(``),a.push(`JavaScript toolchain:`);let e=n.filter(e=>e.id!==`ruff`);for(let t of e)a.push(` ${t.name}: selected`);let t=r.filter(e=>e.id!==`ruff`);for(let e of t)a.push(` ${e.name}: skipped (${e.reason})`)}if(a.push(``),a.push(`Execution plan:`),i.length===0?a.push(` (no tasks to execute)`):i.forEach((e,t)=>{let n=e.description||`${e.executable} ${e.args.join(` `)}`;a.push(` ${t+1}. ${n}`)}),r.length>0){a.push(``),a.push(`Skipped:`);for(let e of r)a.push(` - ${e.name}: ${e.reason}`)}return a.join(` -`)}function Rr(e){for(let t of[`format:write`,`format:fix`,`format`,`fmt`])if(e[t]&&qi(e[t],e))return t}function zr(e){if(e[`format:check`]&&Ki(e[`format:check`],e)===`read-only`)return`format:check`;if(e[`fmt:check`]&&Ki(e[`fmt:check`],e)===`read-only`)return`fmt:check`}function Br(e,t){return t===`fix`?Rr(e):zr(e)}function Vr(e,t){if(t===`fix`)return e[`lint:fix`]?`lint:fix`:e[`lint:write`]?`lint:write`:void 0;if(e[`lint:check`]&&Ki(e[`lint:check`],e)===`read-only`)return`lint:check`;if(e.lint&&Ki(e.lint,e)===`read-only`)return`lint`}function Hr(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped)return 0;let r=e[t];return r===`;`||r===` -`?1:r===`&`&&e[t+1]===`&`||r===`|`&&e[t+1]===`|`?2:+(r===`|`)}function Ur(e,t){let n=t;for(;nt?n-1:t}function Wr(e,t){return t.inSingleQuote||t.inDoubleQuote||t.isEscaped?!1:e.length===0||/\s/.test(e[e.length-1])}function Gr(e,t){return t.isEscaped=!1,{ch:e,advance:!0}}function Kr(e,t,n,r){let i=e[t];if(n.isEscaped)return{newCmd:r+Gr(i,n).ch,nextIndex:t,sepLen:0};if(i===`\\`&&!n.inSingleQuote)return n.isEscaped=!0,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`'`&&!n.inDoubleQuote)return n.inSingleQuote=!n.inSingleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`"`&&!n.inSingleQuote)return n.inDoubleQuote=!n.inDoubleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`#`&&Wr(r,n))return{newCmd:r,nextIndex:Ur(e,t),sepLen:0};let a=Hr(e,t,n);return{newCmd:r+(a===0?i:``),nextIndex:t,sepLen:a}}function qr(e){let t=[],n=``,r={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1,hasSyntaxError:!1};for(let i=0;i0?(n.trim()&&t.push(n.trim()),n=``,i+=a.sepLen-1):(n=a.newCmd,i=a.nextIndex)}return(r.inSingleQuote||r.inDoubleQuote||r.isEscaped)&&(r.hasSyntaxError=!0),n.trim()&&t.push(n.trim()),{commands:t,hasSyntaxError:r.hasSyntaxError}}function Jr(e){return qr(e).commands}function Yr(e,t,n){return t.isEscaped=!1,n+e}function Xr(e,t){return e===`'`&&!t.inDoubleQuote?(t.inSingleQuote=!t.inSingleQuote,!0):e===`"`&&!t.inSingleQuote&&(t.inDoubleQuote=!t.inDoubleQuote,!0)}const Zr=/* @__PURE__ */ new Set([`@`,`*`,`#`,`?`,`-`,`$`,`!`,`0`]);function Qr(e,t,n){if(n.inSingleQuote||n.isEscaped||e[t]!==`$`||t+1>=e.length)return!1;let r=e[t+1];return!!(r===`{`||Zr.has(r)||r>=`1`&&r<=`9`||r===`_`||r>=`a`&&r<=`z`||r>=`A`&&r<=`Z`)}function $r(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped||e[t]!==`&`)return!1;let r=t>0?e[t-1]:``,i=t+1`}function ei(e,t,n){if(n.inSingleQuote||n.isEscaped)return!1;let r=e[t];return r==="`"||r===`$`&&t+1`)&&t+1`||r===`<`||r===`&`&&t+1`}function ri(e,t,n){return $r(e,t,n.state)||Qr(e,t,n.state)||ei(e,t,n.state)||ti(e,t,n.state)?(n.inspection.hasUnsupportedSyntax=!0,!0):ni(e,t,n.state)?(n.inspection.hasRedirection=!0,n.inspection.hasUnsupportedSyntax=!0,!0):!1}function ii(e,t,n,r){let i=e[t];return n.state.isEscaped?{word:Yr(i,n.state,r),hasChars:!0,skipped:!1}:i===`\\`&&!n.state.inSingleQuote?(n.state.isEscaped=!0,{word:r,hasChars:!1,skipped:!0}):(ri(e,t,n),Xr(i,n.state)?{word:r,hasChars:!0,skipped:!0}:{word:r+i,hasChars:!0,skipped:!1})}function ai(e){let t={tokens:[],hasUnsupportedSyntax:!1,hasRedirection:!1},n={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1},r={inspection:t,state:n},i=``,a=!1;for(let o=0;o0&&n.push(t)}return n}function fi(e,t,n={},r=/* @__PURE__ */ new Set){if(!e||!t)return!1;let i=di(n[e]===void 0?e:n[e]);for(let e of i){if(ui(e,t))return!0;let i=Bi(e);if(i){if(i===t)return!0;if(!r.has(i)&&n[i]!==void 0){r.add(i);try{if(fi(n[i],t,n,r))return!0}finally{r.delete(i)}}}let a=Vi(e);if(a!==void 0&&fi(a,t,n,r))return!0}return!1}function pi(e,t,n){return!n||n===t?!1:!fi(e[t]||``,n,e)}function mi(e,t,n){return!n||n===t?!1:!fi(e[t]||``,n,e)}function hi(e){let[t]=e;return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||(e===`--fix`||e.startsWith(`--fix=`))&&(t!==`eslint`||e!==`--fix-dry-run`))}function gi(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function _i(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function vi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function yi(e){let[t]=e;return t===`eslint`&&e.some(e=>(e===`--fix`||e.startsWith(`--fix=`))&&e!==`--fix-dry-run`)}function bi(e){let[t]=e;return t===`oxlint`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function xi(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Si(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Ci(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:!e.some(e=>e===`--check`||e===`-c`)}function wi(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Ti(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)&&e!==`--fix-dry-run`||e===`-o`||e.startsWith(`-o=`)||e===`--output-file`||e.startsWith(`--output-file=`)||e===`--cache`||e===`--cache-file`||e.startsWith(`--cache-file=`)||e===`--cache-location`||e.startsWith(`--cache-location=`))}function Ei(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--cache`||e===`--cache-location`||e.startsWith(`--cache-location=`)||e===`--insert-pragma`)}function Di(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`)||e===`--reporter-file`||e.startsWith(`--reporter-file=`)||e===`--log-file`||e.startsWith(`--log-file=`))}function Oi(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)||e===`--fix-suggestions`||e===`--fix-dangerously`||e===`--init`)}function ki(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--init`||e===`--migrate`||e.startsWith(`--migrate=`))}function Ai(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`--check`||e===`-c`||e===`--list-different`||e===`-l`)&&!Ei(e)}function ji(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`--check`||e===`-c`)&&!ki(e)}function Mi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:!Di(e)}function Ni(e){let[t]=e;return t===`eslint`&&!Ti(e)}function Pi(e){let[t]=e;return t===`oxlint`&&!Oi(e)}function Fi(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:!Di(e)}function Ii(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:!Di(e)}function Li(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:e.some(e=>e===`--check`||e===`-c`)&&!ki(e)}function Ri(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:!Oi(e)}function zi(e){let[t,n]=e;return t!==`vp`||n!==`check`?!1:!e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Bi(e){if(e.length===0)return;let[t,n,r]=e;if((t===`npm`||t===`pnpm`||t===`yarn`||t===`bun`)&&n===`run`&&r)return r;if((t===`pnpm`||t===`bun`||t===`yarn`)&&n&&!n.startsWith(`-`))return n}function Vi(e){if(e.length>=3&&(e[0]===`sh`||e[0]===`bash`)&&e[1]===`-c`)return e[2]}function Hi(e){return gi(e)||_i(e)||vi(e)||yi(e)||bi(e)||xi(e)||Si(e)||Ci(e)||wi(e)}function Ui(e){return Ai(e)||ji(e)||Mi(e)||Ni(e)||Pi(e)||Fi(e)||Ii(e)||Li(e)||Ri(e)||zi(e)}function Wi(e,t,n){if(e.length===0)return`unknown`;if(hi(e))return`write-capable`;let r=Vi(e);if(r!==void 0)return Gi(r,t,n);let i=Bi(e);if(i){if(n.has(i))return`unknown`;let e=t[i];if(!e)return`unknown`;n.add(i);try{return Gi(e,t,n)}finally{n.delete(i)}}return Hi(e)?`write-capable`:Ui(e)?`read-only`:`unknown`}function Gi(e,t,n){let r=qr(e);if(r.hasSyntaxError)return`unknown`;let{commands:i}=r;if(i.length===0)return`unknown`;let a=!1;for(let e of i){let r=ai(e),i=Wi(li(r.tokens),t,n);if(i===`write-capable`)return`write-capable`;if(r.hasUnsupportedSyntax||i===`unknown`)return`unknown`;i===`read-only`&&(a=!0)}return a?`read-only`:`unknown`}function Ki(e,t={}){return Gi(e,t,/* @__PURE__ */ new Set)}function qi(e,t={},n=/* @__PURE__ */ new Set){return di(e).some(e=>{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return qi(e,t,n)}finally{n.delete(r)}}let i=Vi(e);return i===void 0?gi(e)||_i(e)||vi(e)||Ci(e):qi(i,t,n)})}function Ji(e,t={},n=/* @__PURE__ */ new Set){return di(e).some(e=>{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Ji(e,t,n)}finally{n.delete(r)}}let i=Vi(e);return i===void 0?yi(e)||bi(e)||xi(e)||wi(e):Ji(i,t,n)})}function Yi(e,t={},n=/* @__PURE__ */ new Set){return di(e).some(e=>{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Yi(e,t,n)}finally{n.delete(r)}}let i=Vi(e);if(i!==void 0)return Yi(i,t,n);if(Si(e))return!0;let[a,o]=e;return a===`vp`&&o===`check`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))})}function Xi(e,t,n,r){return t&&fi(e,t,n)?!0:r(e)}function Zi(e,t,n,r,i){let a=Xi(t,r,e,t=>qi(t,e)),o=Xi(t,i,e,t=>Ji(t,e)),s=Yi(t,e);return a&&o?[{capability:`format`,capabilities:[`format`,`lint`],scriptName:n}]:a&&!s?[{capability:`format`,scriptName:n}]:o&&!s?[{capability:`lint`,scriptName:n}]:s?[{capability:`autofix`,scriptName:n}]:[{capability:`typecheck`,capabilities:[],scriptName:n}]}function Qi(e,t){return qi(t[e],t)?{capability:`format`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function $i(e,t){return Ji(t[e],t)?{capability:`lint`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function ea(e,t,n){let r=[];return e&&r.push(Qi(e,n)),t&&r.push($i(t,n)),r}function ta(e,t,n,r,i){r&&pi(t,n,r)&&e.push(Qi(r,t)),i&&mi(t,n,i)&&e.push($i(i,t))}function na(e){let t=e.fix?`fix`:e[`check:fix`]?`check:fix`:void 0,n=Br(e,`fix`),r=Vr(e,`fix`);if(!t)return ea(n,r,e);let i=Zi(e,e[t]||``,t,n,r);return ta(i,e,t,n,r),i}function ra(e){let t=[],n=Br(e,`check`),r=Vr(e,`check`);return n&&t.push({capability:`format`,scriptName:n}),r&&t.push({capability:`lint`,scriptName:r}),t}function ia(e,t){return t===`fix`?na(e):ra(e)}var aa=class{id=`npm-scripts`;name=`package.json scripts`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson?.scripts;if(!t||Object.keys(t).length===0)return{detected:!1,reason:`no scripts declared in package.json`};let n=ia(t,`fix`),r=ia(t,`check`),i=[...n,...r];return i.length>0?{detected:!0,reason:`found supported scripts: ${Array.from(new Set(i.map(e=>`"${e.scriptName}"`))).join(`, `)}`}:{detected:!1,reason:`no supported autofix or check scripts found in package.json`}}plan(e,t){let n=ia(e.jsEnv?.packageJson?.scripts||{},t),r=cn(e.jsPm||`npm`);return n.map(n=>({id:`script-${n.scriptName}`,toolId:this.id,capability:n.capability,capabilities:n.capabilities,executable:r,args:[`run`,n.scriptName],cwd:e.cwd,mode:t,description:`package.json script: ${r} run ${n.scriptName}`}))}};function oa(e){return e?Object.values(e).some(e=>di(e).some(e=>e[0]===`vp`)):!1}function sa(e,t){return e?!!(e.dependencies?.[t]||e.devDependencies?.[t]||e.peerDependencies?.[t]||e.optionalDependencies?.[t]):!1}function ca(e,t){for(let n of t)if(f.existsSync(p.join(e,n)))return!0;return!1}var la=class{id=`vite-plus`;name=`Vite+`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sn(t),r=ca(e.cwd,[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.cjs`]);return n||r&&oa(t?.scripts)?{detected:!0,reason:`Vite+ dependency and/or configuration detected`}:{detected:!1,reason:`no Vite+ dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`vite-plus-fmt`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp fmt`},{id:`vite-plus-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`,`--fix`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp lint --fix`}]:[{id:`vite-plus-fmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`,`--check`],cwd:e.cwd,mode:`check`,description:`Vite+: vp fmt --check`},{id:`vite-plus-lint`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`],cwd:e.cwd,mode:`check`,description:`Vite+: vp lint`}]}},ua=class{id=`biome`;name=`Biome`;capabilities=[`format`,`lint`,`assist`];detect(e){let t=e.jsEnv?.packageJson,n=sa(t,`@biomejs/biome`),r=ca(e.cwd,[`biome.json`,`biome.jsonc`]);return n&&r?{detected:!0,reason:`Biome dependency and configuration detected`}:r?{detected:!0,reason:`Biome configuration detected`}:n?{detected:!1,reason:`Biome dependency present without configuration file`}:{detected:!1,reason:`no Biome dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`biome-format-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: format --write .`},{id:`biome-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: lint --write .`},{id:`biome-assist-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--write`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: safe assist actions (--write)`}]:[{id:`biome-format-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: format .`},{id:`biome-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: lint .`},{id:`biome-assist-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: check assist actions`}]}},da=class{id=`prettier`;name=`Prettier`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=sa(t,`prettier`),r=!!t?.prettier,i=ca(e.cwd,[`.prettierrc`,`.prettierrc.json`,`.prettierrc.yml`,`.prettierrc.yaml`,`.prettierrc.json5`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`]);return n&&(r||i)?{detected:!0,reason:`Prettier dependency and configuration detected`}:r||i?{detected:!0,reason:`Prettier configuration detected`}:n?{detected:!1,reason:`Prettier dependency present without configuration`}:{detected:!1,reason:`no Prettier dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`prettier-format`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Prettier: format`}]:[{id:`prettier-check`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Prettier: format check`}]}},fa=class{id=`eslint`;name=`ESLint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sa(t,`eslint`),r=!!t?.eslintConfig,i=ca(e.cwd,[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yaml`,`.eslintrc.yml`]);return n&&(r||i)?{detected:!0,reason:`ESLint dependency and configuration detected`}:r||i?{detected:!0,reason:`ESLint configuration detected`}:n?{detected:!1,reason:`ESLint dependency present without configuration`}:{detected:!1,reason:`no ESLint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`eslint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`ESLint: lint autofix`}]:[{id:`eslint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`ESLint: lint check`}]}},pa=class{id=`oxlint`;name=`Oxlint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sa(t,`oxlint`),r=ca(e.cwd,[`.oxlintrc.json`,`oxlint.json`,`oxlint.config.ts`,`oxlint.config.js`]);return n&&r?{detected:!0,reason:`Oxlint dependency and configuration detected`}:r?{detected:!0,reason:`Oxlint configuration detected`}:n?{detected:!1,reason:`Oxlint dependency present without configuration`}:{detected:!1,reason:`no Oxlint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxlint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxlint: lint autofix`}]:[{id:`oxlint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`Oxlint: lint check`}]}},ma=class{id=`oxfmt`;name=`Oxfmt`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=sa(t,`oxfmt`),r=ca(e.cwd,[`.oxfmtrc.json`,`oxfmt.json`,`oxfmt.config.ts`,`oxfmt.config.js`]);return n&&r?{detected:!0,reason:`Oxfmt dependency and configuration detected`}:r?{detected:!0,reason:`Oxfmt configuration detected`}:n?{detected:!1,reason:`Oxfmt dependency present without configuration`}:{detected:!1,reason:`no Oxfmt dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxfmt-format`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxfmt: format`}]:[{id:`oxfmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Oxfmt: format check`}]}},ha=class{id=`javascript`;name=`JavaScript/TypeScript`;scriptAdapter=new aa;vitePlusAdapter=new la;biomeAdapter=new ua;prettierAdapter=new da;eslintAdapter=new fa;oxlintAdapter=new pa;oxfmtAdapter=new ma;detect(e){return!!e.jsEnv?.hasPackageJson}getAdapters(e){return[this.scriptAdapter,this.vitePlusAdapter,this.biomeAdapter,this.oxfmtAdapter,this.prettierAdapter,this.oxlintAdapter,this.eslintAdapter]}},ga=class{id=`ruff`;name=`Ruff`;capabilities=[`lint`,`format`];detect(e){return e.hasPythonSource??or(e.cwd)?{detected:!0,reason:`default Python toolchain`}:{detected:!1,reason:`no Python source files detected`}}plan(e,t){let n=[];return t===`fix`?n.push({id:`ruff-lint-fix`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: lint autofix`},{id:`ruff-format`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: format`}):n.push({id:`ruff-lint-check`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: lint check`},{id:`ruff-format-check`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: format check`}),n}},_a=class{id=`python`;name=`Python`;ruffAdapter=new ga;detect(e){return e.hasPythonSource??or(e.cwd)}getAdapters(e){return[this.ruffAdapter]}},va=class{providers=/* @__PURE__ */ new Map;standaloneAdapters=/* @__PURE__ */ new Map;registerProvider(e){this.providers.set(e.id,e)}getProvider(e){return this.providers.get(e)}getProviders(){return Array.from(this.providers.values())}registerAdapter(e){this.standaloneAdapters.set(e.id,e)}getAdapter(e){return this.standaloneAdapters.get(e)}getStandaloneAdapters(){return Array.from(this.standaloneAdapters.values())}clear(){this.providers.clear(),this.standaloneAdapters.clear()}};function ya(){let e=new va;return e.registerProvider(new _a),e.registerProvider(new ha),e}const ba=ya();async function xa(e,t=process.cwd()){let n=`${e.command} ${e.args.join(` `)}`.trim();if(en(`Installing JS dependencies: ${n}`),await Yt(e.command,e.args,{cwd:t,ignoreReturnCode:!0})!==0)throw Error(`JS dependency installation failed executing "${n}". Check dependency constraints or lockfile compatibility.`)}async function Sa(e=process.cwd()){let t=fn(e);if(!t.hasPackageJson){en(`No package.json found. Skipping scripts.`);return}if(t.packageJsonError)throw Error(t.packageJsonError);let n=cn(process.env.PACKAGE_MANAGER||_n(t).name),r=(await Ir(ba,{cwd:e,jsEnv:t,jsPm:n,hasPythonSource:!1},`fix`)).tasks.filter(e=>e.toolId!==`ruff`);if(r.length===0){en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`);return}await xa(vn(n),e);let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}}async function Ca(e,t,n=process.cwd()){let r=`${e} ${t.join(` `)}`.trim();if(en(`Executing: ${r}`),await Yt(e,t,{cwd:n,ignoreReturnCode:!0})!==0)throw Error(`Python command "${r}" failed. Check Python environment and dependency configuration.`)}async function wa(e,t=process.cwd()){Dr(e,`Invalid Python environment: "pmInfo" must be an object`);let n=e.name===`pip`?`pip`:e.name;if(!await Vt(n,!1)&&!e.isStandalone){let e=`Required Python package manager '${n}' is not available in PATH.`;throw Error(e)}if(!e.isStandalone&&e.installCommands.length>0){let n=e.installCommands;en(`Installing Python dependencies: ${n.map(e=>`${e.executable} ${e.args.join(` `)}`).join(` && `)}`);for(let{executable:e,args:r}of n)await Ca(e,r,t)}}async function Ta(e=process.cwd(),t,n){if(!(t??or(e)))return;let r;if(n)r=n;else{if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);r=(await Ir(ba,{cwd:e,hasPythonSource:!0},`fix`)).tasks.filter(e=>e.toolId===`ruff`)}let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}}async function Ea(e,t){if(process.env.JS_SETUP_OUTCOME===`failure`||process.env.NODE_SETUP_OUTCOME===`failure`||process.env.BUN_SETUP_OUTCOME===`failure`||process.env.PNPM_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`JavaScript runtime or package manager setup failed.`);try{if(t){let n=fn(e);if(!n.hasPackageJson)return en(`No package.json found. Skipping scripts.`),null;if(n.packageJsonError)throw Error(n.packageJsonError);if(t.length===0)return en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`),null;await xa(vn(cn(process.env.PACKAGE_MANAGER||_n(n).name)),e);let r=(await new Ar().executeTasks(t)).filter(e=>e.error);if(r.length>0){let e=r.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}return null}return await Sa(e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Da(e,t){if(process.env.PYTHON_SETUP_OUTCOME===`failure`||process.env.UV_SETUP_OUTCOME===`failure`||process.env.PY_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Python runtime or package manager setup failed.`);let n=t&&`pmInfo`in t?t.pmInfo:Tr(e,void 0,{ctx:t?.ctx,hasSource:t?.hasSource});if(!n)return null;try{return await wa(n,e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Oa(e,t,n){if(process.env.RUFF_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Ruff setup failed.`);try{return await Ta(e,t,n),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function ka(e,t,n){let r=t??or(e);if(!r)return[];let i=[],a=ir(e),o=await Da(e,{ctx:a,hasSource:!0,pmInfo:Tr(e,void 0,{ctx:a,hasSource:!0,isProject:!0})});o&&i.push(o);let s=await Oa(e,r,n);return s&&i.push(s),i}async function Aa(e=process.cwd()){let t=or(e),n;try{let r=fn(e),i={cwd:e,jsEnv:r,jsPm:cn(process.env.PACKAGE_MANAGER||_n(r).name),hasPythonSource:t};n=await Ir(ba,i,`fix`),en(n.summary)}catch{}let r=[],i=n?n.tasks.filter(e=>e.toolId!==`ruff`):void 0,a=n?n.tasks.filter(e=>e.toolId===`ruff`):void 0,o=await Ea(e,i);o&&r.push(o);let s=await ka(e,t,a);r.push(...s),r.length>0&&(Zt(`Failed to run scripts: ${r.map(e=>e.message).join(` -`)}`),process.env.NODE_ENV!==`test`&&process.exit(1))}process.env.NODE_ENV!==`test`&&Or(import.meta.url)&&Aa();export{Sa as executeJsWorkflow,wa as executePythonWorkflow,Ta as executeRuffAutofix,Aa as run,cn as sanitizePackageManager}; \ No newline at end of file +`&&e[i]!==`\r`;)r+=` `,i++;return i!Un(e))}function mr(e,t){if(!Un(e[`build-system`]))return!1;if(typeof t==`string`){let e=fr(t);return/(?:^|\n)\s*\[\s*build-system\s*\]\s*(?:\n|$)/.test(e)}let n=Object.entries(e[`build-system`]);return n.length===0||n.some(([,e])=>!Un(e))}function hr(e,t){if(pr(e,t)||mr(e,t))return!0;if(Un(e.tool)&&Un(e.tool.uv)){let t=e.tool.uv;return Yn(t.workspace)||Array.isArray(t[`dev-dependencies`])}return!1}function gr(e){return Un(e.tool)&&Un(e.tool.uv)}function _r(e,t){return pr(e,t)||mr(e,t)}function vr(e,t){return p.relative(e,t)||`.`}function yr(e,t){if(!t)throw Error(`Invalid Python project configuration: 'uv.lock' was detected without a valid 'pyproject.toml' project or workspace configuration ('[project]', '[build-system]', or '[tool.uv.workspace]'). 'uv sync' requires a valid 'pyproject.toml' file.`);return{name:`uv`,lockfile:`uv.lock`,configFile:`pyproject.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}}function br(e,t){if(e.hasRequirementsTxt&&e.requirementsDir){let t=vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`));return{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`pip`,`install`,`-r`,t]}],execPrefix:`uv run`}}return t?{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}:null}function xr(e){let t=e.pyprojectToml?.success===!0&&hr(e.pyprojectToml.data,e.pyprojectToml.rawContent),n=e.workspaceRootToml?.success===!0&&hr(e.workspaceRootToml.data,e.workspaceRootToml.rawContent),r=t||n,i=e.uvToml?.success===!0,a=e.pyprojectToml?.success===!0&&gr(e.pyprojectToml.data)||e.workspaceRootToml?.success===!0&&gr(e.workspaceRootToml.data);return e.hasUvLock?yr(e,r):a||i?br(e,r):null}function Sr(e){let t=e.pyprojectToml?.success===!0&&_r(e.pyprojectToml.data,e.pyprojectToml.rawContent);if(!(e.hasRequirementsTxt||e.hasSetupPy||e.hasSetupCfg||t))return null;let n;t?n=`pyproject.toml`:e.hasSetupPy?n=`setup.py`:e.hasSetupCfg&&(n=`setup.cfg`);let r=[],i,a=e.hasSetupPy||e.hasSetupCfg||t,o=e.requirementsDir?vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`)):`requirements.txt`,s=vr(e.cwd,e.projectDir);return e.hasRequirementsTxt&&a?(r=[{executable:`pip`,args:[`install`,`-r`,o]},{executable:`pip`,args:[`install`,`-e`,s]}],i=`requirements.txt`):e.hasRequirementsTxt?(r=[{executable:`pip`,args:[`install`,`-r`,o]}],i=`requirements.txt`):a&&(r=[{executable:`pip`,args:[`install`,`-e`,s]}]),{name:`pip`,lockfile:i,configFile:n,installCommands:r,execPrefix:``}}function Cr(e=process.cwd(),t){if(t?.hasSource??or(e))return!0;let n=t?.ctx??ir(e);if(n.projectDir===n.cwd&&tr(n.cwd)&&(n.pyprojectToml?.success===!0&&hr(n.pyprojectToml.data,n.pyprojectToml.rawContent)||n.hasUvLock||n.hasRequirementsTxt||n.hasSetupPy||n.hasSetupCfg))return!0;if(n.workspaceRootDir&&n.workspaceRootToml?.success===!0){let t=Zn(n.workspaceRootDir);if(t&&Xn(n.workspaceRootDir,p.resolve(e),t.config))return!0}return!1}function wr(e,t){t!=null&&(e.pyprojectToml=t);for(let t of Vn)if(t===`uv`){let t=xr(e);if(t)return t}else if(t===`pip`){let t=Sr(e);if(t)return t}return{name:`pip`,installCommands:[],execPrefix:``,isStandalone:!0}}function Tr(e=process.cwd(),t,n){let r=n?.ctx??ir(e);return n?.isProject??Cr(e,{ctx:r,hasSource:n?.hasSource})?wr(r,t):null}function Er(e){if(!Array.isArray(e))throw Error(`Invalid Python environment: "pmInfo.installCommands" must be an array`);for(let t of e){if(!t||typeof t!=`object`)throw Error(`Invalid Python environment: malformed "installCommands" item`);let e=t;if(typeof e.executable!=`string`||!e.executable.trim()||!Array.isArray(e.args)||!e.args.every(e=>typeof e==`string`))throw Error(`Invalid Python environment: malformed "installCommands" item`)}}function Dr(e,t=`Invalid Python environment: "pmInfo" must be an object`){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(t);let n=e;if(n.name!==`uv`&&n.name!==`pip`)throw Error(`Invalid Python environment: pmInfo name must be "uv" or "pip"`);return Er(n.installCommands),n}function Or(e){if(!process.argv[1])return!1;try{return l(e)===f.realpathSync(process.argv[1])}catch{return!1}}async function kr(e,t,n=process.platform){let r=p.join(e,`node_modules`,`.bin`),i=/* @__PURE__ */ new Set([`.cmd`,`.bat`,`.exe`]);if(n===`win32`){let e=p.extname(t).toLowerCase();if(e){if(!i.has(e))return;let n=p.join(r,t);if(f.existsSync(n))return n}else for(let e of[`.cmd`,`.bat`,`.exe`,``]){let n=p.join(r,`${t}${e}`);if(f.existsSync(n))return n}}else{let e=p.join(r,t);if(f.existsSync(e))return e}let a=await Vt(t,!1);if(a){if(n===`win32`){let e=p.extname(a).toLowerCase();if(e&&!i.has(e))return}return a}}var Ar=class{platform;constructor(e=process.platform){this.platform=e}async resolveTaskExecutable(e){if(e.toolId===`npm-scripts`)return e.executable;if(e.toolId===`ruff`){if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);return`ruff`}let t=await kr(e.cwd,e.executable,this.platform);if(!t){let t=e.toolName||e.toolId,n=e.requiredPackage||e.executable;throw Error(`Configured tool "${t}" could not run: executable "${e.executable}" is not available in node_modules/.bin or PATH. Please install "${n}" in project dependencies.`)}return t}async executeTasks(e){let t=[];for(let n of e){let e=`${n.executable} ${n.args.join(` `)}`.trim();try{let r=await this.resolveTaskExecutable(n);en(`Executing: ${e}`);let i=n.env?Object.fromEntries(Object.entries({...process.env,...n.env}).filter(e=>e[1]!==void 0)):void 0,a=await Yt(r,n.args,{cwd:n.cwd,env:i,ignoreReturnCode:!0});if(a!==0){let r=n.toolId===`ruff`?`Ruff command "${e}" failed. Check Python and Ruff configuration.`:n.toolId===`npm-scripts`?`Script "${n.args[1]||e}" failed while executing "${e}".`:`Task "${n.id}" (${e}) failed with exit code ${a}.`;t.push({task:n,exitCode:a,error:Error(r)})}else t.push({task:n,exitCode:a})}catch(e){let r=e instanceof Error?e:Error(String(e));t.push({task:n,exitCode:1,error:r})}}return t}};function jr(e,t){return t.has(`autofix`)?!0:e===`autofix`?t.has(`format`)&&t.has(`lint`)&&t.has(`assist`):t.has(e)}function Mr(e,t){let n=[],r=[];for(let i of e)jr(i.capability,t)?r.push(i):n.push(i);return{kept:n,skipped:r}}function Nr(e,t){let n=e.get(t);return n||(n=/* @__PURE__ */ new Set,e.set(t,n)),n}async function Pr(e,t,n,r,i,a,o){for(let s of e){let e=s.adapter,c=Nr(t,s.scope),l=await e.plan(n,r);if(l.length===0)continue;let{kept:u,skipped:d}=Mr(l,c);if(u.length===0)a.push({id:e.id,name:e.name,reason:`all capabilities already covered by higher priority tool`});else{i.push({id:e.id,name:e.name,reason:s.reason});for(let e of u)if(c.add(e.capability),e.capabilities)for(let t of e.capabilities)c.add(t);if(o.push(...u),d.length>0){let t=Array.from(new Set(d.map(e=>e.capability))).join(`, `);a.push({id:e.id,name:e.name,reason:`partially skipped (${t} covered by higher priority tool)`})}}}}async function Fr(e,t,n,r,i,a,o){let s=[];for(let t of e.getStandaloneAdapters()){let e=await t.detect(n),r=t.scope??`standalone`;e.detected?s.push({adapter:t,reason:e.reason,scope:r}):e.reason&&!e.reason.startsWith(`no `)&&a.push({id:t.id,name:t.name,reason:e.reason})}await Pr(s,t,n,r,i,a,o)}function Ir(e){let t=[],n=/* @__PURE__ */ new Set;for(let r of e)n.has(r.id)||(n.add(r.id),t.push(r));return t}async function Lr(e,t,n=`fix`){let r=t.hasPythonSource??or(t.cwd),i=t.jsEnv??fn(t.cwd),a={...t,jsEnv:i,hasPythonSource:r},o=[],s=[],c=[],l=e.getProviders(),u=/* @__PURE__ */ new Map;for(let e of l){if(!await e.detect(a))continue;let t=e.getAdapters(a),r=[];for(let n of t){let t=await n.detect(a),i=n.scope??e.id;t.detected?r.push({adapter:n,reason:t.reason,scope:i}):t.reason&&!t.reason.startsWith(`no `)&&s.push({id:n.id,name:n.name,reason:t.reason})}await Pr(r,u,a,n,o,s,c)}await Fr(e,u,a,n,o,s,c);let d=Ir(c);return{tasks:d,selectedTools:o,skippedTools:s,summary:Rr(e,a,o,s,d)}}function Rr(e,t,n,r,i){let a=[];a.push(`Detected environments:`);let o=t.hasPythonSource??!1,s=t.jsEnv?.hasPackageJson??!1;if(a.push(` Python: ${o}`),a.push(` JavaScript: ${s}`),o&&(a.push(``),a.push(`Python toolchain:`),n.filter(e=>e.id===`ruff`).length>0?a.push(` Ruff: default tool`):a.push(` None`)),s){a.push(``),a.push(`JavaScript toolchain:`);let e=n.filter(e=>e.id!==`ruff`);for(let t of e)a.push(` ${t.name}: selected`);let t=r.filter(e=>e.id!==`ruff`);for(let e of t)a.push(` ${e.name}: skipped (${e.reason})`)}if(a.push(``),a.push(`Execution plan:`),i.length===0?a.push(` (no tasks to execute)`):i.forEach((e,t)=>{let n=e.description||`${e.executable} ${e.args.join(` `)}`;a.push(` ${t+1}. ${n}`)}),r.length>0){a.push(``),a.push(`Skipped:`);for(let e of r)a.push(` - ${e.name}: ${e.reason}`)}return a.join(` +`)}function zr(e){for(let t of[`format:write`,`format:fix`,`format`,`fmt`])if(e[t]&&Xi(e[t],e))return t}function Br(e){if(e[`format:check`]&&Yi(e[`format:check`],e)===`read-only`)return`format:check`;if(e[`fmt:check`]&&Yi(e[`fmt:check`],e)===`read-only`)return`fmt:check`}function Vr(e,t){return t===`fix`?zr(e):Br(e)}function Hr(e,t){if(t===`fix`)return e[`lint:fix`]?`lint:fix`:e[`lint:write`]?`lint:write`:void 0;if(e[`lint:check`]&&Yi(e[`lint:check`],e)===`read-only`)return`lint:check`;if(e.lint&&Yi(e.lint,e)===`read-only`)return`lint`}function Ur(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped)return 0;let r=e[t];return r===`;`||r===` +`?1:r===`&`&&e[t+1]===`&`||r===`|`&&e[t+1]===`|`?2:+(r===`|`)}function Wr(e,t){let n=t;for(;nt?n-1:t}function Gr(e,t){return t.inSingleQuote||t.inDoubleQuote||t.isEscaped?!1:e.length===0||/\s/.test(e[e.length-1])}function Kr(e,t){return t.isEscaped=!1,{ch:e,advance:!0}}function qr(e,t,n,r){let i=e[t];if(n.isEscaped)return{newCmd:r+Kr(i,n).ch,nextIndex:t,sepLen:0};if(i===`\\`&&!n.inSingleQuote)return n.isEscaped=!0,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`'`&&!n.inDoubleQuote)return n.inSingleQuote=!n.inSingleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`"`&&!n.inSingleQuote)return n.inDoubleQuote=!n.inDoubleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`#`&&Gr(r,n))return{newCmd:r,nextIndex:Wr(e,t),sepLen:0};let a=Ur(e,t,n);return{newCmd:r+(a===0?i:``),nextIndex:t,sepLen:a}}function Jr(e){let t=[],n=``,r={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1,hasSyntaxError:!1};for(let i=0;i0?(n.trim()&&t.push(n.trim()),n=``,i+=a.sepLen-1):(n=a.newCmd,i=a.nextIndex)}return(r.inSingleQuote||r.inDoubleQuote||r.isEscaped)&&(r.hasSyntaxError=!0),n.trim()&&t.push(n.trim()),{commands:t,hasSyntaxError:r.hasSyntaxError}}function Yr(e){return Jr(e).commands}function Xr(e,t,n){return t.isEscaped=!1,n+e}function Zr(e,t){return e===`'`&&!t.inDoubleQuote?(t.inSingleQuote=!t.inSingleQuote,!0):e===`"`&&!t.inSingleQuote&&(t.inDoubleQuote=!t.inDoubleQuote,!0)}const Qr=/* @__PURE__ */ new Set([`@`,`*`,`#`,`?`,`-`,`$`,`!`,`0`]);function $r(e,t,n){if(n.inSingleQuote||n.isEscaped||e[t]!==`$`||t+1>=e.length)return!1;let r=e[t+1];return!!(r===`{`||Qr.has(r)||r>=`1`&&r<=`9`||r===`_`||r>=`a`&&r<=`z`||r>=`A`&&r<=`Z`)}function ei(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped||e[t]!==`&`)return!1;let r=t>0?e[t-1]:``,i=t+1`}function ti(e,t,n){if(n.inSingleQuote||n.isEscaped)return!1;let r=e[t];return r==="`"||r===`$`&&t+1`)&&t+1`||r===`<`||r===`&`&&t+1`}function ii(e,t,n){return ei(e,t,n.state)||$r(e,t,n.state)||ti(e,t,n.state)||ni(e,t,n.state)?(n.inspection.hasUnsupportedSyntax=!0,!0):ri(e,t,n.state)?(n.inspection.hasRedirection=!0,n.inspection.hasUnsupportedSyntax=!0,!0):!1}function ai(e,t,n,r){let i=e[t];return n.state.isEscaped?{word:Xr(i,n.state,r),hasChars:!0,skipped:!1}:i===`\\`&&!n.state.inSingleQuote?(n.state.isEscaped=!0,{word:r,hasChars:!1,skipped:!0}):(ii(e,t,n),Zr(i,n.state)?{word:r,hasChars:!0,skipped:!0}:{word:r+i,hasChars:!0,skipped:!1})}function oi(e){let t={tokens:[],hasUnsupportedSyntax:!1,hasRedirection:!1},n={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1},r={inspection:t,state:n},i=``,a=!1;for(let o=0;o0&&n.push(t)}return n}function pi(e,t,n={},r=/* @__PURE__ */ new Set){if(!e||!t)return!1;let i=fi(n[e]===void 0?e:n[e]);for(let e of i){if(di(e,t))return!0;let i=Vi(e);if(i){if(i===t)return!0;if(!r.has(i)&&n[i]!==void 0){r.add(i);try{if(pi(n[i],t,n,r))return!0}finally{r.delete(i)}}}let a=Hi(e);if(a!==void 0&&pi(a,t,n,r))return!0}return!1}function mi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function hi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function gi(e){let[t]=e;return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||(e===`--fix`||e.startsWith(`--fix=`))&&(t!==`eslint`||e!==`--fix-dry-run`))}function _i(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function vi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function yi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function bi(e){let[t]=e;return t===`eslint`&&e.some(e=>(e===`--fix`||e.startsWith(`--fix=`))&&e!==`--fix-dry-run`)}function xi(e){let[t]=e;return t===`oxlint`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Si(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Ci(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function wi(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:!e.some(e=>e===`--check`||e===`-c`)}function Ti(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Ei(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)&&e!==`--fix-dry-run`||e===`-o`||e.startsWith(`-o=`)||e===`--output-file`||e.startsWith(`--output-file=`)||e===`--cache`||e===`--cache-file`||e.startsWith(`--cache-file=`)||e===`--cache-location`||e.startsWith(`--cache-location=`))}function Di(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--cache`||e===`--cache-location`||e.startsWith(`--cache-location=`)||e===`--insert-pragma`)}function Oi(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`)||e===`--reporter-file`||e.startsWith(`--reporter-file=`)||e===`--log-file`||e.startsWith(`--log-file=`))}function ki(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)||e===`--fix-suggestions`||e===`--fix-dangerously`||e===`--init`)}function Ai(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--init`||e===`--migrate`||e.startsWith(`--migrate=`))}function ji(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`--check`||e===`-c`||e===`--list-different`||e===`-l`)&&!Di(e)}function Mi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function Ni(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:!Oi(e)}function Pi(e){let[t]=e;return t===`eslint`&&!Ei(e)}function Fi(e){let[t]=e;return t===`oxlint`&&!ki(e)}function Ii(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:!Oi(e)}function Li(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:!Oi(e)}function Ri(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function zi(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:!ki(e)}function Bi(e){let[t,n]=e;return t!==`vp`||n!==`check`?!1:!e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Vi(e){if(e.length===0)return;let[t,n,r]=e;if((t===`npm`||t===`pnpm`||t===`yarn`||t===`bun`)&&n===`run`&&r)return r;if((t===`pnpm`||t===`bun`||t===`yarn`)&&n&&!n.startsWith(`-`))return n}function Hi(e){if(e.length>=3&&(e[0]===`sh`||e[0]===`bash`)&&e[1]===`-c`)return e[2]}function Ui(e){if(e.length===0)return e;let[t]=e;if(t!==`cross-env`&&t!==`cross-env-shell`)return e;let n=1;for(;n{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Xi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?_i(e)||vi(e)||yi(e)||wi(e):Xi(i,t,n)})}function Zi(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Zi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?bi(e)||xi(e)||Si(e)||Ti(e):Zi(i,t,n)})}function Qi(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Qi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);if(i!==void 0)return Qi(i,t,n);if(Ci(e))return!0;let[a,o]=e;return a===`vp`&&o===`check`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))})}function $i(e,t,n,r){return t&&pi(e,t,n)?!0:r(e)}function ea(e,t,n,r,i){let a=$i(t,r,e,t=>Xi(t,e)),o=$i(t,i,e,t=>Zi(t,e)),s=Qi(t,e);return a&&o?[{capability:`format`,capabilities:[`format`,`lint`],scriptName:n}]:a&&!s?[{capability:`format`,scriptName:n}]:o&&!s?[{capability:`lint`,scriptName:n}]:s?[{capability:`autofix`,scriptName:n}]:[{capability:`typecheck`,capabilities:[],scriptName:n}]}function ta(e,t){return Xi(t[e],t)?{capability:`format`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function na(e,t){return Zi(t[e],t)?{capability:`lint`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function ra(e,t,n){let r=[];return e&&r.push(ta(e,n)),t&&r.push(na(t,n)),r}function ia(e,t,n,r,i){r&&mi(t,n,r)&&e.push(ta(r,t)),i&&hi(t,n,i)&&e.push(na(i,t))}function aa(e){let t=e.fix?`fix`:e[`check:fix`]?`check:fix`:void 0,n=Vr(e,`fix`),r=Hr(e,`fix`);if(!t)return ra(n,r,e);let i=ea(e,e[t]||``,t,n,r);return ia(i,e,t,n,r),i}function oa(e){let t=[],n=Vr(e,`check`),r=Hr(e,`check`);return n&&t.push({capability:`format`,scriptName:n}),r&&t.push({capability:`lint`,scriptName:r}),t}function sa(e,t){return t===`fix`?aa(e):oa(e)}var ca=class{id=`npm-scripts`;name=`package.json scripts`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson?.scripts;if(!t||Object.keys(t).length===0)return{detected:!1,reason:`no scripts declared in package.json`};let n=sa(t,`fix`),r=sa(t,`check`),i=[...n,...r];return i.length>0?{detected:!0,reason:`found supported scripts: ${Array.from(new Set(i.map(e=>`"${e.scriptName}"`))).join(`, `)}`}:{detected:!1,reason:`no supported autofix or check scripts found in package.json`}}plan(e,t){let n=sa(e.jsEnv?.packageJson?.scripts||{},t),r=cn(e.jsPm||`npm`);return n.map(n=>({id:`script-${n.scriptName}`,toolId:this.id,capability:n.capability,capabilities:n.capabilities,executable:r,args:[`run`,n.scriptName],cwd:e.cwd,mode:t,description:`package.json script: ${r} run ${n.scriptName}`}))}};function la(e){return e?Object.values(e).some(t=>Wi(t,e)):!1}function ua(e,t){return e?!!(e.dependencies?.[t]||e.devDependencies?.[t]||e.peerDependencies?.[t]||e.optionalDependencies?.[t]):!1}function da(e,t){for(let n of t)if(f.existsSync(p.join(e,n)))return!0;return!1}var fa=class{id=`vite-plus`;name=`Vite+`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sn(t),r=da(e.cwd,[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.cjs`]);return n||r&&la(t?.scripts)?{detected:!0,reason:`Vite+ dependency and/or configuration detected`}:{detected:!1,reason:`no Vite+ dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`vite-plus-fmt`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp fmt`},{id:`vite-plus-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`,`--fix`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp lint --fix`}]:[{id:`vite-plus-fmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`,`--check`],cwd:e.cwd,mode:`check`,description:`Vite+: vp fmt --check`},{id:`vite-plus-lint`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`],cwd:e.cwd,mode:`check`,description:`Vite+: vp lint`}]}},pa=class{id=`biome`;name=`Biome`;capabilities=[`format`,`lint`,`assist`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`@biomejs/biome`),r=da(e.cwd,[`biome.json`,`biome.jsonc`]);return n&&r?{detected:!0,reason:`Biome dependency and configuration detected`}:r?{detected:!0,reason:`Biome configuration detected`}:n?{detected:!1,reason:`Biome dependency present without configuration file`}:{detected:!1,reason:`no Biome dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`biome-format-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: format --write .`},{id:`biome-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: lint --write .`},{id:`biome-assist-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--write`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: safe assist actions (--write)`}]:[{id:`biome-format-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: format .`},{id:`biome-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: lint .`},{id:`biome-assist-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: check assist actions`}]}},ma=class{id=`prettier`;name=`Prettier`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`prettier`),r=!!t?.prettier,i=da(e.cwd,[`.prettierrc`,`.prettierrc.json`,`.prettierrc.yml`,`.prettierrc.yaml`,`.prettierrc.json5`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`]);return n&&(r||i)?{detected:!0,reason:`Prettier dependency and configuration detected`}:r||i?{detected:!0,reason:`Prettier configuration detected`}:n?{detected:!1,reason:`Prettier dependency present without configuration`}:{detected:!1,reason:`no Prettier dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`prettier-format`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Prettier: format`}]:[{id:`prettier-check`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Prettier: format check`}]}},ha=class{id=`eslint`;name=`ESLint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`eslint`),r=!!t?.eslintConfig,i=da(e.cwd,[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yaml`,`.eslintrc.yml`]);return n&&(r||i)?{detected:!0,reason:`ESLint dependency and configuration detected`}:r||i?{detected:!0,reason:`ESLint configuration detected`}:n?{detected:!1,reason:`ESLint dependency present without configuration`}:{detected:!1,reason:`no ESLint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`eslint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`ESLint: lint autofix`}]:[{id:`eslint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`ESLint: lint check`}]}},ga=class{id=`oxlint`;name=`Oxlint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`oxlint`),r=da(e.cwd,[`.oxlintrc.json`,`oxlint.json`,`oxlint.config.ts`,`oxlint.config.js`]);return n&&r?{detected:!0,reason:`Oxlint dependency and configuration detected`}:r?{detected:!0,reason:`Oxlint configuration detected`}:n?{detected:!1,reason:`Oxlint dependency present without configuration`}:{detected:!1,reason:`no Oxlint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxlint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxlint: lint autofix`}]:[{id:`oxlint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`Oxlint: lint check`}]}},_a=class{id=`oxfmt`;name=`Oxfmt`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`oxfmt`),r=da(e.cwd,[`.oxfmtrc.json`,`oxfmt.json`,`oxfmt.config.ts`,`oxfmt.config.js`]);return n&&r?{detected:!0,reason:`Oxfmt dependency and configuration detected`}:r?{detected:!0,reason:`Oxfmt configuration detected`}:n?{detected:!1,reason:`Oxfmt dependency present without configuration`}:{detected:!1,reason:`no Oxfmt dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxfmt-format`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxfmt: format`}]:[{id:`oxfmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Oxfmt: format check`}]}},va=class{id=`javascript`;name=`JavaScript/TypeScript`;scriptAdapter=new ca;vitePlusAdapter=new fa;biomeAdapter=new pa;prettierAdapter=new ma;eslintAdapter=new ha;oxlintAdapter=new ga;oxfmtAdapter=new _a;detect(e){return!!e.jsEnv?.hasPackageJson}getAdapters(e){return[this.scriptAdapter,this.vitePlusAdapter,this.biomeAdapter,this.oxfmtAdapter,this.prettierAdapter,this.oxlintAdapter,this.eslintAdapter]}},ya=class{id=`ruff`;name=`Ruff`;capabilities=[`lint`,`format`];detect(e){return e.hasPythonSource??or(e.cwd)?{detected:!0,reason:`default Python toolchain`}:{detected:!1,reason:`no Python source files detected`}}plan(e,t){let n=[];return t===`fix`?n.push({id:`ruff-lint-fix`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: lint autofix`},{id:`ruff-format`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: format`}):n.push({id:`ruff-lint-check`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: lint check`},{id:`ruff-format-check`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: format check`}),n}},ba=class{id=`python`;name=`Python`;ruffAdapter=new ya;detect(e){return e.hasPythonSource??or(e.cwd)}getAdapters(e){return[this.ruffAdapter]}},xa=class{providers=/* @__PURE__ */ new Map;standaloneAdapters=/* @__PURE__ */ new Map;registerProvider(e){this.providers.set(e.id,e)}getProvider(e){return this.providers.get(e)}getProviders(){return Array.from(this.providers.values())}registerAdapter(e){this.standaloneAdapters.set(e.id,e)}getAdapter(e){return this.standaloneAdapters.get(e)}getStandaloneAdapters(){return Array.from(this.standaloneAdapters.values())}clear(){this.providers.clear(),this.standaloneAdapters.clear()}};function Sa(){let e=new xa;return e.registerProvider(new ba),e.registerProvider(new va),e}const Ca=Sa();async function wa(e,t=process.cwd()){let n=`${e.command} ${e.args.join(` `)}`.trim();if(en(`Installing JS dependencies: ${n}`),await Yt(e.command,e.args,{cwd:t,ignoreReturnCode:!0})!==0)throw Error(`JS dependency installation failed executing "${n}". Check dependency constraints or lockfile compatibility.`)}async function Ta(e=process.cwd()){let t=fn(e);if(!t.hasPackageJson){en(`No package.json found. Skipping scripts.`);return}if(t.packageJsonError)throw Error(t.packageJsonError);let n=cn(process.env.PACKAGE_MANAGER||_n(t).name),r=(await Lr(Ca,{cwd:e,jsEnv:t,jsPm:n,hasPythonSource:!1},`fix`)).tasks.filter(e=>e.toolId!==`ruff`);if(r.length===0){en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`);return}await wa(vn(n),e);let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}}async function Ea(e,t,n=process.cwd()){let r=`${e} ${t.join(` `)}`.trim();if(en(`Executing: ${r}`),await Yt(e,t,{cwd:n,ignoreReturnCode:!0})!==0)throw Error(`Python command "${r}" failed. Check Python environment and dependency configuration.`)}async function Da(e,t=process.cwd()){Dr(e,`Invalid Python environment: "pmInfo" must be an object`);let n=e.name===`pip`?`pip`:e.name;if(!await Vt(n,!1)&&!e.isStandalone){let e=`Required Python package manager '${n}' is not available in PATH.`;throw Error(e)}if(!e.isStandalone&&e.installCommands.length>0){let n=e.installCommands;en(`Installing Python dependencies: ${n.map(e=>`${e.executable} ${e.args.join(` `)}`).join(` && `)}`);for(let{executable:e,args:r}of n)await Ea(e,r,t)}}async function Oa(e=process.cwd(),t,n){if(!(t??or(e)))return;let r;if(n)r=n;else{if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);r=(await Lr(Ca,{cwd:e,hasPythonSource:!0},`fix`)).tasks.filter(e=>e.toolId===`ruff`)}let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}}async function ka(e,t){if(process.env.JS_SETUP_OUTCOME===`failure`||process.env.NODE_SETUP_OUTCOME===`failure`||process.env.BUN_SETUP_OUTCOME===`failure`||process.env.PNPM_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`JavaScript runtime or package manager setup failed.`);try{if(t){let n=fn(e);if(!n.hasPackageJson)return en(`No package.json found. Skipping scripts.`),null;if(n.packageJsonError)throw Error(n.packageJsonError);if(t.length===0)return en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`),null;await wa(vn(cn(process.env.PACKAGE_MANAGER||_n(n).name)),e);let r=(await new Ar().executeTasks(t)).filter(e=>e.error);if(r.length>0){let e=r.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}return null}return await Ta(e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Aa(e,t){if(process.env.PYTHON_SETUP_OUTCOME===`failure`||process.env.UV_SETUP_OUTCOME===`failure`||process.env.PY_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Python runtime or package manager setup failed.`);let n=t&&`pmInfo`in t?t.pmInfo:Tr(e,void 0,{ctx:t?.ctx,hasSource:t?.hasSource});if(!n)return null;try{return await Da(n,e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function ja(e,t,n){if(process.env.RUFF_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Ruff setup failed.`);try{return await Oa(e,t,n),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Ma(e,t,n){let r=t??or(e);if(!r)return[];let i=[],a=ir(e),o=await Aa(e,{ctx:a,hasSource:!0,pmInfo:Tr(e,void 0,{ctx:a,hasSource:!0,isProject:!0})});o&&i.push(o);let s=await ja(e,r,n);return s&&i.push(s),i}async function Na(e=process.cwd()){let t=or(e),n;try{let r=fn(e),i={cwd:e,jsEnv:r,jsPm:cn(process.env.PACKAGE_MANAGER||_n(r).name),hasPythonSource:t};n=await Lr(Ca,i,`fix`),en(n.summary)}catch{}let r=[],i=n?n.tasks.filter(e=>e.toolId!==`ruff`):void 0,a=n?n.tasks.filter(e=>e.toolId===`ruff`):void 0,o=await ka(e,i);o&&r.push(o);let s=await Ma(e,t,a);r.push(...s),r.length>0&&(Zt(`Failed to run scripts: ${r.map(e=>e.message).join(` +`)}`),process.env.NODE_ENV!==`test`&&process.exit(1))}process.env.NODE_ENV!==`test`&&Or(import.meta.url)&&Na();export{Ta as executeJsWorkflow,Da as executePythonWorkflow,Oa as executeRuffAutofix,Na as run,cn as sanitizePackageManager}; \ No newline at end of file diff --git a/src/autofix/adapters/javascript/script-adapter.ts b/src/autofix/adapters/javascript/script-adapter.ts index fa6e9bc0..5d50e068 100644 --- a/src/autofix/adapters/javascript/script-adapter.ts +++ b/src/autofix/adapters/javascript/script-adapter.ts @@ -742,13 +742,99 @@ function extractDelegatedTarget(tokens: string[]): string | undefined { return undefined; } -function extractShellWrapperScript(tokens: string[]): string | undefined { +export function extractShellWrapperScript(tokens: string[]): string | undefined { if (tokens.length >= 3 && (tokens[0] === "sh" || tokens[0] === "bash") && tokens[1] === "-c") { return tokens[2]; } return undefined; } +/** + * Unwraps environment wrapper commands like `cross-env` or `cross-env-shell`, + * stripping initial flags and subsequent environment variable assignments + * to retrieve the target command tokens. + */ +export function unwrapEnvironmentWrapper(tokens: string[]): string[] { + if (tokens.length === 0) return tokens; + const [exe] = tokens; + if (exe !== "cross-env" && exe !== "cross-env-shell") { + return tokens; + } + + let i = 1; + while (i < tokens.length) { + const token = tokens[i]; + if (token.startsWith("-")) { + i++; + continue; + } + if (isEnvAssignment(token)) { + i++; + continue; + } + break; + } + return tokens.slice(i); +} + +/** + * Checks whether an invocation (or nested wrapped invocations) executes the `vp` command. + * Supports direct invocations, environment wrappers (cross-env), shell wrappers (sh -c, bash -c), + * package-manager execution wrappers (npx, bunx, pnpm exec, etc.), and script delegations. + */ +export function hasVitePlusCommand( + scriptBody: string, + scripts: Record = {}, + activePath: Set = new Set(), +): boolean { + if (!scriptBody) return false; + const invocations = parseCommandInvocations(scriptBody); + + for (const rawTokens of invocations) { + const tokens = unwrapEnvironmentWrapper(rawTokens); + if (tokens.length === 0) continue; + + if (tokens[0] === "vp") { + return true; + } + + // Package-manager runner wrappers: npx vp, bunx vp, pnpm dlx vp, yarn dlx vp, npm exec vp, pnpm exec vp + if ((tokens[0] === "npx" || tokens[0] === "bunx") && tokens[1] === "vp") { + return true; + } + if ( + (tokens[0] === "npm" || tokens[0] === "pnpm" || tokens[0] === "yarn") && + (tokens[1] === "exec" || tokens[1] === "dlx") && + tokens[2] === "vp" + ) { + return true; + } + + // Shell wrappers: sh -c "...", bash -c "..." + const wrapped = extractShellWrapperScript(tokens); + if (wrapped !== undefined) { + if (hasVitePlusCommand(wrapped, scripts, activePath)) { + return true; + } + } + + // Package-manager script delegation + const target = extractDelegatedTarget(tokens); + if (target && !activePath.has(target) && scripts[target]) { + activePath.add(target); + try { + if (hasVitePlusCommand(scripts[target], scripts, activePath)) { + return true; + } + } finally { + activePath.delete(target); + } + } + } + + return false; +} + function isKnownWriteCommand(tokens: string[]): boolean { return ( isPrettierWrite(tokens) || diff --git a/src/autofix/adapters/javascript/tools.ts b/src/autofix/adapters/javascript/tools.ts index 1452499e..6645e141 100644 --- a/src/autofix/adapters/javascript/tools.ts +++ b/src/autofix/adapters/javascript/tools.ts @@ -11,13 +11,12 @@ import type { } from "../../types.js"; import { hasVitePlusDependency, type JsPackageManifest } from "../../../javascript-env.js"; -import { parseCommandInvocations } from "./script-adapter.js"; +import { hasVitePlusCommand } from "./script-adapter.js"; function hasVitePlusScript(scripts?: Record): boolean { if (!scripts) return false; return Object.values(scripts).some((scriptBody) => { - const invocations = parseCommandInvocations(scriptBody); - return invocations.some((tokens) => tokens[0] === "vp"); + return hasVitePlusCommand(scriptBody, scripts); }); } diff --git a/src/autofix/planner.ts b/src/autofix/planner.ts index eceb44f9..34a5b3df 100644 --- a/src/autofix/planner.ts +++ b/src/autofix/planner.ts @@ -14,6 +14,7 @@ import { hasPythonSource } from "../python-env.js"; interface CandidateTool { adapter: ToolAdapter; reason?: string; + scope: string; } function isTaskCapabilityCovered( @@ -54,9 +55,21 @@ function filterCandidateTasks( return { kept, skipped }; } +function getOrCreateScopeCapabilities( + coveredCapabilitiesByScope: Map>, + scope: string, +): Set { + let caps = coveredCapabilitiesByScope.get(scope); + if (!caps) { + caps = new Set(); + coveredCapabilitiesByScope.set(scope, caps); + } + return caps; +} + async function processCandidateTools( candidateTools: CandidateTool[], - providerCapabilities: Set, + coveredCapabilitiesByScope: Map>, context: ProjectContext, mode: ExecutionMode, selectedTools: Array<{ id: string; name: string; reason?: string }>, @@ -65,13 +78,17 @@ async function processCandidateTools( ): Promise { for (const candidate of candidateTools) { const adapter = candidate.adapter; + const scopeCapabilities = getOrCreateScopeCapabilities( + coveredCapabilitiesByScope, + candidate.scope, + ); const plannedTasks = await adapter.plan(context, mode); if (plannedTasks.length === 0) { continue; } - const { kept, skipped } = filterCandidateTasks(plannedTasks, providerCapabilities); + const { kept, skipped } = filterCandidateTasks(plannedTasks, scopeCapabilities); if (kept.length === 0) { skippedTools.push({ @@ -84,10 +101,10 @@ async function processCandidateTools( selectedTools.push({ id: adapter.id, name: adapter.name, reason: candidate.reason }); for (const task of kept) { - providerCapabilities.add(task.capability); + scopeCapabilities.add(task.capability); if (task.capabilities) { for (const cap of task.capabilities) { - providerCapabilities.add(cap); + scopeCapabilities.add(cap); } } } @@ -106,7 +123,7 @@ async function processCandidateTools( async function processStandaloneAdapters( registry: AutofixRegistry, - coveredCapabilities: Set, + coveredCapabilitiesByScope: Map>, context: ProjectContext, mode: ExecutionMode, selectedTools: Array<{ id: string; name: string; reason?: string }>, @@ -116,8 +133,9 @@ async function processStandaloneAdapters( const candidateTools: CandidateTool[] = []; for (const adapter of registry.getStandaloneAdapters()) { const result = await adapter.detect(context); + const scope = adapter.scope ?? "standalone"; if (result.detected) { - candidateTools.push({ adapter, reason: result.reason }); + candidateTools.push({ adapter, reason: result.reason, scope }); } else if (result.reason && !result.reason.startsWith("no ")) { skippedTools.push({ id: adapter.id, name: adapter.name, reason: result.reason }); } @@ -125,7 +143,7 @@ async function processStandaloneAdapters( await processCandidateTools( candidateTools, - coveredCapabilities, + coveredCapabilitiesByScope, context, mode, selectedTools, @@ -174,7 +192,7 @@ export async function planExecution( const tasks: ExecutionTask[] = []; const providers = registry.getProviders(); - const coveredCapabilities = new Set(); + const coveredCapabilitiesByScope = new Map>(); for (const provider of providers) { const isDetected = await provider.detect(effectiveContext); @@ -188,8 +206,9 @@ export async function planExecution( // Detect tools for (const adapter of adapters) { const result = await adapter.detect(effectiveContext); + const scope = adapter.scope ?? provider.id; if (result.detected) { - candidateTools.push({ adapter, reason: result.reason }); + candidateTools.push({ adapter, reason: result.reason, scope }); } else if (result.reason && !result.reason.startsWith("no ")) { skippedTools.push({ id: adapter.id, name: adapter.name, reason: result.reason }); } @@ -197,7 +216,7 @@ export async function planExecution( await processCandidateTools( candidateTools, - coveredCapabilities, + coveredCapabilitiesByScope, effectiveContext, mode, selectedTools, @@ -208,7 +227,7 @@ export async function planExecution( await processStandaloneAdapters( registry, - coveredCapabilities, + coveredCapabilitiesByScope, effectiveContext, mode, selectedTools, diff --git a/src/autofix/types.ts b/src/autofix/types.ts index 5dd7ae71..b09db540 100644 --- a/src/autofix/types.ts +++ b/src/autofix/types.ts @@ -38,6 +38,7 @@ export interface ToolAdapter { id: string; name: string; capabilities: readonly Capability[]; + scope?: string; detect(context: ProjectContext): Promise | AdapterDetectionResult; diff --git a/tests/autofix-architecture.test.ts b/tests/autofix-architecture.test.ts index c0c52138..edf944a1 100644 --- a/tests/autofix-architecture.test.ts +++ b/tests/autofix-architecture.test.ts @@ -1705,12 +1705,93 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { expect(plan.tasks.map((t) => t.id)).toContain("vite-plus-lint-fix"); }); + it("detects Vite+ through command wrappers: cross-env, sh -c, bash -c, and runner wrappers", async () => { + // 1. cross-env + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + format: "cross-env NODE_ENV=production vp fmt", + }, + }), + ); + fs.writeFileSync(path.join(tempDir, "vite.config.ts"), "export default {};"); + + const registry = createDefaultRegistry(); + const planCrossEnv = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planCrossEnv.selectedTools.map((t) => t.id)).toContain("vite-plus"); + + // 2. cross-env-shell + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + format: "cross-env-shell NODE_ENV=production vp fmt", + }, + }), + ); + const planCrossEnvShell = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planCrossEnvShell.selectedTools.map((t) => t.id)).toContain("vite-plus"); + + // 3. sh -c + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + check: "sh -c 'vp check'", + }, + }), + ); + const planSh = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planSh.selectedTools.map((t) => t.id)).toContain("vite-plus"); + + // 4. bash -c + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + fmt: "bash -c 'vp fmt'", + }, + }), + ); + const planBash = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planBash.selectedTools.map((t) => t.id)).toContain("vite-plus"); + + // 5. npx vp / bunx vp / pnpm exec vp + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + fmt1: "npx vp fmt", + fmt2: "bunx vp fmt", + fmt3: "pnpm exec vp fmt", + }, + }), + ); + const planRunners = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planRunners.selectedTools.map((t) => t.id)).toContain("vite-plus"); + + // 6. script delegation invoking vp + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + all: "npm run vp-task", + "vp-task": "vp fmt", + }, + }), + ); + const planDelegation = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planDelegation.selectedTools.map((t) => t.id)).toContain("vite-plus"); + }); + it("prevents false positive when 'vp ' only appears inside echo or descriptive string", async () => { fs.writeFileSync( path.join(tempDir, "package.json"), JSON.stringify({ scripts: { help: 'echo "vp is not installed"', + info: 'echo "run vp fmt later"', }, }), ); @@ -1773,14 +1854,57 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { }); }); + describe("Multi-Language Monorepo Capability Isolation", () => { + it("preserves independent tasks for Python (Ruff) and JavaScript (Prettier/ESLint) without mutual suppression", async () => { + // Python source file + fs.writeFileSync(path.join(tempDir, "app.py"), "print('hello')\n"); + + // JS configuration with prettier and eslint + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + "format:write": "prettier --write .", + "lint:fix": "eslint --fix .", + }, + }), + ); + + const registry = createDefaultRegistry(); + const plan = await planExecution(registry, { cwd: tempDir, hasPythonSource: true }, "fix"); + + // Verify Python tasks are scheduled (Ruff lint and format) + expect(plan.tasks.some((t) => t.id === "ruff-lint-fix")).toBe(true); + expect(plan.tasks.some((t) => t.id === "ruff-format")).toBe(true); + + // Verify JavaScript tasks are NOT suppressed by Python's lint/format capabilities + expect(plan.tasks.some((t) => t.id === "script-format:write")).toBe(true); + expect(plan.tasks.some((t) => t.id === "script-lint:fix")).toBe(true); + + // Verify plan contains all 4 tasks + expect(plan.tasks.map((t) => t.id)).toEqual([ + "ruff-lint-fix", + "ruff-format", + "script-format:write", + "script-lint:fix", + ]); + + // Summary contains both Python and JavaScript toolchains + expect(plan.summary).toContain("Python toolchain:"); + expect(plan.summary).toContain("Ruff: default tool"); + expect(plan.summary).toContain("JavaScript toolchain:"); + }); + }); + describe("Standalone Adapter Conflict Resolution", () => { - it("skips a standalone adapter task when its capability is already covered by a regular adapter", async () => { + it("skips a standalone adapter task when its capability is already covered by a regular adapter in the same scope", async () => { const registry = createDefaultRegistry(); class StandaloneFormatAdapter implements ToolAdapter { id = "standalone-fmt"; name = "Standalone Formatter"; capabilities: ["format"] = ["format"]; + scope = "javascript"; detect() { return { detected: true, reason: "standalone formatter config detected" }; } @@ -1926,13 +2050,14 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { expect(plan.selectedTools.map((t) => t.id)).toContain("standalone-typecheck"); }); - it("partially skips overlapping capabilities between standalone and regular adapters", async () => { + it("partially skips overlapping capabilities between standalone and regular adapters in the same scope", async () => { const registry = createDefaultRegistry(); class StandaloneMultiToolAdapter implements ToolAdapter { id = "standalone-multi"; name = "Standalone Multi Tool"; capabilities: ["format", "assist"] = ["format", "assist"]; + scope = "javascript"; detect() { return { detected: true, reason: "multi tool config detected" }; } From 0f508e7f74ed7e3301b2b3624cc97d8a46a6df41 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 10 Nov 2026 07:35:16 +0000 Subject: [PATCH 3/5] fix(autofix): standalone adapter scope semantics and cross-env option parsing - F-01: Clarify and correct standalone adapter scope semantics with explicit conflict domains, defaulting unassigned standalone adapters to isolated per-adapter scopes (standalone:${id}) and unassigned provider adapters to provider.id. - F-02: Implement option-aware parsing in unwrapEnvironmentWrapper for cross-env and cross-env-shell to handle options consuming separate arguments (-f, --file, -c, --config, --env-file), inline values (--option=val), boolean flags, and delimiter -- while failing closed on unrecognized options. - Rebuild dist/autofix.mjs bundle. - Add changeset and comprehensive regression tests. --- dist/autofix.mjs | 14 +-- .../adapters/javascript/script-adapter.ts | 47 +++++++- src/autofix/planner.ts | 2 +- src/autofix/types.ts | 7 ++ tests/autofix-architecture.test.ts | 104 +++++++++++++++++- 5 files changed, 157 insertions(+), 17 deletions(-) diff --git a/dist/autofix.mjs b/dist/autofix.mjs index 3f5ecc45..50438d58 100644 --- a/dist/autofix.mjs +++ b/dist/autofix.mjs @@ -303,11 +303,11 @@ const Vn=[`uv`,`pip`],Hn=[`.git`,`.venv`,`venv`,`env`,`.env`,`virtualenv`,`.virt `?` `:` `,i++;return i=t+1&&e[a]===`\\`;)n++,a--;if(n%2==0)return r+=` `,[r,i+1]}r+=` `,i++}return[r,i]}function dr(e,t,n){let r=` `,i=t+1;for(;i!Un(e))}function mr(e,t){if(!Un(e[`build-system`]))return!1;if(typeof t==`string`){let e=fr(t);return/(?:^|\n)\s*\[\s*build-system\s*\]\s*(?:\n|$)/.test(e)}let n=Object.entries(e[`build-system`]);return n.length===0||n.some(([,e])=>!Un(e))}function hr(e,t){if(pr(e,t)||mr(e,t))return!0;if(Un(e.tool)&&Un(e.tool.uv)){let t=e.tool.uv;return Yn(t.workspace)||Array.isArray(t[`dev-dependencies`])}return!1}function gr(e){return Un(e.tool)&&Un(e.tool.uv)}function _r(e,t){return pr(e,t)||mr(e,t)}function vr(e,t){return p.relative(e,t)||`.`}function yr(e,t){if(!t)throw Error(`Invalid Python project configuration: 'uv.lock' was detected without a valid 'pyproject.toml' project or workspace configuration ('[project]', '[build-system]', or '[tool.uv.workspace]'). 'uv sync' requires a valid 'pyproject.toml' file.`);return{name:`uv`,lockfile:`uv.lock`,configFile:`pyproject.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}}function br(e,t){if(e.hasRequirementsTxt&&e.requirementsDir){let t=vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`));return{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`pip`,`install`,`-r`,t]}],execPrefix:`uv run`}}return t?{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}:null}function xr(e){let t=e.pyprojectToml?.success===!0&&hr(e.pyprojectToml.data,e.pyprojectToml.rawContent),n=e.workspaceRootToml?.success===!0&&hr(e.workspaceRootToml.data,e.workspaceRootToml.rawContent),r=t||n,i=e.uvToml?.success===!0,a=e.pyprojectToml?.success===!0&&gr(e.pyprojectToml.data)||e.workspaceRootToml?.success===!0&&gr(e.workspaceRootToml.data);return e.hasUvLock?yr(e,r):a||i?br(e,r):null}function Sr(e){let t=e.pyprojectToml?.success===!0&&_r(e.pyprojectToml.data,e.pyprojectToml.rawContent);if(!(e.hasRequirementsTxt||e.hasSetupPy||e.hasSetupCfg||t))return null;let n;t?n=`pyproject.toml`:e.hasSetupPy?n=`setup.py`:e.hasSetupCfg&&(n=`setup.cfg`);let r=[],i,a=e.hasSetupPy||e.hasSetupCfg||t,o=e.requirementsDir?vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`)):`requirements.txt`,s=vr(e.cwd,e.projectDir);return e.hasRequirementsTxt&&a?(r=[{executable:`pip`,args:[`install`,`-r`,o]},{executable:`pip`,args:[`install`,`-e`,s]}],i=`requirements.txt`):e.hasRequirementsTxt?(r=[{executable:`pip`,args:[`install`,`-r`,o]}],i=`requirements.txt`):a&&(r=[{executable:`pip`,args:[`install`,`-e`,s]}]),{name:`pip`,lockfile:i,configFile:n,installCommands:r,execPrefix:``}}function Cr(e=process.cwd(),t){if(t?.hasSource??or(e))return!0;let n=t?.ctx??ir(e);if(n.projectDir===n.cwd&&tr(n.cwd)&&(n.pyprojectToml?.success===!0&&hr(n.pyprojectToml.data,n.pyprojectToml.rawContent)||n.hasUvLock||n.hasRequirementsTxt||n.hasSetupPy||n.hasSetupCfg))return!0;if(n.workspaceRootDir&&n.workspaceRootToml?.success===!0){let t=Zn(n.workspaceRootDir);if(t&&Xn(n.workspaceRootDir,p.resolve(e),t.config))return!0}return!1}function wr(e,t){t!=null&&(e.pyprojectToml=t);for(let t of Vn)if(t===`uv`){let t=xr(e);if(t)return t}else if(t===`pip`){let t=Sr(e);if(t)return t}return{name:`pip`,installCommands:[],execPrefix:``,isStandalone:!0}}function Tr(e=process.cwd(),t,n){let r=n?.ctx??ir(e);return n?.isProject??Cr(e,{ctx:r,hasSource:n?.hasSource})?wr(r,t):null}function Er(e){if(!Array.isArray(e))throw Error(`Invalid Python environment: "pmInfo.installCommands" must be an array`);for(let t of e){if(!t||typeof t!=`object`)throw Error(`Invalid Python environment: malformed "installCommands" item`);let e=t;if(typeof e.executable!=`string`||!e.executable.trim()||!Array.isArray(e.args)||!e.args.every(e=>typeof e==`string`))throw Error(`Invalid Python environment: malformed "installCommands" item`)}}function Dr(e,t=`Invalid Python environment: "pmInfo" must be an object`){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(t);let n=e;if(n.name!==`uv`&&n.name!==`pip`)throw Error(`Invalid Python environment: pmInfo name must be "uv" or "pip"`);return Er(n.installCommands),n}function Or(e){if(!process.argv[1])return!1;try{return l(e)===f.realpathSync(process.argv[1])}catch{return!1}}async function kr(e,t,n=process.platform){let r=p.join(e,`node_modules`,`.bin`),i=/* @__PURE__ */ new Set([`.cmd`,`.bat`,`.exe`]);if(n===`win32`){let e=p.extname(t).toLowerCase();if(e){if(!i.has(e))return;let n=p.join(r,t);if(f.existsSync(n))return n}else for(let e of[`.cmd`,`.bat`,`.exe`,``]){let n=p.join(r,`${t}${e}`);if(f.existsSync(n))return n}}else{let e=p.join(r,t);if(f.existsSync(e))return e}let a=await Vt(t,!1);if(a){if(n===`win32`){let e=p.extname(a).toLowerCase();if(e&&!i.has(e))return}return a}}var Ar=class{platform;constructor(e=process.platform){this.platform=e}async resolveTaskExecutable(e){if(e.toolId===`npm-scripts`)return e.executable;if(e.toolId===`ruff`){if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);return`ruff`}let t=await kr(e.cwd,e.executable,this.platform);if(!t){let t=e.toolName||e.toolId,n=e.requiredPackage||e.executable;throw Error(`Configured tool "${t}" could not run: executable "${e.executable}" is not available in node_modules/.bin or PATH. Please install "${n}" in project dependencies.`)}return t}async executeTasks(e){let t=[];for(let n of e){let e=`${n.executable} ${n.args.join(` `)}`.trim();try{let r=await this.resolveTaskExecutable(n);en(`Executing: ${e}`);let i=n.env?Object.fromEntries(Object.entries({...process.env,...n.env}).filter(e=>e[1]!==void 0)):void 0,a=await Yt(r,n.args,{cwd:n.cwd,env:i,ignoreReturnCode:!0});if(a!==0){let r=n.toolId===`ruff`?`Ruff command "${e}" failed. Check Python and Ruff configuration.`:n.toolId===`npm-scripts`?`Script "${n.args[1]||e}" failed while executing "${e}".`:`Task "${n.id}" (${e}) failed with exit code ${a}.`;t.push({task:n,exitCode:a,error:Error(r)})}else t.push({task:n,exitCode:a})}catch(e){let r=e instanceof Error?e:Error(String(e));t.push({task:n,exitCode:1,error:r})}}return t}};function jr(e,t){return t.has(`autofix`)?!0:e===`autofix`?t.has(`format`)&&t.has(`lint`)&&t.has(`assist`):t.has(e)}function Mr(e,t){let n=[],r=[];for(let i of e)jr(i.capability,t)?r.push(i):n.push(i);return{kept:n,skipped:r}}function Nr(e,t){let n=e.get(t);return n||(n=/* @__PURE__ */ new Set,e.set(t,n)),n}async function Pr(e,t,n,r,i,a,o){for(let s of e){let e=s.adapter,c=Nr(t,s.scope),l=await e.plan(n,r);if(l.length===0)continue;let{kept:u,skipped:d}=Mr(l,c);if(u.length===0)a.push({id:e.id,name:e.name,reason:`all capabilities already covered by higher priority tool`});else{i.push({id:e.id,name:e.name,reason:s.reason});for(let e of u)if(c.add(e.capability),e.capabilities)for(let t of e.capabilities)c.add(t);if(o.push(...u),d.length>0){let t=Array.from(new Set(d.map(e=>e.capability))).join(`, `);a.push({id:e.id,name:e.name,reason:`partially skipped (${t} covered by higher priority tool)`})}}}}async function Fr(e,t,n,r,i,a,o){let s=[];for(let t of e.getStandaloneAdapters()){let e=await t.detect(n),r=t.scope??`standalone`;e.detected?s.push({adapter:t,reason:e.reason,scope:r}):e.reason&&!e.reason.startsWith(`no `)&&a.push({id:t.id,name:t.name,reason:e.reason})}await Pr(s,t,n,r,i,a,o)}function Ir(e){let t=[],n=/* @__PURE__ */ new Set;for(let r of e)n.has(r.id)||(n.add(r.id),t.push(r));return t}async function Lr(e,t,n=`fix`){let r=t.hasPythonSource??or(t.cwd),i=t.jsEnv??fn(t.cwd),a={...t,jsEnv:i,hasPythonSource:r},o=[],s=[],c=[],l=e.getProviders(),u=/* @__PURE__ */ new Map;for(let e of l){if(!await e.detect(a))continue;let t=e.getAdapters(a),r=[];for(let n of t){let t=await n.detect(a),i=n.scope??e.id;t.detected?r.push({adapter:n,reason:t.reason,scope:i}):t.reason&&!t.reason.startsWith(`no `)&&s.push({id:n.id,name:n.name,reason:t.reason})}await Pr(r,u,a,n,o,s,c)}await Fr(e,u,a,n,o,s,c);let d=Ir(c);return{tasks:d,selectedTools:o,skippedTools:s,summary:Rr(e,a,o,s,d)}}function Rr(e,t,n,r,i){let a=[];a.push(`Detected environments:`);let o=t.hasPythonSource??!1,s=t.jsEnv?.hasPackageJson??!1;if(a.push(` Python: ${o}`),a.push(` JavaScript: ${s}`),o&&(a.push(``),a.push(`Python toolchain:`),n.filter(e=>e.id===`ruff`).length>0?a.push(` Ruff: default tool`):a.push(` None`)),s){a.push(``),a.push(`JavaScript toolchain:`);let e=n.filter(e=>e.id!==`ruff`);for(let t of e)a.push(` ${t.name}: selected`);let t=r.filter(e=>e.id!==`ruff`);for(let e of t)a.push(` ${e.name}: skipped (${e.reason})`)}if(a.push(``),a.push(`Execution plan:`),i.length===0?a.push(` (no tasks to execute)`):i.forEach((e,t)=>{let n=e.description||`${e.executable} ${e.args.join(` `)}`;a.push(` ${t+1}. ${n}`)}),r.length>0){a.push(``),a.push(`Skipped:`);for(let e of r)a.push(` - ${e.name}: ${e.reason}`)}return a.join(` -`)}function zr(e){for(let t of[`format:write`,`format:fix`,`format`,`fmt`])if(e[t]&&Xi(e[t],e))return t}function Br(e){if(e[`format:check`]&&Yi(e[`format:check`],e)===`read-only`)return`format:check`;if(e[`fmt:check`]&&Yi(e[`fmt:check`],e)===`read-only`)return`fmt:check`}function Vr(e,t){return t===`fix`?zr(e):Br(e)}function Hr(e,t){if(t===`fix`)return e[`lint:fix`]?`lint:fix`:e[`lint:write`]?`lint:write`:void 0;if(e[`lint:check`]&&Yi(e[`lint:check`],e)===`read-only`)return`lint:check`;if(e.lint&&Yi(e.lint,e)===`read-only`)return`lint`}function Ur(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped)return 0;let r=e[t];return r===`;`||r===` +`&&e[i]!==`\r`;)r+=` `,i++;return i!Un(e))}function mr(e,t){if(!Un(e[`build-system`]))return!1;if(typeof t==`string`){let e=fr(t);return/(?:^|\n)\s*\[\s*build-system\s*\]\s*(?:\n|$)/.test(e)}let n=Object.entries(e[`build-system`]);return n.length===0||n.some(([,e])=>!Un(e))}function hr(e,t){if(pr(e,t)||mr(e,t))return!0;if(Un(e.tool)&&Un(e.tool.uv)){let t=e.tool.uv;return Yn(t.workspace)||Array.isArray(t[`dev-dependencies`])}return!1}function gr(e){return Un(e.tool)&&Un(e.tool.uv)}function _r(e,t){return pr(e,t)||mr(e,t)}function vr(e,t){return p.relative(e,t)||`.`}function yr(e,t){if(!t)throw Error(`Invalid Python project configuration: 'uv.lock' was detected without a valid 'pyproject.toml' project or workspace configuration ('[project]', '[build-system]', or '[tool.uv.workspace]'). 'uv sync' requires a valid 'pyproject.toml' file.`);return{name:`uv`,lockfile:`uv.lock`,configFile:`pyproject.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}}function br(e,t){if(e.hasRequirementsTxt&&e.requirementsDir){let t=vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`));return{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`pip`,`install`,`-r`,t]}],execPrefix:`uv run`}}return t?{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}:null}function xr(e){let t=e.pyprojectToml?.success===!0&&hr(e.pyprojectToml.data,e.pyprojectToml.rawContent),n=e.workspaceRootToml?.success===!0&&hr(e.workspaceRootToml.data,e.workspaceRootToml.rawContent),r=t||n,i=e.uvToml?.success===!0,a=e.pyprojectToml?.success===!0&&gr(e.pyprojectToml.data)||e.workspaceRootToml?.success===!0&&gr(e.workspaceRootToml.data);return e.hasUvLock?yr(e,r):a||i?br(e,r):null}function Sr(e){let t=e.pyprojectToml?.success===!0&&_r(e.pyprojectToml.data,e.pyprojectToml.rawContent);if(!(e.hasRequirementsTxt||e.hasSetupPy||e.hasSetupCfg||t))return null;let n;t?n=`pyproject.toml`:e.hasSetupPy?n=`setup.py`:e.hasSetupCfg&&(n=`setup.cfg`);let r=[],i,a=e.hasSetupPy||e.hasSetupCfg||t,o=e.requirementsDir?vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`)):`requirements.txt`,s=vr(e.cwd,e.projectDir);return e.hasRequirementsTxt&&a?(r=[{executable:`pip`,args:[`install`,`-r`,o]},{executable:`pip`,args:[`install`,`-e`,s]}],i=`requirements.txt`):e.hasRequirementsTxt?(r=[{executable:`pip`,args:[`install`,`-r`,o]}],i=`requirements.txt`):a&&(r=[{executable:`pip`,args:[`install`,`-e`,s]}]),{name:`pip`,lockfile:i,configFile:n,installCommands:r,execPrefix:``}}function Cr(e=process.cwd(),t){if(t?.hasSource??or(e))return!0;let n=t?.ctx??ir(e);if(n.projectDir===n.cwd&&tr(n.cwd)&&(n.pyprojectToml?.success===!0&&hr(n.pyprojectToml.data,n.pyprojectToml.rawContent)||n.hasUvLock||n.hasRequirementsTxt||n.hasSetupPy||n.hasSetupCfg))return!0;if(n.workspaceRootDir&&n.workspaceRootToml?.success===!0){let t=Zn(n.workspaceRootDir);if(t&&Xn(n.workspaceRootDir,p.resolve(e),t.config))return!0}return!1}function wr(e,t){t!=null&&(e.pyprojectToml=t);for(let t of Vn)if(t===`uv`){let t=xr(e);if(t)return t}else if(t===`pip`){let t=Sr(e);if(t)return t}return{name:`pip`,installCommands:[],execPrefix:``,isStandalone:!0}}function Tr(e=process.cwd(),t,n){let r=n?.ctx??ir(e);return n?.isProject??Cr(e,{ctx:r,hasSource:n?.hasSource})?wr(r,t):null}function Er(e){if(!Array.isArray(e))throw Error(`Invalid Python environment: "pmInfo.installCommands" must be an array`);for(let t of e){if(!t||typeof t!=`object`)throw Error(`Invalid Python environment: malformed "installCommands" item`);let e=t;if(typeof e.executable!=`string`||!e.executable.trim()||!Array.isArray(e.args)||!e.args.every(e=>typeof e==`string`))throw Error(`Invalid Python environment: malformed "installCommands" item`)}}function Dr(e,t=`Invalid Python environment: "pmInfo" must be an object`){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(t);let n=e;if(n.name!==`uv`&&n.name!==`pip`)throw Error(`Invalid Python environment: pmInfo name must be "uv" or "pip"`);return Er(n.installCommands),n}function Or(e){if(!process.argv[1])return!1;try{return l(e)===f.realpathSync(process.argv[1])}catch{return!1}}async function kr(e,t,n=process.platform){let r=p.join(e,`node_modules`,`.bin`),i=/* @__PURE__ */ new Set([`.cmd`,`.bat`,`.exe`]);if(n===`win32`){let e=p.extname(t).toLowerCase();if(e){if(!i.has(e))return;let n=p.join(r,t);if(f.existsSync(n))return n}else for(let e of[`.cmd`,`.bat`,`.exe`,``]){let n=p.join(r,`${t}${e}`);if(f.existsSync(n))return n}}else{let e=p.join(r,t);if(f.existsSync(e))return e}let a=await Vt(t,!1);if(a){if(n===`win32`){let e=p.extname(a).toLowerCase();if(e&&!i.has(e))return}return a}}var Ar=class{platform;constructor(e=process.platform){this.platform=e}async resolveTaskExecutable(e){if(e.toolId===`npm-scripts`)return e.executable;if(e.toolId===`ruff`){if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);return`ruff`}let t=await kr(e.cwd,e.executable,this.platform);if(!t){let t=e.toolName||e.toolId,n=e.requiredPackage||e.executable;throw Error(`Configured tool "${t}" could not run: executable "${e.executable}" is not available in node_modules/.bin or PATH. Please install "${n}" in project dependencies.`)}return t}async executeTasks(e){let t=[];for(let n of e){let e=`${n.executable} ${n.args.join(` `)}`.trim();try{let r=await this.resolveTaskExecutable(n);en(`Executing: ${e}`);let i=n.env?Object.fromEntries(Object.entries({...process.env,...n.env}).filter(e=>e[1]!==void 0)):void 0,a=await Yt(r,n.args,{cwd:n.cwd,env:i,ignoreReturnCode:!0});if(a!==0){let r=n.toolId===`ruff`?`Ruff command "${e}" failed. Check Python and Ruff configuration.`:n.toolId===`npm-scripts`?`Script "${n.args[1]||e}" failed while executing "${e}".`:`Task "${n.id}" (${e}) failed with exit code ${a}.`;t.push({task:n,exitCode:a,error:Error(r)})}else t.push({task:n,exitCode:a})}catch(e){let r=e instanceof Error?e:Error(String(e));t.push({task:n,exitCode:1,error:r})}}return t}};function jr(e,t){return t.has(`autofix`)?!0:e===`autofix`?t.has(`format`)&&t.has(`lint`)&&t.has(`assist`):t.has(e)}function Mr(e,t){let n=[],r=[];for(let i of e)jr(i.capability,t)?r.push(i):n.push(i);return{kept:n,skipped:r}}function Nr(e,t){let n=e.get(t);return n||(n=/* @__PURE__ */ new Set,e.set(t,n)),n}async function Pr(e,t,n,r,i,a,o){for(let s of e){let e=s.adapter,c=Nr(t,s.scope),l=await e.plan(n,r);if(l.length===0)continue;let{kept:u,skipped:d}=Mr(l,c);if(u.length===0)a.push({id:e.id,name:e.name,reason:`all capabilities already covered by higher priority tool`});else{i.push({id:e.id,name:e.name,reason:s.reason});for(let e of u)if(c.add(e.capability),e.capabilities)for(let t of e.capabilities)c.add(t);if(o.push(...u),d.length>0){let t=Array.from(new Set(d.map(e=>e.capability))).join(`, `);a.push({id:e.id,name:e.name,reason:`partially skipped (${t} covered by higher priority tool)`})}}}}async function Fr(e,t,n,r,i,a,o){let s=[];for(let t of e.getStandaloneAdapters()){let e=await t.detect(n),r=t.scope??`standalone:${t.id}`;e.detected?s.push({adapter:t,reason:e.reason,scope:r}):e.reason&&!e.reason.startsWith(`no `)&&a.push({id:t.id,name:t.name,reason:e.reason})}await Pr(s,t,n,r,i,a,o)}function Ir(e){let t=[],n=/* @__PURE__ */ new Set;for(let r of e)n.has(r.id)||(n.add(r.id),t.push(r));return t}async function Lr(e,t,n=`fix`){let r=t.hasPythonSource??or(t.cwd),i=t.jsEnv??fn(t.cwd),a={...t,jsEnv:i,hasPythonSource:r},o=[],s=[],c=[],l=e.getProviders(),u=/* @__PURE__ */ new Map;for(let e of l){if(!await e.detect(a))continue;let t=e.getAdapters(a),r=[];for(let n of t){let t=await n.detect(a),i=n.scope??e.id;t.detected?r.push({adapter:n,reason:t.reason,scope:i}):t.reason&&!t.reason.startsWith(`no `)&&s.push({id:n.id,name:n.name,reason:t.reason})}await Pr(r,u,a,n,o,s,c)}await Fr(e,u,a,n,o,s,c);let d=Ir(c);return{tasks:d,selectedTools:o,skippedTools:s,summary:Rr(e,a,o,s,d)}}function Rr(e,t,n,r,i){let a=[];a.push(`Detected environments:`);let o=t.hasPythonSource??!1,s=t.jsEnv?.hasPackageJson??!1;if(a.push(` Python: ${o}`),a.push(` JavaScript: ${s}`),o&&(a.push(``),a.push(`Python toolchain:`),n.filter(e=>e.id===`ruff`).length>0?a.push(` Ruff: default tool`):a.push(` None`)),s){a.push(``),a.push(`JavaScript toolchain:`);let e=n.filter(e=>e.id!==`ruff`);for(let t of e)a.push(` ${t.name}: selected`);let t=r.filter(e=>e.id!==`ruff`);for(let e of t)a.push(` ${e.name}: skipped (${e.reason})`)}if(a.push(``),a.push(`Execution plan:`),i.length===0?a.push(` (no tasks to execute)`):i.forEach((e,t)=>{let n=e.description||`${e.executable} ${e.args.join(` `)}`;a.push(` ${t+1}. ${n}`)}),r.length>0){a.push(``),a.push(`Skipped:`);for(let e of r)a.push(` - ${e.name}: ${e.reason}`)}return a.join(` +`)}function zr(e){for(let t of[`format:write`,`format:fix`,`format`,`fmt`])if(e[t]&&Qi(e[t],e))return t}function Br(e){if(e[`format:check`]&&Zi(e[`format:check`],e)===`read-only`)return`format:check`;if(e[`fmt:check`]&&Zi(e[`fmt:check`],e)===`read-only`)return`fmt:check`}function Vr(e,t){return t===`fix`?zr(e):Br(e)}function Hr(e,t){if(t===`fix`)return e[`lint:fix`]?`lint:fix`:e[`lint:write`]?`lint:write`:void 0;if(e[`lint:check`]&&Zi(e[`lint:check`],e)===`read-only`)return`lint:check`;if(e.lint&&Zi(e.lint,e)===`read-only`)return`lint`}function Ur(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped)return 0;let r=e[t];return r===`;`||r===` `?1:r===`&`&&e[t+1]===`&`||r===`|`&&e[t+1]===`|`?2:+(r===`|`)}function Wr(e,t){let n=t;for(;nt?n-1:t}function Gr(e,t){return t.inSingleQuote||t.inDoubleQuote||t.isEscaped?!1:e.length===0||/\s/.test(e[e.length-1])}function Kr(e,t){return t.isEscaped=!1,{ch:e,advance:!0}}function qr(e,t,n,r){let i=e[t];if(n.isEscaped)return{newCmd:r+Kr(i,n).ch,nextIndex:t,sepLen:0};if(i===`\\`&&!n.inSingleQuote)return n.isEscaped=!0,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`'`&&!n.inDoubleQuote)return n.inSingleQuote=!n.inSingleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`"`&&!n.inSingleQuote)return n.inDoubleQuote=!n.inDoubleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`#`&&Gr(r,n))return{newCmd:r,nextIndex:Wr(e,t),sepLen:0};let a=Ur(e,t,n);return{newCmd:r+(a===0?i:``),nextIndex:t,sepLen:a}}function Jr(e){let t=[],n=``,r={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1,hasSyntaxError:!1};for(let i=0;i0?(n.trim()&&t.push(n.trim()),n=``,i+=a.sepLen-1):(n=a.newCmd,i=a.nextIndex)}return(r.inSingleQuote||r.inDoubleQuote||r.isEscaped)&&(r.hasSyntaxError=!0),n.trim()&&t.push(n.trim()),{commands:t,hasSyntaxError:r.hasSyntaxError}}function Yr(e){return Jr(e).commands}function Xr(e,t,n){return t.isEscaped=!1,n+e}function Zr(e,t){return e===`'`&&!t.inDoubleQuote?(t.inSingleQuote=!t.inSingleQuote,!0):e===`"`&&!t.inSingleQuote&&(t.inDoubleQuote=!t.inDoubleQuote,!0)}const Qr=/* @__PURE__ */ new Set([`@`,`*`,`#`,`?`,`-`,`$`,`!`,`0`]);function $r(e,t,n){if(n.inSingleQuote||n.isEscaped||e[t]!==`$`||t+1>=e.length)return!1;let r=e[t+1];return!!(r===`{`||Qr.has(r)||r>=`1`&&r<=`9`||r===`_`||r>=`a`&&r<=`z`||r>=`A`&&r<=`Z`)}function ei(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped||e[t]!==`&`)return!1;let r=t>0?e[t-1]:``,i=t+1`}function ti(e,t,n){if(n.inSingleQuote||n.isEscaped)return!1;let r=e[t];return r==="`"||r===`$`&&t+1`)&&t+1`||r===`<`||r===`&`&&t+1`}function ii(e,t,n){return ei(e,t,n.state)||$r(e,t,n.state)||ti(e,t,n.state)||ni(e,t,n.state)?(n.inspection.hasUnsupportedSyntax=!0,!0):ri(e,t,n.state)?(n.inspection.hasRedirection=!0,n.inspection.hasUnsupportedSyntax=!0,!0):!1}function ai(e,t,n,r){let i=e[t];return n.state.isEscaped?{word:Xr(i,n.state,r),hasChars:!0,skipped:!1}:i===`\\`&&!n.state.inSingleQuote?(n.state.isEscaped=!0,{word:r,hasChars:!1,skipped:!0}):(ii(e,t,n),Zr(i,n.state)?{word:r,hasChars:!0,skipped:!0}:{word:r+i,hasChars:!0,skipped:!1})}function oi(e){let t={tokens:[],hasUnsupportedSyntax:!1,hasRedirection:!1},n={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1},r={inspection:t,state:n},i=``,a=!1;for(let o=0;o0&&n.push(t)}return n}function pi(e,t,n={},r=/* @__PURE__ */ new Set){if(!e||!t)return!1;let i=fi(n[e]===void 0?e:n[e]);for(let e of i){if(di(e,t))return!0;let i=Vi(e);if(i){if(i===t)return!0;if(!r.has(i)&&n[i]!==void 0){r.add(i);try{if(pi(n[i],t,n,r))return!0}finally{r.delete(i)}}}let a=Hi(e);if(a!==void 0&&pi(a,t,n,r))return!0}return!1}function mi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function hi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function gi(e){let[t]=e;return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||(e===`--fix`||e.startsWith(`--fix=`))&&(t!==`eslint`||e!==`--fix-dry-run`))}function _i(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function vi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function yi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function bi(e){let[t]=e;return t===`eslint`&&e.some(e=>(e===`--fix`||e.startsWith(`--fix=`))&&e!==`--fix-dry-run`)}function xi(e){let[t]=e;return t===`oxlint`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Si(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Ci(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function wi(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:!e.some(e=>e===`--check`||e===`-c`)}function Ti(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Ei(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)&&e!==`--fix-dry-run`||e===`-o`||e.startsWith(`-o=`)||e===`--output-file`||e.startsWith(`--output-file=`)||e===`--cache`||e===`--cache-file`||e.startsWith(`--cache-file=`)||e===`--cache-location`||e.startsWith(`--cache-location=`))}function Di(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--cache`||e===`--cache-location`||e.startsWith(`--cache-location=`)||e===`--insert-pragma`)}function Oi(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`)||e===`--reporter-file`||e.startsWith(`--reporter-file=`)||e===`--log-file`||e.startsWith(`--log-file=`))}function ki(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)||e===`--fix-suggestions`||e===`--fix-dangerously`||e===`--init`)}function Ai(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--init`||e===`--migrate`||e.startsWith(`--migrate=`))}function ji(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`--check`||e===`-c`||e===`--list-different`||e===`-l`)&&!Di(e)}function Mi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function Ni(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:!Oi(e)}function Pi(e){let[t]=e;return t===`eslint`&&!Ei(e)}function Fi(e){let[t]=e;return t===`oxlint`&&!ki(e)}function Ii(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:!Oi(e)}function Li(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:!Oi(e)}function Ri(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function zi(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:!ki(e)}function Bi(e){let[t,n]=e;return t!==`vp`||n!==`check`?!1:!e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Vi(e){if(e.length===0)return;let[t,n,r]=e;if((t===`npm`||t===`pnpm`||t===`yarn`||t===`bun`)&&n===`run`&&r)return r;if((t===`pnpm`||t===`bun`||t===`yarn`)&&n&&!n.startsWith(`-`))return n}function Hi(e){if(e.length>=3&&(e[0]===`sh`||e[0]===`bash`)&&e[1]===`-c`)return e[2]}function Ui(e){if(e.length===0)return e;let[t]=e;if(t!==`cross-env`&&t!==`cross-env-shell`)return e;let n=1;for(;n{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Xi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?_i(e)||vi(e)||yi(e)||wi(e):Xi(i,t,n)})}function Zi(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Zi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?bi(e)||xi(e)||Si(e)||Ti(e):Zi(i,t,n)})}function Qi(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Qi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);if(i!==void 0)return Qi(i,t,n);if(Ci(e))return!0;let[a,o]=e;return a===`vp`&&o===`check`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))})}function $i(e,t,n,r){return t&&pi(e,t,n)?!0:r(e)}function ea(e,t,n,r,i){let a=$i(t,r,e,t=>Xi(t,e)),o=$i(t,i,e,t=>Zi(t,e)),s=Qi(t,e);return a&&o?[{capability:`format`,capabilities:[`format`,`lint`],scriptName:n}]:a&&!s?[{capability:`format`,scriptName:n}]:o&&!s?[{capability:`lint`,scriptName:n}]:s?[{capability:`autofix`,scriptName:n}]:[{capability:`typecheck`,capabilities:[],scriptName:n}]}function ta(e,t){return Xi(t[e],t)?{capability:`format`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function na(e,t){return Zi(t[e],t)?{capability:`lint`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function ra(e,t,n){let r=[];return e&&r.push(ta(e,n)),t&&r.push(na(t,n)),r}function ia(e,t,n,r,i){r&&mi(t,n,r)&&e.push(ta(r,t)),i&&hi(t,n,i)&&e.push(na(i,t))}function aa(e){let t=e.fix?`fix`:e[`check:fix`]?`check:fix`:void 0,n=Vr(e,`fix`),r=Hr(e,`fix`);if(!t)return ra(n,r,e);let i=ea(e,e[t]||``,t,n,r);return ia(i,e,t,n,r),i}function oa(e){let t=[],n=Vr(e,`check`),r=Hr(e,`check`);return n&&t.push({capability:`format`,scriptName:n}),r&&t.push({capability:`lint`,scriptName:r}),t}function sa(e,t){return t===`fix`?aa(e):oa(e)}var ca=class{id=`npm-scripts`;name=`package.json scripts`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson?.scripts;if(!t||Object.keys(t).length===0)return{detected:!1,reason:`no scripts declared in package.json`};let n=sa(t,`fix`),r=sa(t,`check`),i=[...n,...r];return i.length>0?{detected:!0,reason:`found supported scripts: ${Array.from(new Set(i.map(e=>`"${e.scriptName}"`))).join(`, `)}`}:{detected:!1,reason:`no supported autofix or check scripts found in package.json`}}plan(e,t){let n=sa(e.jsEnv?.packageJson?.scripts||{},t),r=cn(e.jsPm||`npm`);return n.map(n=>({id:`script-${n.scriptName}`,toolId:this.id,capability:n.capability,capabilities:n.capabilities,executable:r,args:[`run`,n.scriptName],cwd:e.cwd,mode:t,description:`package.json script: ${r} run ${n.scriptName}`}))}};function la(e){return e?Object.values(e).some(t=>Wi(t,e)):!1}function ua(e,t){return e?!!(e.dependencies?.[t]||e.devDependencies?.[t]||e.peerDependencies?.[t]||e.optionalDependencies?.[t]):!1}function da(e,t){for(let n of t)if(f.existsSync(p.join(e,n)))return!0;return!1}var fa=class{id=`vite-plus`;name=`Vite+`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sn(t),r=da(e.cwd,[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.cjs`]);return n||r&&la(t?.scripts)?{detected:!0,reason:`Vite+ dependency and/or configuration detected`}:{detected:!1,reason:`no Vite+ dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`vite-plus-fmt`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp fmt`},{id:`vite-plus-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`,`--fix`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp lint --fix`}]:[{id:`vite-plus-fmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`,`--check`],cwd:e.cwd,mode:`check`,description:`Vite+: vp fmt --check`},{id:`vite-plus-lint`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`],cwd:e.cwd,mode:`check`,description:`Vite+: vp lint`}]}},pa=class{id=`biome`;name=`Biome`;capabilities=[`format`,`lint`,`assist`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`@biomejs/biome`),r=da(e.cwd,[`biome.json`,`biome.jsonc`]);return n&&r?{detected:!0,reason:`Biome dependency and configuration detected`}:r?{detected:!0,reason:`Biome configuration detected`}:n?{detected:!1,reason:`Biome dependency present without configuration file`}:{detected:!1,reason:`no Biome dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`biome-format-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: format --write .`},{id:`biome-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: lint --write .`},{id:`biome-assist-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--write`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: safe assist actions (--write)`}]:[{id:`biome-format-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: format .`},{id:`biome-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: lint .`},{id:`biome-assist-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: check assist actions`}]}},ma=class{id=`prettier`;name=`Prettier`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`prettier`),r=!!t?.prettier,i=da(e.cwd,[`.prettierrc`,`.prettierrc.json`,`.prettierrc.yml`,`.prettierrc.yaml`,`.prettierrc.json5`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`]);return n&&(r||i)?{detected:!0,reason:`Prettier dependency and configuration detected`}:r||i?{detected:!0,reason:`Prettier configuration detected`}:n?{detected:!1,reason:`Prettier dependency present without configuration`}:{detected:!1,reason:`no Prettier dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`prettier-format`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Prettier: format`}]:[{id:`prettier-check`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Prettier: format check`}]}},ha=class{id=`eslint`;name=`ESLint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`eslint`),r=!!t?.eslintConfig,i=da(e.cwd,[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yaml`,`.eslintrc.yml`]);return n&&(r||i)?{detected:!0,reason:`ESLint dependency and configuration detected`}:r||i?{detected:!0,reason:`ESLint configuration detected`}:n?{detected:!1,reason:`ESLint dependency present without configuration`}:{detected:!1,reason:`no ESLint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`eslint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`ESLint: lint autofix`}]:[{id:`eslint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`ESLint: lint check`}]}},ga=class{id=`oxlint`;name=`Oxlint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`oxlint`),r=da(e.cwd,[`.oxlintrc.json`,`oxlint.json`,`oxlint.config.ts`,`oxlint.config.js`]);return n&&r?{detected:!0,reason:`Oxlint dependency and configuration detected`}:r?{detected:!0,reason:`Oxlint configuration detected`}:n?{detected:!1,reason:`Oxlint dependency present without configuration`}:{detected:!1,reason:`no Oxlint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxlint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxlint: lint autofix`}]:[{id:`oxlint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`Oxlint: lint check`}]}},_a=class{id=`oxfmt`;name=`Oxfmt`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`oxfmt`),r=da(e.cwd,[`.oxfmtrc.json`,`oxfmt.json`,`oxfmt.config.ts`,`oxfmt.config.js`]);return n&&r?{detected:!0,reason:`Oxfmt dependency and configuration detected`}:r?{detected:!0,reason:`Oxfmt configuration detected`}:n?{detected:!1,reason:`Oxfmt dependency present without configuration`}:{detected:!1,reason:`no Oxfmt dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxfmt-format`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxfmt: format`}]:[{id:`oxfmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Oxfmt: format check`}]}},va=class{id=`javascript`;name=`JavaScript/TypeScript`;scriptAdapter=new ca;vitePlusAdapter=new fa;biomeAdapter=new pa;prettierAdapter=new ma;eslintAdapter=new ha;oxlintAdapter=new ga;oxfmtAdapter=new _a;detect(e){return!!e.jsEnv?.hasPackageJson}getAdapters(e){return[this.scriptAdapter,this.vitePlusAdapter,this.biomeAdapter,this.oxfmtAdapter,this.prettierAdapter,this.oxlintAdapter,this.eslintAdapter]}},ya=class{id=`ruff`;name=`Ruff`;capabilities=[`lint`,`format`];detect(e){return e.hasPythonSource??or(e.cwd)?{detected:!0,reason:`default Python toolchain`}:{detected:!1,reason:`no Python source files detected`}}plan(e,t){let n=[];return t===`fix`?n.push({id:`ruff-lint-fix`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: lint autofix`},{id:`ruff-format`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: format`}):n.push({id:`ruff-lint-check`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: lint check`},{id:`ruff-format-check`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: format check`}),n}},ba=class{id=`python`;name=`Python`;ruffAdapter=new ya;detect(e){return e.hasPythonSource??or(e.cwd)}getAdapters(e){return[this.ruffAdapter]}},xa=class{providers=/* @__PURE__ */ new Map;standaloneAdapters=/* @__PURE__ */ new Map;registerProvider(e){this.providers.set(e.id,e)}getProvider(e){return this.providers.get(e)}getProviders(){return Array.from(this.providers.values())}registerAdapter(e){this.standaloneAdapters.set(e.id,e)}getAdapter(e){return this.standaloneAdapters.get(e)}getStandaloneAdapters(){return Array.from(this.standaloneAdapters.values())}clear(){this.providers.clear(),this.standaloneAdapters.clear()}};function Sa(){let e=new xa;return e.registerProvider(new ba),e.registerProvider(new va),e}const Ca=Sa();async function wa(e,t=process.cwd()){let n=`${e.command} ${e.args.join(` `)}`.trim();if(en(`Installing JS dependencies: ${n}`),await Yt(e.command,e.args,{cwd:t,ignoreReturnCode:!0})!==0)throw Error(`JS dependency installation failed executing "${n}". Check dependency constraints or lockfile compatibility.`)}async function Ta(e=process.cwd()){let t=fn(e);if(!t.hasPackageJson){en(`No package.json found. Skipping scripts.`);return}if(t.packageJsonError)throw Error(t.packageJsonError);let n=cn(process.env.PACKAGE_MANAGER||_n(t).name),r=(await Lr(Ca,{cwd:e,jsEnv:t,jsPm:n,hasPythonSource:!1},`fix`)).tasks.filter(e=>e.toolId!==`ruff`);if(r.length===0){en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`);return}await wa(vn(n),e);let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}}async function Ea(e,t,n=process.cwd()){let r=`${e} ${t.join(` `)}`.trim();if(en(`Executing: ${r}`),await Yt(e,t,{cwd:n,ignoreReturnCode:!0})!==0)throw Error(`Python command "${r}" failed. Check Python environment and dependency configuration.`)}async function Da(e,t=process.cwd()){Dr(e,`Invalid Python environment: "pmInfo" must be an object`);let n=e.name===`pip`?`pip`:e.name;if(!await Vt(n,!1)&&!e.isStandalone){let e=`Required Python package manager '${n}' is not available in PATH.`;throw Error(e)}if(!e.isStandalone&&e.installCommands.length>0){let n=e.installCommands;en(`Installing Python dependencies: ${n.map(e=>`${e.executable} ${e.args.join(` `)}`).join(` && `)}`);for(let{executable:e,args:r}of n)await Ea(e,r,t)}}async function Oa(e=process.cwd(),t,n){if(!(t??or(e)))return;let r;if(n)r=n;else{if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);r=(await Lr(Ca,{cwd:e,hasPythonSource:!0},`fix`)).tasks.filter(e=>e.toolId===`ruff`)}let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}}async function ka(e,t){if(process.env.JS_SETUP_OUTCOME===`failure`||process.env.NODE_SETUP_OUTCOME===`failure`||process.env.BUN_SETUP_OUTCOME===`failure`||process.env.PNPM_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`JavaScript runtime or package manager setup failed.`);try{if(t){let n=fn(e);if(!n.hasPackageJson)return en(`No package.json found. Skipping scripts.`),null;if(n.packageJsonError)throw Error(n.packageJsonError);if(t.length===0)return en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`),null;await wa(vn(cn(process.env.PACKAGE_MANAGER||_n(n).name)),e);let r=(await new Ar().executeTasks(t)).filter(e=>e.error);if(r.length>0){let e=r.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}return null}return await Ta(e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Aa(e,t){if(process.env.PYTHON_SETUP_OUTCOME===`failure`||process.env.UV_SETUP_OUTCOME===`failure`||process.env.PY_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Python runtime or package manager setup failed.`);let n=t&&`pmInfo`in t?t.pmInfo:Tr(e,void 0,{ctx:t?.ctx,hasSource:t?.hasSource});if(!n)return null;try{return await Da(n,e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function ja(e,t,n){if(process.env.RUFF_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Ruff setup failed.`);try{return await Oa(e,t,n),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Ma(e,t,n){let r=t??or(e);if(!r)return[];let i=[],a=ir(e),o=await Aa(e,{ctx:a,hasSource:!0,pmInfo:Tr(e,void 0,{ctx:a,hasSource:!0,isProject:!0})});o&&i.push(o);let s=await ja(e,r,n);return s&&i.push(s),i}async function Na(e=process.cwd()){let t=or(e),n;try{let r=fn(e),i={cwd:e,jsEnv:r,jsPm:cn(process.env.PACKAGE_MANAGER||_n(r).name),hasPythonSource:t};n=await Lr(Ca,i,`fix`),en(n.summary)}catch{}let r=[],i=n?n.tasks.filter(e=>e.toolId!==`ruff`):void 0,a=n?n.tasks.filter(e=>e.toolId===`ruff`):void 0,o=await ka(e,i);o&&r.push(o);let s=await Ma(e,t,a);r.push(...s),r.length>0&&(Zt(`Failed to run scripts: ${r.map(e=>e.message).join(` -`)}`),process.env.NODE_ENV!==`test`&&process.exit(1))}process.env.NODE_ENV!==`test`&&Or(import.meta.url)&&Na();export{Ta as executeJsWorkflow,Da as executePythonWorkflow,Oa as executeRuffAutofix,Na as run,cn as sanitizePackageManager}; \ No newline at end of file +`;)n++;return n>t?n-1:t}function Gr(e,t){return t.inSingleQuote||t.inDoubleQuote||t.isEscaped?!1:e.length===0||/\s/.test(e[e.length-1])}function Kr(e,t){return t.isEscaped=!1,{ch:e,advance:!0}}function qr(e,t,n,r){let i=e[t];if(n.isEscaped)return{newCmd:r+Kr(i,n).ch,nextIndex:t,sepLen:0};if(i===`\\`&&!n.inSingleQuote)return n.isEscaped=!0,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`'`&&!n.inDoubleQuote)return n.inSingleQuote=!n.inSingleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`"`&&!n.inSingleQuote)return n.inDoubleQuote=!n.inDoubleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`#`&&Gr(r,n))return{newCmd:r,nextIndex:Wr(e,t),sepLen:0};let a=Ur(e,t,n);return{newCmd:r+(a===0?i:``),nextIndex:t,sepLen:a}}function Jr(e){let t=[],n=``,r={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1,hasSyntaxError:!1};for(let i=0;i0?(n.trim()&&t.push(n.trim()),n=``,i+=a.sepLen-1):(n=a.newCmd,i=a.nextIndex)}return(r.inSingleQuote||r.inDoubleQuote||r.isEscaped)&&(r.hasSyntaxError=!0),n.trim()&&t.push(n.trim()),{commands:t,hasSyntaxError:r.hasSyntaxError}}function Yr(e){return Jr(e).commands}function Xr(e,t,n){return t.isEscaped=!1,n+e}function Zr(e,t){return e===`'`&&!t.inDoubleQuote?(t.inSingleQuote=!t.inSingleQuote,!0):e===`"`&&!t.inSingleQuote&&(t.inDoubleQuote=!t.inDoubleQuote,!0)}const Qr=/* @__PURE__ */ new Set([`@`,`*`,`#`,`?`,`-`,`$`,`!`,`0`]);function $r(e,t,n){if(n.inSingleQuote||n.isEscaped||e[t]!==`$`||t+1>=e.length)return!1;let r=e[t+1];return!!(r===`{`||Qr.has(r)||r>=`1`&&r<=`9`||r===`_`||r>=`a`&&r<=`z`||r>=`A`&&r<=`Z`)}function ei(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped||e[t]!==`&`)return!1;let r=t>0?e[t-1]:``,i=t+1`}function ti(e,t,n){if(n.inSingleQuote||n.isEscaped)return!1;let r=e[t];return r==="`"||r===`$`&&t+1`)&&t+1`||r===`<`||r===`&`&&t+1`}function ii(e,t,n){return ei(e,t,n.state)||$r(e,t,n.state)||ti(e,t,n.state)||ni(e,t,n.state)?(n.inspection.hasUnsupportedSyntax=!0,!0):ri(e,t,n.state)?(n.inspection.hasRedirection=!0,n.inspection.hasUnsupportedSyntax=!0,!0):!1}function ai(e,t,n,r){let i=e[t];return n.state.isEscaped?{word:Xr(i,n.state,r),hasChars:!0,skipped:!1}:i===`\\`&&!n.state.inSingleQuote?(n.state.isEscaped=!0,{word:r,hasChars:!1,skipped:!0}):(ii(e,t,n),Zr(i,n.state)?{word:r,hasChars:!0,skipped:!0}:{word:r+i,hasChars:!0,skipped:!1})}function oi(e){let t={tokens:[],hasUnsupportedSyntax:!1,hasRedirection:!1},n={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1},r={inspection:t,state:n},i=``,a=!1;for(let o=0;o0&&n.push(t)}return n}function pi(e,t,n={},r=/* @__PURE__ */ new Set){if(!e||!t)return!1;let i=fi(n[e]===void 0?e:n[e]);for(let e of i){if(di(e,t))return!0;let i=Vi(e);if(i){if(i===t)return!0;if(!r.has(i)&&n[i]!==void 0){r.add(i);try{if(pi(n[i],t,n,r))return!0}finally{r.delete(i)}}}let a=Hi(e);if(a!==void 0&&pi(a,t,n,r))return!0}return!1}function mi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function hi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function gi(e){let[t]=e;return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||(e===`--fix`||e.startsWith(`--fix=`))&&(t!==`eslint`||e!==`--fix-dry-run`))}function _i(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function vi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function yi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function bi(e){let[t]=e;return t===`eslint`&&e.some(e=>(e===`--fix`||e.startsWith(`--fix=`))&&e!==`--fix-dry-run`)}function xi(e){let[t]=e;return t===`oxlint`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Si(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Ci(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function wi(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:!e.some(e=>e===`--check`||e===`-c`)}function Ti(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Ei(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)&&e!==`--fix-dry-run`||e===`-o`||e.startsWith(`-o=`)||e===`--output-file`||e.startsWith(`--output-file=`)||e===`--cache`||e===`--cache-file`||e.startsWith(`--cache-file=`)||e===`--cache-location`||e.startsWith(`--cache-location=`))}function Di(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--cache`||e===`--cache-location`||e.startsWith(`--cache-location=`)||e===`--insert-pragma`)}function Oi(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`)||e===`--reporter-file`||e.startsWith(`--reporter-file=`)||e===`--log-file`||e.startsWith(`--log-file=`))}function ki(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)||e===`--fix-suggestions`||e===`--fix-dangerously`||e===`--init`)}function Ai(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--init`||e===`--migrate`||e.startsWith(`--migrate=`))}function ji(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`--check`||e===`-c`||e===`--list-different`||e===`-l`)&&!Di(e)}function Mi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function Ni(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:!Oi(e)}function Pi(e){let[t]=e;return t===`eslint`&&!Ei(e)}function Fi(e){let[t]=e;return t===`oxlint`&&!ki(e)}function Ii(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:!Oi(e)}function Li(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:!Oi(e)}function Ri(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function zi(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:!ki(e)}function Bi(e){let[t,n]=e;return t!==`vp`||n!==`check`?!1:!e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Vi(e){if(e.length===0)return;let[t,n,r]=e;if((t===`npm`||t===`pnpm`||t===`yarn`||t===`bun`)&&n===`run`&&r)return r;if((t===`pnpm`||t===`bun`||t===`yarn`)&&n&&!n.startsWith(`-`))return n}function Hi(e){if(e.length>=3&&(e[0]===`sh`||e[0]===`bash`)&&e[1]===`-c`)return e[2]}const Ui=/* @__PURE__ */ new Set([`-f`,`--file`,`-c`,`--config`,`--env-file`]),Wi=/* @__PURE__ */ new Set([`-h`,`--help`,`-v`,`--version`,`--shell`]);function Gi(e){if(e.length===0)return e;let[t]=e;if(t!==`cross-env`&&t!==`cross-env-shell`)return e;let n=1;for(;n=e.length)return[];n+=2}else if(Wi.has(t))n++;else{if(t.startsWith(`-`))return[];if(li(t))n++;else break}}return e.slice(n)}function Ki(e,t={},n=/* @__PURE__ */ new Set){if(!e)return!1;let r=fi(e);for(let e of r){let r=Gi(e);if(r.length===0)continue;if(r[0]===`vp`||(r[0]===`npx`||r[0]===`bunx`)&&r[1]===`vp`||(r[0]===`npm`||r[0]===`pnpm`||r[0]===`yarn`)&&(r[1]===`exec`||r[1]===`dlx`)&&r[2]===`vp`)return!0;let i=Hi(r);if(i!==void 0&&Ki(i,t,n))return!0;let a=Vi(r);if(a&&!n.has(a)&&t[a]){n.add(a);try{if(Ki(t[a],t,n))return!0}finally{n.delete(a)}}}return!1}function qi(e){return _i(e)||vi(e)||yi(e)||bi(e)||xi(e)||Si(e)||Ci(e)||wi(e)||Ti(e)}function Ji(e){return ji(e)||Mi(e)||Ni(e)||Pi(e)||Fi(e)||Ii(e)||Li(e)||Ri(e)||zi(e)||Bi(e)}function Yi(e,t,n){if(e.length===0)return`unknown`;if(gi(e))return`write-capable`;let r=Hi(e);if(r!==void 0)return Xi(r,t,n);let i=Vi(e);if(i){if(n.has(i))return`unknown`;let e=t[i];if(!e)return`unknown`;n.add(i);try{return Xi(e,t,n)}finally{n.delete(i)}}return qi(e)?`write-capable`:Ji(e)?`read-only`:`unknown`}function Xi(e,t,n){let r=Jr(e);if(r.hasSyntaxError)return`unknown`;let{commands:i}=r;if(i.length===0)return`unknown`;let a=!1;for(let e of i){let r=oi(e),i=Yi(ui(r.tokens),t,n);if(i===`write-capable`)return`write-capable`;if(r.hasUnsupportedSyntax||i===`unknown`)return`unknown`;i===`read-only`&&(a=!0)}return a?`read-only`:`unknown`}function Zi(e,t={}){return Xi(e,t,/* @__PURE__ */ new Set)}function Qi(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Qi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?_i(e)||vi(e)||yi(e)||wi(e):Qi(i,t,n)})}function $i(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return $i(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?bi(e)||xi(e)||Si(e)||Ti(e):$i(i,t,n)})}function ea(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return ea(e,t,n)}finally{n.delete(r)}}let i=Hi(e);if(i!==void 0)return ea(i,t,n);if(Ci(e))return!0;let[a,o]=e;return a===`vp`&&o===`check`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))})}function ta(e,t,n,r){return t&&pi(e,t,n)?!0:r(e)}function na(e,t,n,r,i){let a=ta(t,r,e,t=>Qi(t,e)),o=ta(t,i,e,t=>$i(t,e)),s=ea(t,e);return a&&o?[{capability:`format`,capabilities:[`format`,`lint`],scriptName:n}]:a&&!s?[{capability:`format`,scriptName:n}]:o&&!s?[{capability:`lint`,scriptName:n}]:s?[{capability:`autofix`,scriptName:n}]:[{capability:`typecheck`,capabilities:[],scriptName:n}]}function ra(e,t){return Qi(t[e],t)?{capability:`format`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function ia(e,t){return $i(t[e],t)?{capability:`lint`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function aa(e,t,n){let r=[];return e&&r.push(ra(e,n)),t&&r.push(ia(t,n)),r}function oa(e,t,n,r,i){r&&mi(t,n,r)&&e.push(ra(r,t)),i&&hi(t,n,i)&&e.push(ia(i,t))}function sa(e){let t=e.fix?`fix`:e[`check:fix`]?`check:fix`:void 0,n=Vr(e,`fix`),r=Hr(e,`fix`);if(!t)return aa(n,r,e);let i=na(e,e[t]||``,t,n,r);return oa(i,e,t,n,r),i}function ca(e){let t=[],n=Vr(e,`check`),r=Hr(e,`check`);return n&&t.push({capability:`format`,scriptName:n}),r&&t.push({capability:`lint`,scriptName:r}),t}function la(e,t){return t===`fix`?sa(e):ca(e)}var ua=class{id=`npm-scripts`;name=`package.json scripts`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson?.scripts;if(!t||Object.keys(t).length===0)return{detected:!1,reason:`no scripts declared in package.json`};let n=la(t,`fix`),r=la(t,`check`),i=[...n,...r];return i.length>0?{detected:!0,reason:`found supported scripts: ${Array.from(new Set(i.map(e=>`"${e.scriptName}"`))).join(`, `)}`}:{detected:!1,reason:`no supported autofix or check scripts found in package.json`}}plan(e,t){let n=la(e.jsEnv?.packageJson?.scripts||{},t),r=cn(e.jsPm||`npm`);return n.map(n=>({id:`script-${n.scriptName}`,toolId:this.id,capability:n.capability,capabilities:n.capabilities,executable:r,args:[`run`,n.scriptName],cwd:e.cwd,mode:t,description:`package.json script: ${r} run ${n.scriptName}`}))}};function da(e){return e?Object.values(e).some(t=>Ki(t,e)):!1}function fa(e,t){return e?!!(e.dependencies?.[t]||e.devDependencies?.[t]||e.peerDependencies?.[t]||e.optionalDependencies?.[t]):!1}function pa(e,t){for(let n of t)if(f.existsSync(p.join(e,n)))return!0;return!1}var ma=class{id=`vite-plus`;name=`Vite+`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sn(t),r=pa(e.cwd,[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.cjs`]);return n||r&&da(t?.scripts)?{detected:!0,reason:`Vite+ dependency and/or configuration detected`}:{detected:!1,reason:`no Vite+ dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`vite-plus-fmt`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp fmt`},{id:`vite-plus-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`,`--fix`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp lint --fix`}]:[{id:`vite-plus-fmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`,`--check`],cwd:e.cwd,mode:`check`,description:`Vite+: vp fmt --check`},{id:`vite-plus-lint`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`],cwd:e.cwd,mode:`check`,description:`Vite+: vp lint`}]}},ha=class{id=`biome`;name=`Biome`;capabilities=[`format`,`lint`,`assist`];detect(e){let t=e.jsEnv?.packageJson,n=fa(t,`@biomejs/biome`),r=pa(e.cwd,[`biome.json`,`biome.jsonc`]);return n&&r?{detected:!0,reason:`Biome dependency and configuration detected`}:r?{detected:!0,reason:`Biome configuration detected`}:n?{detected:!1,reason:`Biome dependency present without configuration file`}:{detected:!1,reason:`no Biome dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`biome-format-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: format --write .`},{id:`biome-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: lint --write .`},{id:`biome-assist-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--write`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: safe assist actions (--write)`}]:[{id:`biome-format-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: format .`},{id:`biome-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: lint .`},{id:`biome-assist-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: check assist actions`}]}},ga=class{id=`prettier`;name=`Prettier`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=fa(t,`prettier`),r=!!t?.prettier,i=pa(e.cwd,[`.prettierrc`,`.prettierrc.json`,`.prettierrc.yml`,`.prettierrc.yaml`,`.prettierrc.json5`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`]);return n&&(r||i)?{detected:!0,reason:`Prettier dependency and configuration detected`}:r||i?{detected:!0,reason:`Prettier configuration detected`}:n?{detected:!1,reason:`Prettier dependency present without configuration`}:{detected:!1,reason:`no Prettier dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`prettier-format`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Prettier: format`}]:[{id:`prettier-check`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Prettier: format check`}]}},_a=class{id=`eslint`;name=`ESLint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=fa(t,`eslint`),r=!!t?.eslintConfig,i=pa(e.cwd,[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yaml`,`.eslintrc.yml`]);return n&&(r||i)?{detected:!0,reason:`ESLint dependency and configuration detected`}:r||i?{detected:!0,reason:`ESLint configuration detected`}:n?{detected:!1,reason:`ESLint dependency present without configuration`}:{detected:!1,reason:`no ESLint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`eslint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`ESLint: lint autofix`}]:[{id:`eslint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`ESLint: lint check`}]}},va=class{id=`oxlint`;name=`Oxlint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=fa(t,`oxlint`),r=pa(e.cwd,[`.oxlintrc.json`,`oxlint.json`,`oxlint.config.ts`,`oxlint.config.js`]);return n&&r?{detected:!0,reason:`Oxlint dependency and configuration detected`}:r?{detected:!0,reason:`Oxlint configuration detected`}:n?{detected:!1,reason:`Oxlint dependency present without configuration`}:{detected:!1,reason:`no Oxlint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxlint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxlint: lint autofix`}]:[{id:`oxlint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`Oxlint: lint check`}]}},ya=class{id=`oxfmt`;name=`Oxfmt`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=fa(t,`oxfmt`),r=pa(e.cwd,[`.oxfmtrc.json`,`oxfmt.json`,`oxfmt.config.ts`,`oxfmt.config.js`]);return n&&r?{detected:!0,reason:`Oxfmt dependency and configuration detected`}:r?{detected:!0,reason:`Oxfmt configuration detected`}:n?{detected:!1,reason:`Oxfmt dependency present without configuration`}:{detected:!1,reason:`no Oxfmt dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxfmt-format`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxfmt: format`}]:[{id:`oxfmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Oxfmt: format check`}]}},ba=class{id=`javascript`;name=`JavaScript/TypeScript`;scriptAdapter=new ua;vitePlusAdapter=new ma;biomeAdapter=new ha;prettierAdapter=new ga;eslintAdapter=new _a;oxlintAdapter=new va;oxfmtAdapter=new ya;detect(e){return!!e.jsEnv?.hasPackageJson}getAdapters(e){return[this.scriptAdapter,this.vitePlusAdapter,this.biomeAdapter,this.oxfmtAdapter,this.prettierAdapter,this.oxlintAdapter,this.eslintAdapter]}},xa=class{id=`ruff`;name=`Ruff`;capabilities=[`lint`,`format`];detect(e){return e.hasPythonSource??or(e.cwd)?{detected:!0,reason:`default Python toolchain`}:{detected:!1,reason:`no Python source files detected`}}plan(e,t){let n=[];return t===`fix`?n.push({id:`ruff-lint-fix`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: lint autofix`},{id:`ruff-format`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: format`}):n.push({id:`ruff-lint-check`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: lint check`},{id:`ruff-format-check`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: format check`}),n}},Sa=class{id=`python`;name=`Python`;ruffAdapter=new xa;detect(e){return e.hasPythonSource??or(e.cwd)}getAdapters(e){return[this.ruffAdapter]}},Ca=class{providers=/* @__PURE__ */ new Map;standaloneAdapters=/* @__PURE__ */ new Map;registerProvider(e){this.providers.set(e.id,e)}getProvider(e){return this.providers.get(e)}getProviders(){return Array.from(this.providers.values())}registerAdapter(e){this.standaloneAdapters.set(e.id,e)}getAdapter(e){return this.standaloneAdapters.get(e)}getStandaloneAdapters(){return Array.from(this.standaloneAdapters.values())}clear(){this.providers.clear(),this.standaloneAdapters.clear()}};function wa(){let e=new Ca;return e.registerProvider(new Sa),e.registerProvider(new ba),e}const Ta=wa();async function Ea(e,t=process.cwd()){let n=`${e.command} ${e.args.join(` `)}`.trim();if(en(`Installing JS dependencies: ${n}`),await Yt(e.command,e.args,{cwd:t,ignoreReturnCode:!0})!==0)throw Error(`JS dependency installation failed executing "${n}". Check dependency constraints or lockfile compatibility.`)}async function Da(e=process.cwd()){let t=fn(e);if(!t.hasPackageJson){en(`No package.json found. Skipping scripts.`);return}if(t.packageJsonError)throw Error(t.packageJsonError);let n=cn(process.env.PACKAGE_MANAGER||_n(t).name),r=(await Lr(Ta,{cwd:e,jsEnv:t,jsPm:n,hasPythonSource:!1},`fix`)).tasks.filter(e=>e.toolId!==`ruff`);if(r.length===0){en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`);return}await Ea(vn(n),e);let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}}async function Oa(e,t,n=process.cwd()){let r=`${e} ${t.join(` `)}`.trim();if(en(`Executing: ${r}`),await Yt(e,t,{cwd:n,ignoreReturnCode:!0})!==0)throw Error(`Python command "${r}" failed. Check Python environment and dependency configuration.`)}async function ka(e,t=process.cwd()){Dr(e,`Invalid Python environment: "pmInfo" must be an object`);let n=e.name===`pip`?`pip`:e.name;if(!await Vt(n,!1)&&!e.isStandalone){let e=`Required Python package manager '${n}' is not available in PATH.`;throw Error(e)}if(!e.isStandalone&&e.installCommands.length>0){let n=e.installCommands;en(`Installing Python dependencies: ${n.map(e=>`${e.executable} ${e.args.join(` `)}`).join(` && `)}`);for(let{executable:e,args:r}of n)await Oa(e,r,t)}}async function Aa(e=process.cwd(),t,n){if(!(t??or(e)))return;let r;if(n)r=n;else{if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);r=(await Lr(Ta,{cwd:e,hasPythonSource:!0},`fix`)).tasks.filter(e=>e.toolId===`ruff`)}let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}}async function ja(e,t){if(process.env.JS_SETUP_OUTCOME===`failure`||process.env.NODE_SETUP_OUTCOME===`failure`||process.env.BUN_SETUP_OUTCOME===`failure`||process.env.PNPM_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`JavaScript runtime or package manager setup failed.`);try{if(t){let n=fn(e);if(!n.hasPackageJson)return en(`No package.json found. Skipping scripts.`),null;if(n.packageJsonError)throw Error(n.packageJsonError);if(t.length===0)return en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`),null;await Ea(vn(cn(process.env.PACKAGE_MANAGER||_n(n).name)),e);let r=(await new Ar().executeTasks(t)).filter(e=>e.error);if(r.length>0){let e=r.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}return null}return await Da(e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Ma(e,t){if(process.env.PYTHON_SETUP_OUTCOME===`failure`||process.env.UV_SETUP_OUTCOME===`failure`||process.env.PY_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Python runtime or package manager setup failed.`);let n=t&&`pmInfo`in t?t.pmInfo:Tr(e,void 0,{ctx:t?.ctx,hasSource:t?.hasSource});if(!n)return null;try{return await ka(n,e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Na(e,t,n){if(process.env.RUFF_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Ruff setup failed.`);try{return await Aa(e,t,n),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Pa(e,t,n){let r=t??or(e);if(!r)return[];let i=[],a=ir(e),o=await Ma(e,{ctx:a,hasSource:!0,pmInfo:Tr(e,void 0,{ctx:a,hasSource:!0,isProject:!0})});o&&i.push(o);let s=await Na(e,r,n);return s&&i.push(s),i}async function Fa(e=process.cwd()){let t=or(e),n;try{let r=fn(e),i={cwd:e,jsEnv:r,jsPm:cn(process.env.PACKAGE_MANAGER||_n(r).name),hasPythonSource:t};n=await Lr(Ta,i,`fix`),en(n.summary)}catch{}let r=[],i=n?n.tasks.filter(e=>e.toolId!==`ruff`):void 0,a=n?n.tasks.filter(e=>e.toolId===`ruff`):void 0,o=await ja(e,i);o&&r.push(o);let s=await Pa(e,t,a);r.push(...s),r.length>0&&(Zt(`Failed to run scripts: ${r.map(e=>e.message).join(` +`)}`),process.env.NODE_ENV!==`test`&&process.exit(1))}process.env.NODE_ENV!==`test`&&Or(import.meta.url)&&Fa();export{Da as executeJsWorkflow,ka as executePythonWorkflow,Aa as executeRuffAutofix,Fa as run,cn as sanitizePackageManager}; \ No newline at end of file diff --git a/src/autofix/adapters/javascript/script-adapter.ts b/src/autofix/adapters/javascript/script-adapter.ts index 5d50e068..1f1cc6c0 100644 --- a/src/autofix/adapters/javascript/script-adapter.ts +++ b/src/autofix/adapters/javascript/script-adapter.ts @@ -749,10 +749,13 @@ export function extractShellWrapperScript(tokens: string[]): string | undefined return undefined; } +const CROSS_ENV_OPTIONS_WITH_ARGS = new Set(["-f", "--file", "-c", "--config", "--env-file"]); +const CROSS_ENV_BOOLEAN_OPTIONS = new Set(["-h", "--help", "-v", "--version", "--shell"]); + /** * Unwraps environment wrapper commands like `cross-env` or `cross-env-shell`, - * stripping initial flags and subsequent environment variable assignments - * to retrieve the target command tokens. + * correctly parsing options (both flags and options with arguments) and subsequent + * environment variable assignments to retrieve the target command tokens. */ export function unwrapEnvironmentWrapper(tokens: string[]): string[] { if (tokens.length === 0) return tokens; @@ -764,16 +767,54 @@ export function unwrapEnvironmentWrapper(tokens: string[]): string[] { let i = 1; while (i < tokens.length) { const token = tokens[i]; - if (token.startsWith("-")) { + + // Explicit end-of-options delimiter + if (token === "--") { + i++; + break; + } + + // Option with inline value (e.g. --file=.env, --config=conf.json) + if ( + token.startsWith("--file=") || + token.startsWith("--config=") || + token.startsWith("--env-file=") + ) { + i++; + continue; + } + + // Option with separate argument + if (CROSS_ENV_OPTIONS_WITH_ARGS.has(token)) { + if (i + 1 >= tokens.length) { + // Missing argument for option, fail closed / conservative + return []; + } + i += 2; + continue; + } + + // Boolean flag option + if (CROSS_ENV_BOOLEAN_OPTIONS.has(token)) { i++; continue; } + + // Unrecognized option starting with '-' + if (token.startsWith("-")) { + // Conservative fail-closed: do not guess if it takes an argument + return []; + } + + // Environment variable assignment (e.g. NODE_ENV=production) if (isEnvAssignment(token)) { i++; continue; } + break; } + return tokens.slice(i); } diff --git a/src/autofix/planner.ts b/src/autofix/planner.ts index 34a5b3df..579d5388 100644 --- a/src/autofix/planner.ts +++ b/src/autofix/planner.ts @@ -133,7 +133,7 @@ async function processStandaloneAdapters( const candidateTools: CandidateTool[] = []; for (const adapter of registry.getStandaloneAdapters()) { const result = await adapter.detect(context); - const scope = adapter.scope ?? "standalone"; + const scope = adapter.scope ?? `standalone:${adapter.id}`; if (result.detected) { candidateTools.push({ adapter, reason: result.reason, scope }); } else if (result.reason && !result.reason.startsWith("no ")) { diff --git a/src/autofix/types.ts b/src/autofix/types.ts index b09db540..91958836 100644 --- a/src/autofix/types.ts +++ b/src/autofix/types.ts @@ -38,6 +38,13 @@ export interface ToolAdapter { id: string; name: string; capabilities: readonly Capability[]; + /** + * Conflict domain scope for capability deduplication and conflict resolution. + * - For provider adapters, defaults to `provider.id` (e.g. "javascript", "python"). + * - For standalone adapters, can explicitly match a provider id (e.g. "javascript") + * or another shared scope name to resolve genuine conflicts within that domain. + * When omitted, defaults to an isolated per-adapter scope (`standalone:${id}`). + */ scope?: string; detect(context: ProjectContext): Promise | AdapterDetectionResult; diff --git a/tests/autofix-architecture.test.ts b/tests/autofix-architecture.test.ts index edf944a1..713e60f1 100644 --- a/tests/autofix-architecture.test.ts +++ b/tests/autofix-architecture.test.ts @@ -1733,7 +1733,36 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { const planCrossEnvShell = await planExecution(registry, { cwd: tempDir }, "fix"); expect(planCrossEnvShell.selectedTools.map((t) => t.id)).toContain("vite-plus"); - // 3. sh -c + // 3. cross-env with options that consume arguments (-f, --file, -c, --config) + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + formatArgShort: "cross-env -f .env vp fmt", + formatArgLong: "cross-env --file .env vp fmt", + formatInline: "cross-env --file=.env vp fmt", + formatConfig: "cross-env -c config.json vp fmt", + formatMultipleEnv: "cross-env NODE_ENV=production CI=true vp lint", + formatDelimiter: "cross-env -- NODE_ENV=production vp fmt", + }, + }), + ); + const planCrossEnvOptions = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planCrossEnvOptions.selectedTools.map((t) => t.id)).toContain("vite-plus"); + + // 4. unrecognized cross-env option fails closed and does not trigger false positive + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + formatBad: "cross-env -unknown-flag vp fmt", + }, + }), + ); + const planCrossEnvUnknown = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planCrossEnvUnknown.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + + // 5. sh -c fs.writeFileSync( path.join(tempDir, "package.json"), JSON.stringify({ @@ -1745,7 +1774,7 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { const planSh = await planExecution(registry, { cwd: tempDir }, "fix"); expect(planSh.selectedTools.map((t) => t.id)).toContain("vite-plus"); - // 4. bash -c + // 6. bash -c fs.writeFileSync( path.join(tempDir, "package.json"), JSON.stringify({ @@ -1757,7 +1786,7 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { const planBash = await planExecution(registry, { cwd: tempDir }, "fix"); expect(planBash.selectedTools.map((t) => t.id)).toContain("vite-plus"); - // 5. npx vp / bunx vp / pnpm exec vp + // 7. npx vp / bunx vp / pnpm exec vp fs.writeFileSync( path.join(tempDir, "package.json"), JSON.stringify({ @@ -1771,7 +1800,7 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { const planRunners = await planExecution(registry, { cwd: tempDir }, "fix"); expect(planRunners.selectedTools.map((t) => t.id)).toContain("vite-plus"); - // 6. script delegation invoking vp + // 8. script delegation invoking vp fs.writeFileSync( path.join(tempDir, "package.json"), JSON.stringify({ @@ -1945,13 +1974,14 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { ); }); - it("skips a lower-priority adapter when a higher-priority standalone adapter ran first and covered the capability", async () => { + it("skips a lower-priority adapter when a higher-priority standalone adapter ran first and covered the capability in the same scope", async () => { const customRegistry = new AutofixRegistry(); class StandaloneFormatAdapter implements ToolAdapter { id = "standalone-fmt"; name = "Standalone Formatter"; capabilities: ["format"] = ["format"]; + scope = "custom-format-scope"; detect() { return { detected: true, reason: "standalone formatter config detected" }; } @@ -1970,11 +2000,12 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { } } - // Test two standalone adapters where first standalone adapter conflicts with second standalone adapter: + // Test two standalone adapters sharing the same scope where first standalone adapter conflicts with second standalone adapter: class SecondStandaloneFormatAdapter implements ToolAdapter { id = "second-fmt"; name = "Second Formatter"; capabilities: ["format"] = ["format"]; + scope = "custom-format-scope"; detect() { return { detected: true, reason: "second formatter config detected" }; } @@ -2164,6 +2195,67 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { expect(plan.tasks).toHaveLength(1); expect(plan.tasks[0].executable).toBe("check-1"); }); + + it("ensures standalone adapters without explicit scope do not conflict with each other or provider adapters", async () => { + const customRegistry = new AutofixRegistry(); + + // Standalone format adapter with default scope + class StandaloneDefault1 implements ToolAdapter { + id = "default-standalone-1"; + name = "Default Standalone 1"; + capabilities: ["format"] = ["format"]; + detect() { + return { detected: true, reason: "default standalone 1 detected" }; + } + plan(ctx: ProjectContext, mode: ExecutionMode): ExecutionTask[] { + return [ + { + id: "default-standalone-1-fmt", + toolId: this.id, + capability: "format", + executable: "fmt-1", + args: [], + cwd: ctx.cwd, + mode, + }, + ]; + } + } + + // Standalone format adapter with default scope + class StandaloneDefault2 implements ToolAdapter { + id = "default-standalone-2"; + name = "Default Standalone 2"; + capabilities: ["format"] = ["format"]; + detect() { + return { detected: true, reason: "default standalone 2 detected" }; + } + plan(ctx: ProjectContext, mode: ExecutionMode): ExecutionTask[] { + return [ + { + id: "default-standalone-2-fmt", + toolId: this.id, + capability: "format", + executable: "fmt-2", + args: [], + cwd: ctx.cwd, + mode, + }, + ]; + } + } + + customRegistry.registerAdapter(new StandaloneDefault1()); + customRegistry.registerAdapter(new StandaloneDefault2()); + + const plan = await planExecution(customRegistry, { cwd: tempDir }, "fix"); + // Both default standalone adapters have independent default scopes (standalone:default-standalone-1 and standalone:default-standalone-2), + // so neither suppresses the other! + expect(plan.tasks.map((t) => t.id)).toEqual([ + "default-standalone-1-fmt", + "default-standalone-2-fmt", + ]); + }); }); describe("Registry Extensibility", () => { From 38aa7d9684460468ad514b7bb6343ce7ff55945d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 10 Nov 2026 08:14:53 +0000 Subject: [PATCH 4/5] fix(autofix): correct cross-env CLI parsing and unwrapping - Align unwrapEnvironmentWrapper with actual cross-env CLI syntax by removing hypothetical options (-f, --file, etc.) and stripping leading environment variable assignments. - Update regression tests to verify valid cross-env invocations and prevent false-positive detection from unsupported options or unrelated commands. - Synchronize dist/autofix.mjs bundle. --- dist/autofix.mjs | 12 ++-- .../adapters/javascript/script-adapter.ts | 58 ++----------------- tests/autofix-architecture.test.ts | 56 ++++++++++++++---- 3 files changed, 56 insertions(+), 70 deletions(-) diff --git a/dist/autofix.mjs b/dist/autofix.mjs index 50438d58..c6aed594 100644 --- a/dist/autofix.mjs +++ b/dist/autofix.mjs @@ -304,10 +304,10 @@ const Vn=[`uv`,`pip`],Hn=[`.git`,`.venv`,`venv`,`env`,`.env`,`virtualenv`,`.virt `:` `,i++;return i=t+1&&e[a]===`\\`;)n++,a--;if(n%2==0)return r+=` `,[r,i+1]}r+=` `,i++}return[r,i]}function dr(e,t,n){let r=` `,i=t+1;for(;i!Un(e))}function mr(e,t){if(!Un(e[`build-system`]))return!1;if(typeof t==`string`){let e=fr(t);return/(?:^|\n)\s*\[\s*build-system\s*\]\s*(?:\n|$)/.test(e)}let n=Object.entries(e[`build-system`]);return n.length===0||n.some(([,e])=>!Un(e))}function hr(e,t){if(pr(e,t)||mr(e,t))return!0;if(Un(e.tool)&&Un(e.tool.uv)){let t=e.tool.uv;return Yn(t.workspace)||Array.isArray(t[`dev-dependencies`])}return!1}function gr(e){return Un(e.tool)&&Un(e.tool.uv)}function _r(e,t){return pr(e,t)||mr(e,t)}function vr(e,t){return p.relative(e,t)||`.`}function yr(e,t){if(!t)throw Error(`Invalid Python project configuration: 'uv.lock' was detected without a valid 'pyproject.toml' project or workspace configuration ('[project]', '[build-system]', or '[tool.uv.workspace]'). 'uv sync' requires a valid 'pyproject.toml' file.`);return{name:`uv`,lockfile:`uv.lock`,configFile:`pyproject.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}}function br(e,t){if(e.hasRequirementsTxt&&e.requirementsDir){let t=vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`));return{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`pip`,`install`,`-r`,t]}],execPrefix:`uv run`}}return t?{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}:null}function xr(e){let t=e.pyprojectToml?.success===!0&&hr(e.pyprojectToml.data,e.pyprojectToml.rawContent),n=e.workspaceRootToml?.success===!0&&hr(e.workspaceRootToml.data,e.workspaceRootToml.rawContent),r=t||n,i=e.uvToml?.success===!0,a=e.pyprojectToml?.success===!0&&gr(e.pyprojectToml.data)||e.workspaceRootToml?.success===!0&&gr(e.workspaceRootToml.data);return e.hasUvLock?yr(e,r):a||i?br(e,r):null}function Sr(e){let t=e.pyprojectToml?.success===!0&&_r(e.pyprojectToml.data,e.pyprojectToml.rawContent);if(!(e.hasRequirementsTxt||e.hasSetupPy||e.hasSetupCfg||t))return null;let n;t?n=`pyproject.toml`:e.hasSetupPy?n=`setup.py`:e.hasSetupCfg&&(n=`setup.cfg`);let r=[],i,a=e.hasSetupPy||e.hasSetupCfg||t,o=e.requirementsDir?vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`)):`requirements.txt`,s=vr(e.cwd,e.projectDir);return e.hasRequirementsTxt&&a?(r=[{executable:`pip`,args:[`install`,`-r`,o]},{executable:`pip`,args:[`install`,`-e`,s]}],i=`requirements.txt`):e.hasRequirementsTxt?(r=[{executable:`pip`,args:[`install`,`-r`,o]}],i=`requirements.txt`):a&&(r=[{executable:`pip`,args:[`install`,`-e`,s]}]),{name:`pip`,lockfile:i,configFile:n,installCommands:r,execPrefix:``}}function Cr(e=process.cwd(),t){if(t?.hasSource??or(e))return!0;let n=t?.ctx??ir(e);if(n.projectDir===n.cwd&&tr(n.cwd)&&(n.pyprojectToml?.success===!0&&hr(n.pyprojectToml.data,n.pyprojectToml.rawContent)||n.hasUvLock||n.hasRequirementsTxt||n.hasSetupPy||n.hasSetupCfg))return!0;if(n.workspaceRootDir&&n.workspaceRootToml?.success===!0){let t=Zn(n.workspaceRootDir);if(t&&Xn(n.workspaceRootDir,p.resolve(e),t.config))return!0}return!1}function wr(e,t){t!=null&&(e.pyprojectToml=t);for(let t of Vn)if(t===`uv`){let t=xr(e);if(t)return t}else if(t===`pip`){let t=Sr(e);if(t)return t}return{name:`pip`,installCommands:[],execPrefix:``,isStandalone:!0}}function Tr(e=process.cwd(),t,n){let r=n?.ctx??ir(e);return n?.isProject??Cr(e,{ctx:r,hasSource:n?.hasSource})?wr(r,t):null}function Er(e){if(!Array.isArray(e))throw Error(`Invalid Python environment: "pmInfo.installCommands" must be an array`);for(let t of e){if(!t||typeof t!=`object`)throw Error(`Invalid Python environment: malformed "installCommands" item`);let e=t;if(typeof e.executable!=`string`||!e.executable.trim()||!Array.isArray(e.args)||!e.args.every(e=>typeof e==`string`))throw Error(`Invalid Python environment: malformed "installCommands" item`)}}function Dr(e,t=`Invalid Python environment: "pmInfo" must be an object`){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(t);let n=e;if(n.name!==`uv`&&n.name!==`pip`)throw Error(`Invalid Python environment: pmInfo name must be "uv" or "pip"`);return Er(n.installCommands),n}function Or(e){if(!process.argv[1])return!1;try{return l(e)===f.realpathSync(process.argv[1])}catch{return!1}}async function kr(e,t,n=process.platform){let r=p.join(e,`node_modules`,`.bin`),i=/* @__PURE__ */ new Set([`.cmd`,`.bat`,`.exe`]);if(n===`win32`){let e=p.extname(t).toLowerCase();if(e){if(!i.has(e))return;let n=p.join(r,t);if(f.existsSync(n))return n}else for(let e of[`.cmd`,`.bat`,`.exe`,``]){let n=p.join(r,`${t}${e}`);if(f.existsSync(n))return n}}else{let e=p.join(r,t);if(f.existsSync(e))return e}let a=await Vt(t,!1);if(a){if(n===`win32`){let e=p.extname(a).toLowerCase();if(e&&!i.has(e))return}return a}}var Ar=class{platform;constructor(e=process.platform){this.platform=e}async resolveTaskExecutable(e){if(e.toolId===`npm-scripts`)return e.executable;if(e.toolId===`ruff`){if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);return`ruff`}let t=await kr(e.cwd,e.executable,this.platform);if(!t){let t=e.toolName||e.toolId,n=e.requiredPackage||e.executable;throw Error(`Configured tool "${t}" could not run: executable "${e.executable}" is not available in node_modules/.bin or PATH. Please install "${n}" in project dependencies.`)}return t}async executeTasks(e){let t=[];for(let n of e){let e=`${n.executable} ${n.args.join(` `)}`.trim();try{let r=await this.resolveTaskExecutable(n);en(`Executing: ${e}`);let i=n.env?Object.fromEntries(Object.entries({...process.env,...n.env}).filter(e=>e[1]!==void 0)):void 0,a=await Yt(r,n.args,{cwd:n.cwd,env:i,ignoreReturnCode:!0});if(a!==0){let r=n.toolId===`ruff`?`Ruff command "${e}" failed. Check Python and Ruff configuration.`:n.toolId===`npm-scripts`?`Script "${n.args[1]||e}" failed while executing "${e}".`:`Task "${n.id}" (${e}) failed with exit code ${a}.`;t.push({task:n,exitCode:a,error:Error(r)})}else t.push({task:n,exitCode:a})}catch(e){let r=e instanceof Error?e:Error(String(e));t.push({task:n,exitCode:1,error:r})}}return t}};function jr(e,t){return t.has(`autofix`)?!0:e===`autofix`?t.has(`format`)&&t.has(`lint`)&&t.has(`assist`):t.has(e)}function Mr(e,t){let n=[],r=[];for(let i of e)jr(i.capability,t)?r.push(i):n.push(i);return{kept:n,skipped:r}}function Nr(e,t){let n=e.get(t);return n||(n=/* @__PURE__ */ new Set,e.set(t,n)),n}async function Pr(e,t,n,r,i,a,o){for(let s of e){let e=s.adapter,c=Nr(t,s.scope),l=await e.plan(n,r);if(l.length===0)continue;let{kept:u,skipped:d}=Mr(l,c);if(u.length===0)a.push({id:e.id,name:e.name,reason:`all capabilities already covered by higher priority tool`});else{i.push({id:e.id,name:e.name,reason:s.reason});for(let e of u)if(c.add(e.capability),e.capabilities)for(let t of e.capabilities)c.add(t);if(o.push(...u),d.length>0){let t=Array.from(new Set(d.map(e=>e.capability))).join(`, `);a.push({id:e.id,name:e.name,reason:`partially skipped (${t} covered by higher priority tool)`})}}}}async function Fr(e,t,n,r,i,a,o){let s=[];for(let t of e.getStandaloneAdapters()){let e=await t.detect(n),r=t.scope??`standalone:${t.id}`;e.detected?s.push({adapter:t,reason:e.reason,scope:r}):e.reason&&!e.reason.startsWith(`no `)&&a.push({id:t.id,name:t.name,reason:e.reason})}await Pr(s,t,n,r,i,a,o)}function Ir(e){let t=[],n=/* @__PURE__ */ new Set;for(let r of e)n.has(r.id)||(n.add(r.id),t.push(r));return t}async function Lr(e,t,n=`fix`){let r=t.hasPythonSource??or(t.cwd),i=t.jsEnv??fn(t.cwd),a={...t,jsEnv:i,hasPythonSource:r},o=[],s=[],c=[],l=e.getProviders(),u=/* @__PURE__ */ new Map;for(let e of l){if(!await e.detect(a))continue;let t=e.getAdapters(a),r=[];for(let n of t){let t=await n.detect(a),i=n.scope??e.id;t.detected?r.push({adapter:n,reason:t.reason,scope:i}):t.reason&&!t.reason.startsWith(`no `)&&s.push({id:n.id,name:n.name,reason:t.reason})}await Pr(r,u,a,n,o,s,c)}await Fr(e,u,a,n,o,s,c);let d=Ir(c);return{tasks:d,selectedTools:o,skippedTools:s,summary:Rr(e,a,o,s,d)}}function Rr(e,t,n,r,i){let a=[];a.push(`Detected environments:`);let o=t.hasPythonSource??!1,s=t.jsEnv?.hasPackageJson??!1;if(a.push(` Python: ${o}`),a.push(` JavaScript: ${s}`),o&&(a.push(``),a.push(`Python toolchain:`),n.filter(e=>e.id===`ruff`).length>0?a.push(` Ruff: default tool`):a.push(` None`)),s){a.push(``),a.push(`JavaScript toolchain:`);let e=n.filter(e=>e.id!==`ruff`);for(let t of e)a.push(` ${t.name}: selected`);let t=r.filter(e=>e.id!==`ruff`);for(let e of t)a.push(` ${e.name}: skipped (${e.reason})`)}if(a.push(``),a.push(`Execution plan:`),i.length===0?a.push(` (no tasks to execute)`):i.forEach((e,t)=>{let n=e.description||`${e.executable} ${e.args.join(` `)}`;a.push(` ${t+1}. ${n}`)}),r.length>0){a.push(``),a.push(`Skipped:`);for(let e of r)a.push(` - ${e.name}: ${e.reason}`)}return a.join(` -`)}function zr(e){for(let t of[`format:write`,`format:fix`,`format`,`fmt`])if(e[t]&&Qi(e[t],e))return t}function Br(e){if(e[`format:check`]&&Zi(e[`format:check`],e)===`read-only`)return`format:check`;if(e[`fmt:check`]&&Zi(e[`fmt:check`],e)===`read-only`)return`fmt:check`}function Vr(e,t){return t===`fix`?zr(e):Br(e)}function Hr(e,t){if(t===`fix`)return e[`lint:fix`]?`lint:fix`:e[`lint:write`]?`lint:write`:void 0;if(e[`lint:check`]&&Zi(e[`lint:check`],e)===`read-only`)return`lint:check`;if(e.lint&&Zi(e.lint,e)===`read-only`)return`lint`}function Ur(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped)return 0;let r=e[t];return r===`;`||r===` +`)}function zr(e){for(let t of[`format:write`,`format:fix`,`format`,`fmt`])if(e[t]&&Xi(e[t],e))return t}function Br(e){if(e[`format:check`]&&Yi(e[`format:check`],e)===`read-only`)return`format:check`;if(e[`fmt:check`]&&Yi(e[`fmt:check`],e)===`read-only`)return`fmt:check`}function Vr(e,t){return t===`fix`?zr(e):Br(e)}function Hr(e,t){if(t===`fix`)return e[`lint:fix`]?`lint:fix`:e[`lint:write`]?`lint:write`:void 0;if(e[`lint:check`]&&Yi(e[`lint:check`],e)===`read-only`)return`lint:check`;if(e.lint&&Yi(e.lint,e)===`read-only`)return`lint`}function Ur(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped)return 0;let r=e[t];return r===`;`||r===` `?1:r===`&`&&e[t+1]===`&`||r===`|`&&e[t+1]===`|`?2:+(r===`|`)}function Wr(e,t){let n=t;for(;nt?n-1:t}function Gr(e,t){return t.inSingleQuote||t.inDoubleQuote||t.isEscaped?!1:e.length===0||/\s/.test(e[e.length-1])}function Kr(e,t){return t.isEscaped=!1,{ch:e,advance:!0}}function qr(e,t,n,r){let i=e[t];if(n.isEscaped)return{newCmd:r+Kr(i,n).ch,nextIndex:t,sepLen:0};if(i===`\\`&&!n.inSingleQuote)return n.isEscaped=!0,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`'`&&!n.inDoubleQuote)return n.inSingleQuote=!n.inSingleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`"`&&!n.inSingleQuote)return n.inDoubleQuote=!n.inDoubleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`#`&&Gr(r,n))return{newCmd:r,nextIndex:Wr(e,t),sepLen:0};let a=Ur(e,t,n);return{newCmd:r+(a===0?i:``),nextIndex:t,sepLen:a}}function Jr(e){let t=[],n=``,r={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1,hasSyntaxError:!1};for(let i=0;i0?(n.trim()&&t.push(n.trim()),n=``,i+=a.sepLen-1):(n=a.newCmd,i=a.nextIndex)}return(r.inSingleQuote||r.inDoubleQuote||r.isEscaped)&&(r.hasSyntaxError=!0),n.trim()&&t.push(n.trim()),{commands:t,hasSyntaxError:r.hasSyntaxError}}function Yr(e){return Jr(e).commands}function Xr(e,t,n){return t.isEscaped=!1,n+e}function Zr(e,t){return e===`'`&&!t.inDoubleQuote?(t.inSingleQuote=!t.inSingleQuote,!0):e===`"`&&!t.inSingleQuote&&(t.inDoubleQuote=!t.inDoubleQuote,!0)}const Qr=/* @__PURE__ */ new Set([`@`,`*`,`#`,`?`,`-`,`$`,`!`,`0`]);function $r(e,t,n){if(n.inSingleQuote||n.isEscaped||e[t]!==`$`||t+1>=e.length)return!1;let r=e[t+1];return!!(r===`{`||Qr.has(r)||r>=`1`&&r<=`9`||r===`_`||r>=`a`&&r<=`z`||r>=`A`&&r<=`Z`)}function ei(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped||e[t]!==`&`)return!1;let r=t>0?e[t-1]:``,i=t+1`}function ti(e,t,n){if(n.inSingleQuote||n.isEscaped)return!1;let r=e[t];return r==="`"||r===`$`&&t+1`)&&t+1`||r===`<`||r===`&`&&t+1`}function ii(e,t,n){return ei(e,t,n.state)||$r(e,t,n.state)||ti(e,t,n.state)||ni(e,t,n.state)?(n.inspection.hasUnsupportedSyntax=!0,!0):ri(e,t,n.state)?(n.inspection.hasRedirection=!0,n.inspection.hasUnsupportedSyntax=!0,!0):!1}function ai(e,t,n,r){let i=e[t];return n.state.isEscaped?{word:Xr(i,n.state,r),hasChars:!0,skipped:!1}:i===`\\`&&!n.state.inSingleQuote?(n.state.isEscaped=!0,{word:r,hasChars:!1,skipped:!0}):(ii(e,t,n),Zr(i,n.state)?{word:r,hasChars:!0,skipped:!0}:{word:r+i,hasChars:!0,skipped:!1})}function oi(e){let t={tokens:[],hasUnsupportedSyntax:!1,hasRedirection:!1},n={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1},r={inspection:t,state:n},i=``,a=!1;for(let o=0;o0&&n.push(t)}return n}function pi(e,t,n={},r=/* @__PURE__ */ new Set){if(!e||!t)return!1;let i=fi(n[e]===void 0?e:n[e]);for(let e of i){if(di(e,t))return!0;let i=Vi(e);if(i){if(i===t)return!0;if(!r.has(i)&&n[i]!==void 0){r.add(i);try{if(pi(n[i],t,n,r))return!0}finally{r.delete(i)}}}let a=Hi(e);if(a!==void 0&&pi(a,t,n,r))return!0}return!1}function mi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function hi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function gi(e){let[t]=e;return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||(e===`--fix`||e.startsWith(`--fix=`))&&(t!==`eslint`||e!==`--fix-dry-run`))}function _i(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function vi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function yi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function bi(e){let[t]=e;return t===`eslint`&&e.some(e=>(e===`--fix`||e.startsWith(`--fix=`))&&e!==`--fix-dry-run`)}function xi(e){let[t]=e;return t===`oxlint`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Si(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Ci(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function wi(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:!e.some(e=>e===`--check`||e===`-c`)}function Ti(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Ei(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)&&e!==`--fix-dry-run`||e===`-o`||e.startsWith(`-o=`)||e===`--output-file`||e.startsWith(`--output-file=`)||e===`--cache`||e===`--cache-file`||e.startsWith(`--cache-file=`)||e===`--cache-location`||e.startsWith(`--cache-location=`))}function Di(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--cache`||e===`--cache-location`||e.startsWith(`--cache-location=`)||e===`--insert-pragma`)}function Oi(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`)||e===`--reporter-file`||e.startsWith(`--reporter-file=`)||e===`--log-file`||e.startsWith(`--log-file=`))}function ki(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)||e===`--fix-suggestions`||e===`--fix-dangerously`||e===`--init`)}function Ai(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--init`||e===`--migrate`||e.startsWith(`--migrate=`))}function ji(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`--check`||e===`-c`||e===`--list-different`||e===`-l`)&&!Di(e)}function Mi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function Ni(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:!Oi(e)}function Pi(e){let[t]=e;return t===`eslint`&&!Ei(e)}function Fi(e){let[t]=e;return t===`oxlint`&&!ki(e)}function Ii(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:!Oi(e)}function Li(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:!Oi(e)}function Ri(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function zi(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:!ki(e)}function Bi(e){let[t,n]=e;return t!==`vp`||n!==`check`?!1:!e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Vi(e){if(e.length===0)return;let[t,n,r]=e;if((t===`npm`||t===`pnpm`||t===`yarn`||t===`bun`)&&n===`run`&&r)return r;if((t===`pnpm`||t===`bun`||t===`yarn`)&&n&&!n.startsWith(`-`))return n}function Hi(e){if(e.length>=3&&(e[0]===`sh`||e[0]===`bash`)&&e[1]===`-c`)return e[2]}const Ui=/* @__PURE__ */ new Set([`-f`,`--file`,`-c`,`--config`,`--env-file`]),Wi=/* @__PURE__ */ new Set([`-h`,`--help`,`-v`,`--version`,`--shell`]);function Gi(e){if(e.length===0)return e;let[t]=e;if(t!==`cross-env`&&t!==`cross-env-shell`)return e;let n=1;for(;n=e.length)return[];n+=2}else if(Wi.has(t))n++;else{if(t.startsWith(`-`))return[];if(li(t))n++;else break}}return e.slice(n)}function Ki(e,t={},n=/* @__PURE__ */ new Set){if(!e)return!1;let r=fi(e);for(let e of r){let r=Gi(e);if(r.length===0)continue;if(r[0]===`vp`||(r[0]===`npx`||r[0]===`bunx`)&&r[1]===`vp`||(r[0]===`npm`||r[0]===`pnpm`||r[0]===`yarn`)&&(r[1]===`exec`||r[1]===`dlx`)&&r[2]===`vp`)return!0;let i=Hi(r);if(i!==void 0&&Ki(i,t,n))return!0;let a=Vi(r);if(a&&!n.has(a)&&t[a]){n.add(a);try{if(Ki(t[a],t,n))return!0}finally{n.delete(a)}}}return!1}function qi(e){return _i(e)||vi(e)||yi(e)||bi(e)||xi(e)||Si(e)||Ci(e)||wi(e)||Ti(e)}function Ji(e){return ji(e)||Mi(e)||Ni(e)||Pi(e)||Fi(e)||Ii(e)||Li(e)||Ri(e)||zi(e)||Bi(e)}function Yi(e,t,n){if(e.length===0)return`unknown`;if(gi(e))return`write-capable`;let r=Hi(e);if(r!==void 0)return Xi(r,t,n);let i=Vi(e);if(i){if(n.has(i))return`unknown`;let e=t[i];if(!e)return`unknown`;n.add(i);try{return Xi(e,t,n)}finally{n.delete(i)}}return qi(e)?`write-capable`:Ji(e)?`read-only`:`unknown`}function Xi(e,t,n){let r=Jr(e);if(r.hasSyntaxError)return`unknown`;let{commands:i}=r;if(i.length===0)return`unknown`;let a=!1;for(let e of i){let r=oi(e),i=Yi(ui(r.tokens),t,n);if(i===`write-capable`)return`write-capable`;if(r.hasUnsupportedSyntax||i===`unknown`)return`unknown`;i===`read-only`&&(a=!0)}return a?`read-only`:`unknown`}function Zi(e,t={}){return Xi(e,t,/* @__PURE__ */ new Set)}function Qi(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Qi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?_i(e)||vi(e)||yi(e)||wi(e):Qi(i,t,n)})}function $i(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return $i(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?bi(e)||xi(e)||Si(e)||Ti(e):$i(i,t,n)})}function ea(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return ea(e,t,n)}finally{n.delete(r)}}let i=Hi(e);if(i!==void 0)return ea(i,t,n);if(Ci(e))return!0;let[a,o]=e;return a===`vp`&&o===`check`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))})}function ta(e,t,n,r){return t&&pi(e,t,n)?!0:r(e)}function na(e,t,n,r,i){let a=ta(t,r,e,t=>Qi(t,e)),o=ta(t,i,e,t=>$i(t,e)),s=ea(t,e);return a&&o?[{capability:`format`,capabilities:[`format`,`lint`],scriptName:n}]:a&&!s?[{capability:`format`,scriptName:n}]:o&&!s?[{capability:`lint`,scriptName:n}]:s?[{capability:`autofix`,scriptName:n}]:[{capability:`typecheck`,capabilities:[],scriptName:n}]}function ra(e,t){return Qi(t[e],t)?{capability:`format`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function ia(e,t){return $i(t[e],t)?{capability:`lint`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function aa(e,t,n){let r=[];return e&&r.push(ra(e,n)),t&&r.push(ia(t,n)),r}function oa(e,t,n,r,i){r&&mi(t,n,r)&&e.push(ra(r,t)),i&&hi(t,n,i)&&e.push(ia(i,t))}function sa(e){let t=e.fix?`fix`:e[`check:fix`]?`check:fix`:void 0,n=Vr(e,`fix`),r=Hr(e,`fix`);if(!t)return aa(n,r,e);let i=na(e,e[t]||``,t,n,r);return oa(i,e,t,n,r),i}function ca(e){let t=[],n=Vr(e,`check`),r=Hr(e,`check`);return n&&t.push({capability:`format`,scriptName:n}),r&&t.push({capability:`lint`,scriptName:r}),t}function la(e,t){return t===`fix`?sa(e):ca(e)}var ua=class{id=`npm-scripts`;name=`package.json scripts`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson?.scripts;if(!t||Object.keys(t).length===0)return{detected:!1,reason:`no scripts declared in package.json`};let n=la(t,`fix`),r=la(t,`check`),i=[...n,...r];return i.length>0?{detected:!0,reason:`found supported scripts: ${Array.from(new Set(i.map(e=>`"${e.scriptName}"`))).join(`, `)}`}:{detected:!1,reason:`no supported autofix or check scripts found in package.json`}}plan(e,t){let n=la(e.jsEnv?.packageJson?.scripts||{},t),r=cn(e.jsPm||`npm`);return n.map(n=>({id:`script-${n.scriptName}`,toolId:this.id,capability:n.capability,capabilities:n.capabilities,executable:r,args:[`run`,n.scriptName],cwd:e.cwd,mode:t,description:`package.json script: ${r} run ${n.scriptName}`}))}};function da(e){return e?Object.values(e).some(t=>Ki(t,e)):!1}function fa(e,t){return e?!!(e.dependencies?.[t]||e.devDependencies?.[t]||e.peerDependencies?.[t]||e.optionalDependencies?.[t]):!1}function pa(e,t){for(let n of t)if(f.existsSync(p.join(e,n)))return!0;return!1}var ma=class{id=`vite-plus`;name=`Vite+`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sn(t),r=pa(e.cwd,[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.cjs`]);return n||r&&da(t?.scripts)?{detected:!0,reason:`Vite+ dependency and/or configuration detected`}:{detected:!1,reason:`no Vite+ dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`vite-plus-fmt`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp fmt`},{id:`vite-plus-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`,`--fix`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp lint --fix`}]:[{id:`vite-plus-fmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`,`--check`],cwd:e.cwd,mode:`check`,description:`Vite+: vp fmt --check`},{id:`vite-plus-lint`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`],cwd:e.cwd,mode:`check`,description:`Vite+: vp lint`}]}},ha=class{id=`biome`;name=`Biome`;capabilities=[`format`,`lint`,`assist`];detect(e){let t=e.jsEnv?.packageJson,n=fa(t,`@biomejs/biome`),r=pa(e.cwd,[`biome.json`,`biome.jsonc`]);return n&&r?{detected:!0,reason:`Biome dependency and configuration detected`}:r?{detected:!0,reason:`Biome configuration detected`}:n?{detected:!1,reason:`Biome dependency present without configuration file`}:{detected:!1,reason:`no Biome dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`biome-format-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: format --write .`},{id:`biome-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: lint --write .`},{id:`biome-assist-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--write`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: safe assist actions (--write)`}]:[{id:`biome-format-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: format .`},{id:`biome-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: lint .`},{id:`biome-assist-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: check assist actions`}]}},ga=class{id=`prettier`;name=`Prettier`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=fa(t,`prettier`),r=!!t?.prettier,i=pa(e.cwd,[`.prettierrc`,`.prettierrc.json`,`.prettierrc.yml`,`.prettierrc.yaml`,`.prettierrc.json5`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`]);return n&&(r||i)?{detected:!0,reason:`Prettier dependency and configuration detected`}:r||i?{detected:!0,reason:`Prettier configuration detected`}:n?{detected:!1,reason:`Prettier dependency present without configuration`}:{detected:!1,reason:`no Prettier dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`prettier-format`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Prettier: format`}]:[{id:`prettier-check`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Prettier: format check`}]}},_a=class{id=`eslint`;name=`ESLint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=fa(t,`eslint`),r=!!t?.eslintConfig,i=pa(e.cwd,[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yaml`,`.eslintrc.yml`]);return n&&(r||i)?{detected:!0,reason:`ESLint dependency and configuration detected`}:r||i?{detected:!0,reason:`ESLint configuration detected`}:n?{detected:!1,reason:`ESLint dependency present without configuration`}:{detected:!1,reason:`no ESLint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`eslint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`ESLint: lint autofix`}]:[{id:`eslint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`ESLint: lint check`}]}},va=class{id=`oxlint`;name=`Oxlint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=fa(t,`oxlint`),r=pa(e.cwd,[`.oxlintrc.json`,`oxlint.json`,`oxlint.config.ts`,`oxlint.config.js`]);return n&&r?{detected:!0,reason:`Oxlint dependency and configuration detected`}:r?{detected:!0,reason:`Oxlint configuration detected`}:n?{detected:!1,reason:`Oxlint dependency present without configuration`}:{detected:!1,reason:`no Oxlint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxlint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxlint: lint autofix`}]:[{id:`oxlint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`Oxlint: lint check`}]}},ya=class{id=`oxfmt`;name=`Oxfmt`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=fa(t,`oxfmt`),r=pa(e.cwd,[`.oxfmtrc.json`,`oxfmt.json`,`oxfmt.config.ts`,`oxfmt.config.js`]);return n&&r?{detected:!0,reason:`Oxfmt dependency and configuration detected`}:r?{detected:!0,reason:`Oxfmt configuration detected`}:n?{detected:!1,reason:`Oxfmt dependency present without configuration`}:{detected:!1,reason:`no Oxfmt dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxfmt-format`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxfmt: format`}]:[{id:`oxfmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Oxfmt: format check`}]}},ba=class{id=`javascript`;name=`JavaScript/TypeScript`;scriptAdapter=new ua;vitePlusAdapter=new ma;biomeAdapter=new ha;prettierAdapter=new ga;eslintAdapter=new _a;oxlintAdapter=new va;oxfmtAdapter=new ya;detect(e){return!!e.jsEnv?.hasPackageJson}getAdapters(e){return[this.scriptAdapter,this.vitePlusAdapter,this.biomeAdapter,this.oxfmtAdapter,this.prettierAdapter,this.oxlintAdapter,this.eslintAdapter]}},xa=class{id=`ruff`;name=`Ruff`;capabilities=[`lint`,`format`];detect(e){return e.hasPythonSource??or(e.cwd)?{detected:!0,reason:`default Python toolchain`}:{detected:!1,reason:`no Python source files detected`}}plan(e,t){let n=[];return t===`fix`?n.push({id:`ruff-lint-fix`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: lint autofix`},{id:`ruff-format`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: format`}):n.push({id:`ruff-lint-check`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: lint check`},{id:`ruff-format-check`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: format check`}),n}},Sa=class{id=`python`;name=`Python`;ruffAdapter=new xa;detect(e){return e.hasPythonSource??or(e.cwd)}getAdapters(e){return[this.ruffAdapter]}},Ca=class{providers=/* @__PURE__ */ new Map;standaloneAdapters=/* @__PURE__ */ new Map;registerProvider(e){this.providers.set(e.id,e)}getProvider(e){return this.providers.get(e)}getProviders(){return Array.from(this.providers.values())}registerAdapter(e){this.standaloneAdapters.set(e.id,e)}getAdapter(e){return this.standaloneAdapters.get(e)}getStandaloneAdapters(){return Array.from(this.standaloneAdapters.values())}clear(){this.providers.clear(),this.standaloneAdapters.clear()}};function wa(){let e=new Ca;return e.registerProvider(new Sa),e.registerProvider(new ba),e}const Ta=wa();async function Ea(e,t=process.cwd()){let n=`${e.command} ${e.args.join(` `)}`.trim();if(en(`Installing JS dependencies: ${n}`),await Yt(e.command,e.args,{cwd:t,ignoreReturnCode:!0})!==0)throw Error(`JS dependency installation failed executing "${n}". Check dependency constraints or lockfile compatibility.`)}async function Da(e=process.cwd()){let t=fn(e);if(!t.hasPackageJson){en(`No package.json found. Skipping scripts.`);return}if(t.packageJsonError)throw Error(t.packageJsonError);let n=cn(process.env.PACKAGE_MANAGER||_n(t).name),r=(await Lr(Ta,{cwd:e,jsEnv:t,jsPm:n,hasPythonSource:!1},`fix`)).tasks.filter(e=>e.toolId!==`ruff`);if(r.length===0){en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`);return}await Ea(vn(n),e);let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}}async function Oa(e,t,n=process.cwd()){let r=`${e} ${t.join(` `)}`.trim();if(en(`Executing: ${r}`),await Yt(e,t,{cwd:n,ignoreReturnCode:!0})!==0)throw Error(`Python command "${r}" failed. Check Python environment and dependency configuration.`)}async function ka(e,t=process.cwd()){Dr(e,`Invalid Python environment: "pmInfo" must be an object`);let n=e.name===`pip`?`pip`:e.name;if(!await Vt(n,!1)&&!e.isStandalone){let e=`Required Python package manager '${n}' is not available in PATH.`;throw Error(e)}if(!e.isStandalone&&e.installCommands.length>0){let n=e.installCommands;en(`Installing Python dependencies: ${n.map(e=>`${e.executable} ${e.args.join(` `)}`).join(` && `)}`);for(let{executable:e,args:r}of n)await Oa(e,r,t)}}async function Aa(e=process.cwd(),t,n){if(!(t??or(e)))return;let r;if(n)r=n;else{if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);r=(await Lr(Ta,{cwd:e,hasPythonSource:!0},`fix`)).tasks.filter(e=>e.toolId===`ruff`)}let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}}async function ja(e,t){if(process.env.JS_SETUP_OUTCOME===`failure`||process.env.NODE_SETUP_OUTCOME===`failure`||process.env.BUN_SETUP_OUTCOME===`failure`||process.env.PNPM_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`JavaScript runtime or package manager setup failed.`);try{if(t){let n=fn(e);if(!n.hasPackageJson)return en(`No package.json found. Skipping scripts.`),null;if(n.packageJsonError)throw Error(n.packageJsonError);if(t.length===0)return en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`),null;await Ea(vn(cn(process.env.PACKAGE_MANAGER||_n(n).name)),e);let r=(await new Ar().executeTasks(t)).filter(e=>e.error);if(r.length>0){let e=r.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}return null}return await Da(e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Ma(e,t){if(process.env.PYTHON_SETUP_OUTCOME===`failure`||process.env.UV_SETUP_OUTCOME===`failure`||process.env.PY_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Python runtime or package manager setup failed.`);let n=t&&`pmInfo`in t?t.pmInfo:Tr(e,void 0,{ctx:t?.ctx,hasSource:t?.hasSource});if(!n)return null;try{return await ka(n,e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Na(e,t,n){if(process.env.RUFF_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Ruff setup failed.`);try{return await Aa(e,t,n),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Pa(e,t,n){let r=t??or(e);if(!r)return[];let i=[],a=ir(e),o=await Ma(e,{ctx:a,hasSource:!0,pmInfo:Tr(e,void 0,{ctx:a,hasSource:!0,isProject:!0})});o&&i.push(o);let s=await Na(e,r,n);return s&&i.push(s),i}async function Fa(e=process.cwd()){let t=or(e),n;try{let r=fn(e),i={cwd:e,jsEnv:r,jsPm:cn(process.env.PACKAGE_MANAGER||_n(r).name),hasPythonSource:t};n=await Lr(Ta,i,`fix`),en(n.summary)}catch{}let r=[],i=n?n.tasks.filter(e=>e.toolId!==`ruff`):void 0,a=n?n.tasks.filter(e=>e.toolId===`ruff`):void 0,o=await ja(e,i);o&&r.push(o);let s=await Pa(e,t,a);r.push(...s),r.length>0&&(Zt(`Failed to run scripts: ${r.map(e=>e.message).join(` -`)}`),process.env.NODE_ENV!==`test`&&process.exit(1))}process.env.NODE_ENV!==`test`&&Or(import.meta.url)&&Fa();export{Da as executeJsWorkflow,ka as executePythonWorkflow,Aa as executeRuffAutofix,Fa as run,cn as sanitizePackageManager}; \ No newline at end of file +`;)n++;return n>t?n-1:t}function Gr(e,t){return t.inSingleQuote||t.inDoubleQuote||t.isEscaped?!1:e.length===0||/\s/.test(e[e.length-1])}function Kr(e,t){return t.isEscaped=!1,{ch:e,advance:!0}}function qr(e,t,n,r){let i=e[t];if(n.isEscaped)return{newCmd:r+Kr(i,n).ch,nextIndex:t,sepLen:0};if(i===`\\`&&!n.inSingleQuote)return n.isEscaped=!0,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`'`&&!n.inDoubleQuote)return n.inSingleQuote=!n.inSingleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`"`&&!n.inSingleQuote)return n.inDoubleQuote=!n.inDoubleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`#`&&Gr(r,n))return{newCmd:r,nextIndex:Wr(e,t),sepLen:0};let a=Ur(e,t,n);return{newCmd:r+(a===0?i:``),nextIndex:t,sepLen:a}}function Jr(e){let t=[],n=``,r={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1,hasSyntaxError:!1};for(let i=0;i0?(n.trim()&&t.push(n.trim()),n=``,i+=a.sepLen-1):(n=a.newCmd,i=a.nextIndex)}return(r.inSingleQuote||r.inDoubleQuote||r.isEscaped)&&(r.hasSyntaxError=!0),n.trim()&&t.push(n.trim()),{commands:t,hasSyntaxError:r.hasSyntaxError}}function Yr(e){return Jr(e).commands}function Xr(e,t,n){return t.isEscaped=!1,n+e}function Zr(e,t){return e===`'`&&!t.inDoubleQuote?(t.inSingleQuote=!t.inSingleQuote,!0):e===`"`&&!t.inSingleQuote&&(t.inDoubleQuote=!t.inDoubleQuote,!0)}const Qr=/* @__PURE__ */ new Set([`@`,`*`,`#`,`?`,`-`,`$`,`!`,`0`]);function $r(e,t,n){if(n.inSingleQuote||n.isEscaped||e[t]!==`$`||t+1>=e.length)return!1;let r=e[t+1];return!!(r===`{`||Qr.has(r)||r>=`1`&&r<=`9`||r===`_`||r>=`a`&&r<=`z`||r>=`A`&&r<=`Z`)}function ei(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped||e[t]!==`&`)return!1;let r=t>0?e[t-1]:``,i=t+1`}function ti(e,t,n){if(n.inSingleQuote||n.isEscaped)return!1;let r=e[t];return r==="`"||r===`$`&&t+1`)&&t+1`||r===`<`||r===`&`&&t+1`}function ii(e,t,n){return ei(e,t,n.state)||$r(e,t,n.state)||ti(e,t,n.state)||ni(e,t,n.state)?(n.inspection.hasUnsupportedSyntax=!0,!0):ri(e,t,n.state)?(n.inspection.hasRedirection=!0,n.inspection.hasUnsupportedSyntax=!0,!0):!1}function ai(e,t,n,r){let i=e[t];return n.state.isEscaped?{word:Xr(i,n.state,r),hasChars:!0,skipped:!1}:i===`\\`&&!n.state.inSingleQuote?(n.state.isEscaped=!0,{word:r,hasChars:!1,skipped:!0}):(ii(e,t,n),Zr(i,n.state)?{word:r,hasChars:!0,skipped:!0}:{word:r+i,hasChars:!0,skipped:!1})}function oi(e){let t={tokens:[],hasUnsupportedSyntax:!1,hasRedirection:!1},n={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1},r={inspection:t,state:n},i=``,a=!1;for(let o=0;o0&&n.push(t)}return n}function pi(e,t,n={},r=/* @__PURE__ */ new Set){if(!e||!t)return!1;let i=fi(n[e]===void 0?e:n[e]);for(let e of i){if(di(e,t))return!0;let i=Vi(e);if(i){if(i===t)return!0;if(!r.has(i)&&n[i]!==void 0){r.add(i);try{if(pi(n[i],t,n,r))return!0}finally{r.delete(i)}}}let a=Hi(e);if(a!==void 0&&pi(a,t,n,r))return!0}return!1}function mi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function hi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function gi(e){let[t]=e;return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||(e===`--fix`||e.startsWith(`--fix=`))&&(t!==`eslint`||e!==`--fix-dry-run`))}function _i(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function vi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function yi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function bi(e){let[t]=e;return t===`eslint`&&e.some(e=>(e===`--fix`||e.startsWith(`--fix=`))&&e!==`--fix-dry-run`)}function xi(e){let[t]=e;return t===`oxlint`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Si(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Ci(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function wi(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:!e.some(e=>e===`--check`||e===`-c`)}function Ti(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Ei(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)&&e!==`--fix-dry-run`||e===`-o`||e.startsWith(`-o=`)||e===`--output-file`||e.startsWith(`--output-file=`)||e===`--cache`||e===`--cache-file`||e.startsWith(`--cache-file=`)||e===`--cache-location`||e.startsWith(`--cache-location=`))}function Di(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--cache`||e===`--cache-location`||e.startsWith(`--cache-location=`)||e===`--insert-pragma`)}function Oi(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`)||e===`--reporter-file`||e.startsWith(`--reporter-file=`)||e===`--log-file`||e.startsWith(`--log-file=`))}function ki(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)||e===`--fix-suggestions`||e===`--fix-dangerously`||e===`--init`)}function Ai(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--init`||e===`--migrate`||e.startsWith(`--migrate=`))}function ji(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`--check`||e===`-c`||e===`--list-different`||e===`-l`)&&!Di(e)}function Mi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function Ni(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:!Oi(e)}function Pi(e){let[t]=e;return t===`eslint`&&!Ei(e)}function Fi(e){let[t]=e;return t===`oxlint`&&!ki(e)}function Ii(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:!Oi(e)}function Li(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:!Oi(e)}function Ri(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function zi(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:!ki(e)}function Bi(e){let[t,n]=e;return t!==`vp`||n!==`check`?!1:!e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Vi(e){if(e.length===0)return;let[t,n,r]=e;if((t===`npm`||t===`pnpm`||t===`yarn`||t===`bun`)&&n===`run`&&r)return r;if((t===`pnpm`||t===`bun`||t===`yarn`)&&n&&!n.startsWith(`-`))return n}function Hi(e){if(e.length>=3&&(e[0]===`sh`||e[0]===`bash`)&&e[1]===`-c`)return e[2]}function Ui(e){if(e.length===0)return e;let[t]=e;if(t!==`cross-env`&&t!==`cross-env-shell`)return e;let n=1;for(;n{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Xi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?_i(e)||vi(e)||yi(e)||wi(e):Xi(i,t,n)})}function Zi(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Zi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?bi(e)||xi(e)||Si(e)||Ti(e):Zi(i,t,n)})}function Qi(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Qi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);if(i!==void 0)return Qi(i,t,n);if(Ci(e))return!0;let[a,o]=e;return a===`vp`&&o===`check`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))})}function $i(e,t,n,r){return t&&pi(e,t,n)?!0:r(e)}function ea(e,t,n,r,i){let a=$i(t,r,e,t=>Xi(t,e)),o=$i(t,i,e,t=>Zi(t,e)),s=Qi(t,e);return a&&o?[{capability:`format`,capabilities:[`format`,`lint`],scriptName:n}]:a&&!s?[{capability:`format`,scriptName:n}]:o&&!s?[{capability:`lint`,scriptName:n}]:s?[{capability:`autofix`,scriptName:n}]:[{capability:`typecheck`,capabilities:[],scriptName:n}]}function ta(e,t){return Xi(t[e],t)?{capability:`format`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function na(e,t){return Zi(t[e],t)?{capability:`lint`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function ra(e,t,n){let r=[];return e&&r.push(ta(e,n)),t&&r.push(na(t,n)),r}function ia(e,t,n,r,i){r&&mi(t,n,r)&&e.push(ta(r,t)),i&&hi(t,n,i)&&e.push(na(i,t))}function aa(e){let t=e.fix?`fix`:e[`check:fix`]?`check:fix`:void 0,n=Vr(e,`fix`),r=Hr(e,`fix`);if(!t)return ra(n,r,e);let i=ea(e,e[t]||``,t,n,r);return ia(i,e,t,n,r),i}function oa(e){let t=[],n=Vr(e,`check`),r=Hr(e,`check`);return n&&t.push({capability:`format`,scriptName:n}),r&&t.push({capability:`lint`,scriptName:r}),t}function sa(e,t){return t===`fix`?aa(e):oa(e)}var ca=class{id=`npm-scripts`;name=`package.json scripts`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson?.scripts;if(!t||Object.keys(t).length===0)return{detected:!1,reason:`no scripts declared in package.json`};let n=sa(t,`fix`),r=sa(t,`check`),i=[...n,...r];return i.length>0?{detected:!0,reason:`found supported scripts: ${Array.from(new Set(i.map(e=>`"${e.scriptName}"`))).join(`, `)}`}:{detected:!1,reason:`no supported autofix or check scripts found in package.json`}}plan(e,t){let n=sa(e.jsEnv?.packageJson?.scripts||{},t),r=cn(e.jsPm||`npm`);return n.map(n=>({id:`script-${n.scriptName}`,toolId:this.id,capability:n.capability,capabilities:n.capabilities,executable:r,args:[`run`,n.scriptName],cwd:e.cwd,mode:t,description:`package.json script: ${r} run ${n.scriptName}`}))}};function la(e){return e?Object.values(e).some(t=>Wi(t,e)):!1}function ua(e,t){return e?!!(e.dependencies?.[t]||e.devDependencies?.[t]||e.peerDependencies?.[t]||e.optionalDependencies?.[t]):!1}function da(e,t){for(let n of t)if(f.existsSync(p.join(e,n)))return!0;return!1}var fa=class{id=`vite-plus`;name=`Vite+`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sn(t),r=da(e.cwd,[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.cjs`]);return n||r&&la(t?.scripts)?{detected:!0,reason:`Vite+ dependency and/or configuration detected`}:{detected:!1,reason:`no Vite+ dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`vite-plus-fmt`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp fmt`},{id:`vite-plus-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`,`--fix`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp lint --fix`}]:[{id:`vite-plus-fmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`,`--check`],cwd:e.cwd,mode:`check`,description:`Vite+: vp fmt --check`},{id:`vite-plus-lint`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`],cwd:e.cwd,mode:`check`,description:`Vite+: vp lint`}]}},pa=class{id=`biome`;name=`Biome`;capabilities=[`format`,`lint`,`assist`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`@biomejs/biome`),r=da(e.cwd,[`biome.json`,`biome.jsonc`]);return n&&r?{detected:!0,reason:`Biome dependency and configuration detected`}:r?{detected:!0,reason:`Biome configuration detected`}:n?{detected:!1,reason:`Biome dependency present without configuration file`}:{detected:!1,reason:`no Biome dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`biome-format-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: format --write .`},{id:`biome-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: lint --write .`},{id:`biome-assist-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--write`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: safe assist actions (--write)`}]:[{id:`biome-format-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: format .`},{id:`biome-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: lint .`},{id:`biome-assist-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: check assist actions`}]}},ma=class{id=`prettier`;name=`Prettier`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`prettier`),r=!!t?.prettier,i=da(e.cwd,[`.prettierrc`,`.prettierrc.json`,`.prettierrc.yml`,`.prettierrc.yaml`,`.prettierrc.json5`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`]);return n&&(r||i)?{detected:!0,reason:`Prettier dependency and configuration detected`}:r||i?{detected:!0,reason:`Prettier configuration detected`}:n?{detected:!1,reason:`Prettier dependency present without configuration`}:{detected:!1,reason:`no Prettier dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`prettier-format`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Prettier: format`}]:[{id:`prettier-check`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Prettier: format check`}]}},ha=class{id=`eslint`;name=`ESLint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`eslint`),r=!!t?.eslintConfig,i=da(e.cwd,[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yaml`,`.eslintrc.yml`]);return n&&(r||i)?{detected:!0,reason:`ESLint dependency and configuration detected`}:r||i?{detected:!0,reason:`ESLint configuration detected`}:n?{detected:!1,reason:`ESLint dependency present without configuration`}:{detected:!1,reason:`no ESLint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`eslint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`ESLint: lint autofix`}]:[{id:`eslint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`ESLint: lint check`}]}},ga=class{id=`oxlint`;name=`Oxlint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`oxlint`),r=da(e.cwd,[`.oxlintrc.json`,`oxlint.json`,`oxlint.config.ts`,`oxlint.config.js`]);return n&&r?{detected:!0,reason:`Oxlint dependency and configuration detected`}:r?{detected:!0,reason:`Oxlint configuration detected`}:n?{detected:!1,reason:`Oxlint dependency present without configuration`}:{detected:!1,reason:`no Oxlint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxlint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxlint: lint autofix`}]:[{id:`oxlint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`Oxlint: lint check`}]}},_a=class{id=`oxfmt`;name=`Oxfmt`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`oxfmt`),r=da(e.cwd,[`.oxfmtrc.json`,`oxfmt.json`,`oxfmt.config.ts`,`oxfmt.config.js`]);return n&&r?{detected:!0,reason:`Oxfmt dependency and configuration detected`}:r?{detected:!0,reason:`Oxfmt configuration detected`}:n?{detected:!1,reason:`Oxfmt dependency present without configuration`}:{detected:!1,reason:`no Oxfmt dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxfmt-format`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxfmt: format`}]:[{id:`oxfmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Oxfmt: format check`}]}},va=class{id=`javascript`;name=`JavaScript/TypeScript`;scriptAdapter=new ca;vitePlusAdapter=new fa;biomeAdapter=new pa;prettierAdapter=new ma;eslintAdapter=new ha;oxlintAdapter=new ga;oxfmtAdapter=new _a;detect(e){return!!e.jsEnv?.hasPackageJson}getAdapters(e){return[this.scriptAdapter,this.vitePlusAdapter,this.biomeAdapter,this.oxfmtAdapter,this.prettierAdapter,this.oxlintAdapter,this.eslintAdapter]}},ya=class{id=`ruff`;name=`Ruff`;capabilities=[`lint`,`format`];detect(e){return e.hasPythonSource??or(e.cwd)?{detected:!0,reason:`default Python toolchain`}:{detected:!1,reason:`no Python source files detected`}}plan(e,t){let n=[];return t===`fix`?n.push({id:`ruff-lint-fix`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: lint autofix`},{id:`ruff-format`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: format`}):n.push({id:`ruff-lint-check`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: lint check`},{id:`ruff-format-check`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: format check`}),n}},ba=class{id=`python`;name=`Python`;ruffAdapter=new ya;detect(e){return e.hasPythonSource??or(e.cwd)}getAdapters(e){return[this.ruffAdapter]}},xa=class{providers=/* @__PURE__ */ new Map;standaloneAdapters=/* @__PURE__ */ new Map;registerProvider(e){this.providers.set(e.id,e)}getProvider(e){return this.providers.get(e)}getProviders(){return Array.from(this.providers.values())}registerAdapter(e){this.standaloneAdapters.set(e.id,e)}getAdapter(e){return this.standaloneAdapters.get(e)}getStandaloneAdapters(){return Array.from(this.standaloneAdapters.values())}clear(){this.providers.clear(),this.standaloneAdapters.clear()}};function Sa(){let e=new xa;return e.registerProvider(new ba),e.registerProvider(new va),e}const Ca=Sa();async function wa(e,t=process.cwd()){let n=`${e.command} ${e.args.join(` `)}`.trim();if(en(`Installing JS dependencies: ${n}`),await Yt(e.command,e.args,{cwd:t,ignoreReturnCode:!0})!==0)throw Error(`JS dependency installation failed executing "${n}". Check dependency constraints or lockfile compatibility.`)}async function Ta(e=process.cwd()){let t=fn(e);if(!t.hasPackageJson){en(`No package.json found. Skipping scripts.`);return}if(t.packageJsonError)throw Error(t.packageJsonError);let n=cn(process.env.PACKAGE_MANAGER||_n(t).name),r=(await Lr(Ca,{cwd:e,jsEnv:t,jsPm:n,hasPythonSource:!1},`fix`)).tasks.filter(e=>e.toolId!==`ruff`);if(r.length===0){en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`);return}await wa(vn(n),e);let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}}async function Ea(e,t,n=process.cwd()){let r=`${e} ${t.join(` `)}`.trim();if(en(`Executing: ${r}`),await Yt(e,t,{cwd:n,ignoreReturnCode:!0})!==0)throw Error(`Python command "${r}" failed. Check Python environment and dependency configuration.`)}async function Da(e,t=process.cwd()){Dr(e,`Invalid Python environment: "pmInfo" must be an object`);let n=e.name===`pip`?`pip`:e.name;if(!await Vt(n,!1)&&!e.isStandalone){let e=`Required Python package manager '${n}' is not available in PATH.`;throw Error(e)}if(!e.isStandalone&&e.installCommands.length>0){let n=e.installCommands;en(`Installing Python dependencies: ${n.map(e=>`${e.executable} ${e.args.join(` `)}`).join(` && `)}`);for(let{executable:e,args:r}of n)await Ea(e,r,t)}}async function Oa(e=process.cwd(),t,n){if(!(t??or(e)))return;let r;if(n)r=n;else{if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);r=(await Lr(Ca,{cwd:e,hasPythonSource:!0},`fix`)).tasks.filter(e=>e.toolId===`ruff`)}let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}}async function ka(e,t){if(process.env.JS_SETUP_OUTCOME===`failure`||process.env.NODE_SETUP_OUTCOME===`failure`||process.env.BUN_SETUP_OUTCOME===`failure`||process.env.PNPM_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`JavaScript runtime or package manager setup failed.`);try{if(t){let n=fn(e);if(!n.hasPackageJson)return en(`No package.json found. Skipping scripts.`),null;if(n.packageJsonError)throw Error(n.packageJsonError);if(t.length===0)return en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`),null;await wa(vn(cn(process.env.PACKAGE_MANAGER||_n(n).name)),e);let r=(await new Ar().executeTasks(t)).filter(e=>e.error);if(r.length>0){let e=r.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}return null}return await Ta(e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Aa(e,t){if(process.env.PYTHON_SETUP_OUTCOME===`failure`||process.env.UV_SETUP_OUTCOME===`failure`||process.env.PY_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Python runtime or package manager setup failed.`);let n=t&&`pmInfo`in t?t.pmInfo:Tr(e,void 0,{ctx:t?.ctx,hasSource:t?.hasSource});if(!n)return null;try{return await Da(n,e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function ja(e,t,n){if(process.env.RUFF_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Ruff setup failed.`);try{return await Oa(e,t,n),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Ma(e,t,n){let r=t??or(e);if(!r)return[];let i=[],a=ir(e),o=await Aa(e,{ctx:a,hasSource:!0,pmInfo:Tr(e,void 0,{ctx:a,hasSource:!0,isProject:!0})});o&&i.push(o);let s=await ja(e,r,n);return s&&i.push(s),i}async function Na(e=process.cwd()){let t=or(e),n;try{let r=fn(e),i={cwd:e,jsEnv:r,jsPm:cn(process.env.PACKAGE_MANAGER||_n(r).name),hasPythonSource:t};n=await Lr(Ca,i,`fix`),en(n.summary)}catch{}let r=[],i=n?n.tasks.filter(e=>e.toolId!==`ruff`):void 0,a=n?n.tasks.filter(e=>e.toolId===`ruff`):void 0,o=await ka(e,i);o&&r.push(o);let s=await Ma(e,t,a);r.push(...s),r.length>0&&(Zt(`Failed to run scripts: ${r.map(e=>e.message).join(` +`)}`),process.env.NODE_ENV!==`test`&&process.exit(1))}process.env.NODE_ENV!==`test`&&Or(import.meta.url)&&Na();export{Ta as executeJsWorkflow,Da as executePythonWorkflow,Oa as executeRuffAutofix,Na as run,cn as sanitizePackageManager}; \ No newline at end of file diff --git a/src/autofix/adapters/javascript/script-adapter.ts b/src/autofix/adapters/javascript/script-adapter.ts index 1f1cc6c0..8bb35fef 100644 --- a/src/autofix/adapters/javascript/script-adapter.ts +++ b/src/autofix/adapters/javascript/script-adapter.ts @@ -749,13 +749,11 @@ export function extractShellWrapperScript(tokens: string[]): string | undefined return undefined; } -const CROSS_ENV_OPTIONS_WITH_ARGS = new Set(["-f", "--file", "-c", "--config", "--env-file"]); -const CROSS_ENV_BOOLEAN_OPTIONS = new Set(["-h", "--help", "-v", "--version", "--shell"]); - /** * Unwraps environment wrapper commands like `cross-env` or `cross-env-shell`, - * correctly parsing options (both flags and options with arguments) and subsequent - * environment variable assignments to retrieve the target command tokens. + * stripping initial environment variable assignments to retrieve the target command tokens. + * In accordance with cross-env CLI syntax, cross-env accepts environment variable + * setters (`KEY=val`) followed by the command and its arguments. */ export function unwrapEnvironmentWrapper(tokens: string[]): string[] { if (tokens.length === 0) return tokens; @@ -765,54 +763,8 @@ export function unwrapEnvironmentWrapper(tokens: string[]): string[] { } let i = 1; - while (i < tokens.length) { - const token = tokens[i]; - - // Explicit end-of-options delimiter - if (token === "--") { - i++; - break; - } - - // Option with inline value (e.g. --file=.env, --config=conf.json) - if ( - token.startsWith("--file=") || - token.startsWith("--config=") || - token.startsWith("--env-file=") - ) { - i++; - continue; - } - - // Option with separate argument - if (CROSS_ENV_OPTIONS_WITH_ARGS.has(token)) { - if (i + 1 >= tokens.length) { - // Missing argument for option, fail closed / conservative - return []; - } - i += 2; - continue; - } - - // Boolean flag option - if (CROSS_ENV_BOOLEAN_OPTIONS.has(token)) { - i++; - continue; - } - - // Unrecognized option starting with '-' - if (token.startsWith("-")) { - // Conservative fail-closed: do not guess if it takes an argument - return []; - } - - // Environment variable assignment (e.g. NODE_ENV=production) - if (isEnvAssignment(token)) { - i++; - continue; - } - - break; + while (i < tokens.length && isEnvAssignment(tokens[i])) { + i++; } return tokens.slice(i); diff --git a/tests/autofix-architecture.test.ts b/tests/autofix-architecture.test.ts index 713e60f1..4c77532d 100644 --- a/tests/autofix-architecture.test.ts +++ b/tests/autofix-architecture.test.ts @@ -1733,35 +1733,69 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { const planCrossEnvShell = await planExecution(registry, { cwd: tempDir }, "fix"); expect(planCrossEnvShell.selectedTools.map((t) => t.id)).toContain("vite-plus"); - // 3. cross-env with options that consume arguments (-f, --file, -c, --config) + // 3. cross-env with multiple environment variable assignments fs.writeFileSync( path.join(tempDir, "package.json"), JSON.stringify({ scripts: { - formatArgShort: "cross-env -f .env vp fmt", - formatArgLong: "cross-env --file .env vp fmt", - formatInline: "cross-env --file=.env vp fmt", - formatConfig: "cross-env -c config.json vp fmt", - formatMultipleEnv: "cross-env NODE_ENV=production CI=true vp lint", - formatDelimiter: "cross-env -- NODE_ENV=production vp fmt", + formatMultipleEnv: "cross-env CI=true NODE_ENV=production vp lint", }, }), ); - const planCrossEnvOptions = await planExecution(registry, { cwd: tempDir }, "fix"); - expect(planCrossEnvOptions.selectedTools.map((t) => t.id)).toContain("vite-plus"); + const planCrossEnvMultiple = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planCrossEnvMultiple.selectedTools.map((t) => t.id)).toContain("vite-plus"); - // 4. unrecognized cross-env option fails closed and does not trigger false positive + // 4. cross-env delegating to a script that invokes vp fs.writeFileSync( path.join(tempDir, "package.json"), JSON.stringify({ scripts: { - formatBad: "cross-env -unknown-flag vp fmt", + formatDelegated: "cross-env NODE_ENV=production npm run format:vp", + "format:vp": "vp fmt", + }, + }), + ); + const planCrossEnvDelegated = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planCrossEnvDelegated.selectedTools.map((t) => t.id)).toContain("vite-plus"); + + // 5. unsupported options or flags must not be treated as valid and must not cause false-positive Vite+ detection + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + formatShort: "cross-env -f .env vp fmt", + formatLong: "cross-env --file .env vp fmt", + formatUnknown: "cross-env -unknown-flag vp fmt", }, }), ); const planCrossEnvUnknown = await planExecution(registry, { cwd: tempDir }, "fix"); expect(planCrossEnvUnknown.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + // 6. cross-env with missing command after environment assignments + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + noCommand: "cross-env NODE_ENV=production", + }, + }), + ); + const planCrossEnvNoCommand = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planCrossEnvNoCommand.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + + // 7. cross-env running an unrelated command with vp in arguments must not trigger Vite+ detection + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + grepTest: "cross-env NODE_ENV=production grep vp file.txt", + }, + }), + ); + const planCrossEnvGrep = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planCrossEnvGrep.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + // 5. sh -c fs.writeFileSync( path.join(tempDir, "package.json"), From 7a802a33358b7654980416758d9c56f7c0c7fa24 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 10 Nov 2026 09:12:55 +0000 Subject: [PATCH 5/5] fix(autofix): reject invalid shell syntax during vite-plus detection - Expose syntax error diagnostics via parseCommandInvocationsDetailed. - Make hasVitePlusCommand reject commands containing confirmed shell syntax errors (unterminated quotes, trailing escapes). - Synchronize dist/autofix.mjs bundle. - Add regression tests covering malformed commands and wrappers. --- dist/autofix.mjs | 12 +-- .../adapters/javascript/script-adapter.ts | 41 +++++++--- tests/autofix-architecture.test.ts | 77 +++++++++++++++++++ 3 files changed, 114 insertions(+), 16 deletions(-) diff --git a/dist/autofix.mjs b/dist/autofix.mjs index c6aed594..8418d70a 100644 --- a/dist/autofix.mjs +++ b/dist/autofix.mjs @@ -304,10 +304,10 @@ const Vn=[`uv`,`pip`],Hn=[`.git`,`.venv`,`venv`,`env`,`.env`,`virtualenv`,`.virt `:` `,i++;return i=t+1&&e[a]===`\\`;)n++,a--;if(n%2==0)return r+=` `,[r,i+1]}r+=` `,i++}return[r,i]}function dr(e,t,n){let r=` `,i=t+1;for(;i!Un(e))}function mr(e,t){if(!Un(e[`build-system`]))return!1;if(typeof t==`string`){let e=fr(t);return/(?:^|\n)\s*\[\s*build-system\s*\]\s*(?:\n|$)/.test(e)}let n=Object.entries(e[`build-system`]);return n.length===0||n.some(([,e])=>!Un(e))}function hr(e,t){if(pr(e,t)||mr(e,t))return!0;if(Un(e.tool)&&Un(e.tool.uv)){let t=e.tool.uv;return Yn(t.workspace)||Array.isArray(t[`dev-dependencies`])}return!1}function gr(e){return Un(e.tool)&&Un(e.tool.uv)}function _r(e,t){return pr(e,t)||mr(e,t)}function vr(e,t){return p.relative(e,t)||`.`}function yr(e,t){if(!t)throw Error(`Invalid Python project configuration: 'uv.lock' was detected without a valid 'pyproject.toml' project or workspace configuration ('[project]', '[build-system]', or '[tool.uv.workspace]'). 'uv sync' requires a valid 'pyproject.toml' file.`);return{name:`uv`,lockfile:`uv.lock`,configFile:`pyproject.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}}function br(e,t){if(e.hasRequirementsTxt&&e.requirementsDir){let t=vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`));return{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`pip`,`install`,`-r`,t]}],execPrefix:`uv run`}}return t?{name:`uv`,configFile:e.pyprojectDir?`pyproject.toml`:`uv.toml`,installCommands:[{executable:`uv`,args:[`sync`]}],lockCommand:`uv lock`,syncCommand:`uv sync`,execPrefix:`uv run`}:null}function xr(e){let t=e.pyprojectToml?.success===!0&&hr(e.pyprojectToml.data,e.pyprojectToml.rawContent),n=e.workspaceRootToml?.success===!0&&hr(e.workspaceRootToml.data,e.workspaceRootToml.rawContent),r=t||n,i=e.uvToml?.success===!0,a=e.pyprojectToml?.success===!0&&gr(e.pyprojectToml.data)||e.workspaceRootToml?.success===!0&&gr(e.workspaceRootToml.data);return e.hasUvLock?yr(e,r):a||i?br(e,r):null}function Sr(e){let t=e.pyprojectToml?.success===!0&&_r(e.pyprojectToml.data,e.pyprojectToml.rawContent);if(!(e.hasRequirementsTxt||e.hasSetupPy||e.hasSetupCfg||t))return null;let n;t?n=`pyproject.toml`:e.hasSetupPy?n=`setup.py`:e.hasSetupCfg&&(n=`setup.cfg`);let r=[],i,a=e.hasSetupPy||e.hasSetupCfg||t,o=e.requirementsDir?vr(e.cwd,p.join(e.requirementsDir,`requirements.txt`)):`requirements.txt`,s=vr(e.cwd,e.projectDir);return e.hasRequirementsTxt&&a?(r=[{executable:`pip`,args:[`install`,`-r`,o]},{executable:`pip`,args:[`install`,`-e`,s]}],i=`requirements.txt`):e.hasRequirementsTxt?(r=[{executable:`pip`,args:[`install`,`-r`,o]}],i=`requirements.txt`):a&&(r=[{executable:`pip`,args:[`install`,`-e`,s]}]),{name:`pip`,lockfile:i,configFile:n,installCommands:r,execPrefix:``}}function Cr(e=process.cwd(),t){if(t?.hasSource??or(e))return!0;let n=t?.ctx??ir(e);if(n.projectDir===n.cwd&&tr(n.cwd)&&(n.pyprojectToml?.success===!0&&hr(n.pyprojectToml.data,n.pyprojectToml.rawContent)||n.hasUvLock||n.hasRequirementsTxt||n.hasSetupPy||n.hasSetupCfg))return!0;if(n.workspaceRootDir&&n.workspaceRootToml?.success===!0){let t=Zn(n.workspaceRootDir);if(t&&Xn(n.workspaceRootDir,p.resolve(e),t.config))return!0}return!1}function wr(e,t){t!=null&&(e.pyprojectToml=t);for(let t of Vn)if(t===`uv`){let t=xr(e);if(t)return t}else if(t===`pip`){let t=Sr(e);if(t)return t}return{name:`pip`,installCommands:[],execPrefix:``,isStandalone:!0}}function Tr(e=process.cwd(),t,n){let r=n?.ctx??ir(e);return n?.isProject??Cr(e,{ctx:r,hasSource:n?.hasSource})?wr(r,t):null}function Er(e){if(!Array.isArray(e))throw Error(`Invalid Python environment: "pmInfo.installCommands" must be an array`);for(let t of e){if(!t||typeof t!=`object`)throw Error(`Invalid Python environment: malformed "installCommands" item`);let e=t;if(typeof e.executable!=`string`||!e.executable.trim()||!Array.isArray(e.args)||!e.args.every(e=>typeof e==`string`))throw Error(`Invalid Python environment: malformed "installCommands" item`)}}function Dr(e,t=`Invalid Python environment: "pmInfo" must be an object`){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(t);let n=e;if(n.name!==`uv`&&n.name!==`pip`)throw Error(`Invalid Python environment: pmInfo name must be "uv" or "pip"`);return Er(n.installCommands),n}function Or(e){if(!process.argv[1])return!1;try{return l(e)===f.realpathSync(process.argv[1])}catch{return!1}}async function kr(e,t,n=process.platform){let r=p.join(e,`node_modules`,`.bin`),i=/* @__PURE__ */ new Set([`.cmd`,`.bat`,`.exe`]);if(n===`win32`){let e=p.extname(t).toLowerCase();if(e){if(!i.has(e))return;let n=p.join(r,t);if(f.existsSync(n))return n}else for(let e of[`.cmd`,`.bat`,`.exe`,``]){let n=p.join(r,`${t}${e}`);if(f.existsSync(n))return n}}else{let e=p.join(r,t);if(f.existsSync(e))return e}let a=await Vt(t,!1);if(a){if(n===`win32`){let e=p.extname(a).toLowerCase();if(e&&!i.has(e))return}return a}}var Ar=class{platform;constructor(e=process.platform){this.platform=e}async resolveTaskExecutable(e){if(e.toolId===`npm-scripts`)return e.executable;if(e.toolId===`ruff`){if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);return`ruff`}let t=await kr(e.cwd,e.executable,this.platform);if(!t){let t=e.toolName||e.toolId,n=e.requiredPackage||e.executable;throw Error(`Configured tool "${t}" could not run: executable "${e.executable}" is not available in node_modules/.bin or PATH. Please install "${n}" in project dependencies.`)}return t}async executeTasks(e){let t=[];for(let n of e){let e=`${n.executable} ${n.args.join(` `)}`.trim();try{let r=await this.resolveTaskExecutable(n);en(`Executing: ${e}`);let i=n.env?Object.fromEntries(Object.entries({...process.env,...n.env}).filter(e=>e[1]!==void 0)):void 0,a=await Yt(r,n.args,{cwd:n.cwd,env:i,ignoreReturnCode:!0});if(a!==0){let r=n.toolId===`ruff`?`Ruff command "${e}" failed. Check Python and Ruff configuration.`:n.toolId===`npm-scripts`?`Script "${n.args[1]||e}" failed while executing "${e}".`:`Task "${n.id}" (${e}) failed with exit code ${a}.`;t.push({task:n,exitCode:a,error:Error(r)})}else t.push({task:n,exitCode:a})}catch(e){let r=e instanceof Error?e:Error(String(e));t.push({task:n,exitCode:1,error:r})}}return t}};function jr(e,t){return t.has(`autofix`)?!0:e===`autofix`?t.has(`format`)&&t.has(`lint`)&&t.has(`assist`):t.has(e)}function Mr(e,t){let n=[],r=[];for(let i of e)jr(i.capability,t)?r.push(i):n.push(i);return{kept:n,skipped:r}}function Nr(e,t){let n=e.get(t);return n||(n=/* @__PURE__ */ new Set,e.set(t,n)),n}async function Pr(e,t,n,r,i,a,o){for(let s of e){let e=s.adapter,c=Nr(t,s.scope),l=await e.plan(n,r);if(l.length===0)continue;let{kept:u,skipped:d}=Mr(l,c);if(u.length===0)a.push({id:e.id,name:e.name,reason:`all capabilities already covered by higher priority tool`});else{i.push({id:e.id,name:e.name,reason:s.reason});for(let e of u)if(c.add(e.capability),e.capabilities)for(let t of e.capabilities)c.add(t);if(o.push(...u),d.length>0){let t=Array.from(new Set(d.map(e=>e.capability))).join(`, `);a.push({id:e.id,name:e.name,reason:`partially skipped (${t} covered by higher priority tool)`})}}}}async function Fr(e,t,n,r,i,a,o){let s=[];for(let t of e.getStandaloneAdapters()){let e=await t.detect(n),r=t.scope??`standalone:${t.id}`;e.detected?s.push({adapter:t,reason:e.reason,scope:r}):e.reason&&!e.reason.startsWith(`no `)&&a.push({id:t.id,name:t.name,reason:e.reason})}await Pr(s,t,n,r,i,a,o)}function Ir(e){let t=[],n=/* @__PURE__ */ new Set;for(let r of e)n.has(r.id)||(n.add(r.id),t.push(r));return t}async function Lr(e,t,n=`fix`){let r=t.hasPythonSource??or(t.cwd),i=t.jsEnv??fn(t.cwd),a={...t,jsEnv:i,hasPythonSource:r},o=[],s=[],c=[],l=e.getProviders(),u=/* @__PURE__ */ new Map;for(let e of l){if(!await e.detect(a))continue;let t=e.getAdapters(a),r=[];for(let n of t){let t=await n.detect(a),i=n.scope??e.id;t.detected?r.push({adapter:n,reason:t.reason,scope:i}):t.reason&&!t.reason.startsWith(`no `)&&s.push({id:n.id,name:n.name,reason:t.reason})}await Pr(r,u,a,n,o,s,c)}await Fr(e,u,a,n,o,s,c);let d=Ir(c);return{tasks:d,selectedTools:o,skippedTools:s,summary:Rr(e,a,o,s,d)}}function Rr(e,t,n,r,i){let a=[];a.push(`Detected environments:`);let o=t.hasPythonSource??!1,s=t.jsEnv?.hasPackageJson??!1;if(a.push(` Python: ${o}`),a.push(` JavaScript: ${s}`),o&&(a.push(``),a.push(`Python toolchain:`),n.filter(e=>e.id===`ruff`).length>0?a.push(` Ruff: default tool`):a.push(` None`)),s){a.push(``),a.push(`JavaScript toolchain:`);let e=n.filter(e=>e.id!==`ruff`);for(let t of e)a.push(` ${t.name}: selected`);let t=r.filter(e=>e.id!==`ruff`);for(let e of t)a.push(` ${e.name}: skipped (${e.reason})`)}if(a.push(``),a.push(`Execution plan:`),i.length===0?a.push(` (no tasks to execute)`):i.forEach((e,t)=>{let n=e.description||`${e.executable} ${e.args.join(` `)}`;a.push(` ${t+1}. ${n}`)}),r.length>0){a.push(``),a.push(`Skipped:`);for(let e of r)a.push(` - ${e.name}: ${e.reason}`)}return a.join(` -`)}function zr(e){for(let t of[`format:write`,`format:fix`,`format`,`fmt`])if(e[t]&&Xi(e[t],e))return t}function Br(e){if(e[`format:check`]&&Yi(e[`format:check`],e)===`read-only`)return`format:check`;if(e[`fmt:check`]&&Yi(e[`fmt:check`],e)===`read-only`)return`fmt:check`}function Vr(e,t){return t===`fix`?zr(e):Br(e)}function Hr(e,t){if(t===`fix`)return e[`lint:fix`]?`lint:fix`:e[`lint:write`]?`lint:write`:void 0;if(e[`lint:check`]&&Yi(e[`lint:check`],e)===`read-only`)return`lint:check`;if(e.lint&&Yi(e.lint,e)===`read-only`)return`lint`}function Ur(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped)return 0;let r=e[t];return r===`;`||r===` +`)}function zr(e){for(let t of[`format:write`,`format:fix`,`format`,`fmt`])if(e[t]&&Yi(e[t],e))return t}function Br(e){if(e[`format:check`]&&Ji(e[`format:check`],e)===`read-only`)return`format:check`;if(e[`fmt:check`]&&Ji(e[`fmt:check`],e)===`read-only`)return`fmt:check`}function Vr(e,t){return t===`fix`?zr(e):Br(e)}function Hr(e,t){if(t===`fix`)return e[`lint:fix`]?`lint:fix`:e[`lint:write`]?`lint:write`:void 0;if(e[`lint:check`]&&Ji(e[`lint:check`],e)===`read-only`)return`lint:check`;if(e.lint&&Ji(e.lint,e)===`read-only`)return`lint`}function Ur(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped)return 0;let r=e[t];return r===`;`||r===` `?1:r===`&`&&e[t+1]===`&`||r===`|`&&e[t+1]===`|`?2:+(r===`|`)}function Wr(e,t){let n=t;for(;nt?n-1:t}function Gr(e,t){return t.inSingleQuote||t.inDoubleQuote||t.isEscaped?!1:e.length===0||/\s/.test(e[e.length-1])}function Kr(e,t){return t.isEscaped=!1,{ch:e,advance:!0}}function qr(e,t,n,r){let i=e[t];if(n.isEscaped)return{newCmd:r+Kr(i,n).ch,nextIndex:t,sepLen:0};if(i===`\\`&&!n.inSingleQuote)return n.isEscaped=!0,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`'`&&!n.inDoubleQuote)return n.inSingleQuote=!n.inSingleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`"`&&!n.inSingleQuote)return n.inDoubleQuote=!n.inDoubleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`#`&&Gr(r,n))return{newCmd:r,nextIndex:Wr(e,t),sepLen:0};let a=Ur(e,t,n);return{newCmd:r+(a===0?i:``),nextIndex:t,sepLen:a}}function Jr(e){let t=[],n=``,r={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1,hasSyntaxError:!1};for(let i=0;i0?(n.trim()&&t.push(n.trim()),n=``,i+=a.sepLen-1):(n=a.newCmd,i=a.nextIndex)}return(r.inSingleQuote||r.inDoubleQuote||r.isEscaped)&&(r.hasSyntaxError=!0),n.trim()&&t.push(n.trim()),{commands:t,hasSyntaxError:r.hasSyntaxError}}function Yr(e){return Jr(e).commands}function Xr(e,t,n){return t.isEscaped=!1,n+e}function Zr(e,t){return e===`'`&&!t.inDoubleQuote?(t.inSingleQuote=!t.inSingleQuote,!0):e===`"`&&!t.inSingleQuote&&(t.inDoubleQuote=!t.inDoubleQuote,!0)}const Qr=/* @__PURE__ */ new Set([`@`,`*`,`#`,`?`,`-`,`$`,`!`,`0`]);function $r(e,t,n){if(n.inSingleQuote||n.isEscaped||e[t]!==`$`||t+1>=e.length)return!1;let r=e[t+1];return!!(r===`{`||Qr.has(r)||r>=`1`&&r<=`9`||r===`_`||r>=`a`&&r<=`z`||r>=`A`&&r<=`Z`)}function ei(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped||e[t]!==`&`)return!1;let r=t>0?e[t-1]:``,i=t+1`}function ti(e,t,n){if(n.inSingleQuote||n.isEscaped)return!1;let r=e[t];return r==="`"||r===`$`&&t+1`)&&t+1`||r===`<`||r===`&`&&t+1`}function ii(e,t,n){return ei(e,t,n.state)||$r(e,t,n.state)||ti(e,t,n.state)||ni(e,t,n.state)?(n.inspection.hasUnsupportedSyntax=!0,!0):ri(e,t,n.state)?(n.inspection.hasRedirection=!0,n.inspection.hasUnsupportedSyntax=!0,!0):!1}function ai(e,t,n,r){let i=e[t];return n.state.isEscaped?{word:Xr(i,n.state,r),hasChars:!0,skipped:!1}:i===`\\`&&!n.state.inSingleQuote?(n.state.isEscaped=!0,{word:r,hasChars:!1,skipped:!0}):(ii(e,t,n),Zr(i,n.state)?{word:r,hasChars:!0,skipped:!0}:{word:r+i,hasChars:!0,skipped:!1})}function oi(e){let t={tokens:[],hasUnsupportedSyntax:!1,hasRedirection:!1},n={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1},r={inspection:t,state:n},i=``,a=!1;for(let o=0;o0&&n.push(t)}return n}function pi(e,t,n={},r=/* @__PURE__ */ new Set){if(!e||!t)return!1;let i=fi(n[e]===void 0?e:n[e]);for(let e of i){if(di(e,t))return!0;let i=Vi(e);if(i){if(i===t)return!0;if(!r.has(i)&&n[i]!==void 0){r.add(i);try{if(pi(n[i],t,n,r))return!0}finally{r.delete(i)}}}let a=Hi(e);if(a!==void 0&&pi(a,t,n,r))return!0}return!1}function mi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function hi(e,t,n){return!n||n===t?!1:!pi(e[t]||``,n,e)}function gi(e){let[t]=e;return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||(e===`--fix`||e.startsWith(`--fix=`))&&(t!==`eslint`||e!==`--fix-dry-run`))}function _i(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function vi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function yi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function bi(e){let[t]=e;return t===`eslint`&&e.some(e=>(e===`--fix`||e.startsWith(`--fix=`))&&e!==`--fix-dry-run`)}function xi(e){let[t]=e;return t===`oxlint`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Si(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Ci(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function wi(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:!e.some(e=>e===`--check`||e===`-c`)}function Ti(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Ei(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)&&e!==`--fix-dry-run`||e===`-o`||e.startsWith(`-o=`)||e===`--output-file`||e.startsWith(`--output-file=`)||e===`--cache`||e===`--cache-file`||e.startsWith(`--cache-file=`)||e===`--cache-location`||e.startsWith(`--cache-location=`))}function Di(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--cache`||e===`--cache-location`||e.startsWith(`--cache-location=`)||e===`--insert-pragma`)}function Oi(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`)||e===`--reporter-file`||e.startsWith(`--reporter-file=`)||e===`--log-file`||e.startsWith(`--log-file=`))}function ki(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)||e===`--fix-suggestions`||e===`--fix-dangerously`||e===`--init`)}function Ai(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--init`||e===`--migrate`||e.startsWith(`--migrate=`))}function ji(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`--check`||e===`-c`||e===`--list-different`||e===`-l`)&&!Di(e)}function Mi(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function Ni(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:!Oi(e)}function Pi(e){let[t]=e;return t===`eslint`&&!Ei(e)}function Fi(e){let[t]=e;return t===`oxlint`&&!ki(e)}function Ii(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:!Oi(e)}function Li(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:!Oi(e)}function Ri(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:e.some(e=>e===`--check`||e===`-c`)&&!Ai(e)}function zi(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:!ki(e)}function Bi(e){let[t,n]=e;return t!==`vp`||n!==`check`?!1:!e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Vi(e){if(e.length===0)return;let[t,n,r]=e;if((t===`npm`||t===`pnpm`||t===`yarn`||t===`bun`)&&n===`run`&&r)return r;if((t===`pnpm`||t===`bun`||t===`yarn`)&&n&&!n.startsWith(`-`))return n}function Hi(e){if(e.length>=3&&(e[0]===`sh`||e[0]===`bash`)&&e[1]===`-c`)return e[2]}function Ui(e){if(e.length===0)return e;let[t]=e;if(t!==`cross-env`&&t!==`cross-env-shell`)return e;let n=1;for(;n{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Xi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?_i(e)||vi(e)||yi(e)||wi(e):Xi(i,t,n)})}function Zi(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Zi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);return i===void 0?bi(e)||xi(e)||Si(e)||Ti(e):Zi(i,t,n)})}function Qi(e,t={},n=/* @__PURE__ */ new Set){return fi(e).some(e=>{let r=Vi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Qi(e,t,n)}finally{n.delete(r)}}let i=Hi(e);if(i!==void 0)return Qi(i,t,n);if(Ci(e))return!0;let[a,o]=e;return a===`vp`&&o===`check`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))})}function $i(e,t,n,r){return t&&pi(e,t,n)?!0:r(e)}function ea(e,t,n,r,i){let a=$i(t,r,e,t=>Xi(t,e)),o=$i(t,i,e,t=>Zi(t,e)),s=Qi(t,e);return a&&o?[{capability:`format`,capabilities:[`format`,`lint`],scriptName:n}]:a&&!s?[{capability:`format`,scriptName:n}]:o&&!s?[{capability:`lint`,scriptName:n}]:s?[{capability:`autofix`,scriptName:n}]:[{capability:`typecheck`,capabilities:[],scriptName:n}]}function ta(e,t){return Xi(t[e],t)?{capability:`format`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function na(e,t){return Zi(t[e],t)?{capability:`lint`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function ra(e,t,n){let r=[];return e&&r.push(ta(e,n)),t&&r.push(na(t,n)),r}function ia(e,t,n,r,i){r&&mi(t,n,r)&&e.push(ta(r,t)),i&&hi(t,n,i)&&e.push(na(i,t))}function aa(e){let t=e.fix?`fix`:e[`check:fix`]?`check:fix`:void 0,n=Vr(e,`fix`),r=Hr(e,`fix`);if(!t)return ra(n,r,e);let i=ea(e,e[t]||``,t,n,r);return ia(i,e,t,n,r),i}function oa(e){let t=[],n=Vr(e,`check`),r=Hr(e,`check`);return n&&t.push({capability:`format`,scriptName:n}),r&&t.push({capability:`lint`,scriptName:r}),t}function sa(e,t){return t===`fix`?aa(e):oa(e)}var ca=class{id=`npm-scripts`;name=`package.json scripts`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson?.scripts;if(!t||Object.keys(t).length===0)return{detected:!1,reason:`no scripts declared in package.json`};let n=sa(t,`fix`),r=sa(t,`check`),i=[...n,...r];return i.length>0?{detected:!0,reason:`found supported scripts: ${Array.from(new Set(i.map(e=>`"${e.scriptName}"`))).join(`, `)}`}:{detected:!1,reason:`no supported autofix or check scripts found in package.json`}}plan(e,t){let n=sa(e.jsEnv?.packageJson?.scripts||{},t),r=cn(e.jsPm||`npm`);return n.map(n=>({id:`script-${n.scriptName}`,toolId:this.id,capability:n.capability,capabilities:n.capabilities,executable:r,args:[`run`,n.scriptName],cwd:e.cwd,mode:t,description:`package.json script: ${r} run ${n.scriptName}`}))}};function la(e){return e?Object.values(e).some(t=>Wi(t,e)):!1}function ua(e,t){return e?!!(e.dependencies?.[t]||e.devDependencies?.[t]||e.peerDependencies?.[t]||e.optionalDependencies?.[t]):!1}function da(e,t){for(let n of t)if(f.existsSync(p.join(e,n)))return!0;return!1}var fa=class{id=`vite-plus`;name=`Vite+`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sn(t),r=da(e.cwd,[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.cjs`]);return n||r&&la(t?.scripts)?{detected:!0,reason:`Vite+ dependency and/or configuration detected`}:{detected:!1,reason:`no Vite+ dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`vite-plus-fmt`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp fmt`},{id:`vite-plus-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`,`--fix`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp lint --fix`}]:[{id:`vite-plus-fmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`,`--check`],cwd:e.cwd,mode:`check`,description:`Vite+: vp fmt --check`},{id:`vite-plus-lint`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`],cwd:e.cwd,mode:`check`,description:`Vite+: vp lint`}]}},pa=class{id=`biome`;name=`Biome`;capabilities=[`format`,`lint`,`assist`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`@biomejs/biome`),r=da(e.cwd,[`biome.json`,`biome.jsonc`]);return n&&r?{detected:!0,reason:`Biome dependency and configuration detected`}:r?{detected:!0,reason:`Biome configuration detected`}:n?{detected:!1,reason:`Biome dependency present without configuration file`}:{detected:!1,reason:`no Biome dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`biome-format-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: format --write .`},{id:`biome-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: lint --write .`},{id:`biome-assist-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--write`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: safe assist actions (--write)`}]:[{id:`biome-format-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: format .`},{id:`biome-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: lint .`},{id:`biome-assist-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: check assist actions`}]}},ma=class{id=`prettier`;name=`Prettier`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`prettier`),r=!!t?.prettier,i=da(e.cwd,[`.prettierrc`,`.prettierrc.json`,`.prettierrc.yml`,`.prettierrc.yaml`,`.prettierrc.json5`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`]);return n&&(r||i)?{detected:!0,reason:`Prettier dependency and configuration detected`}:r||i?{detected:!0,reason:`Prettier configuration detected`}:n?{detected:!1,reason:`Prettier dependency present without configuration`}:{detected:!1,reason:`no Prettier dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`prettier-format`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Prettier: format`}]:[{id:`prettier-check`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Prettier: format check`}]}},ha=class{id=`eslint`;name=`ESLint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`eslint`),r=!!t?.eslintConfig,i=da(e.cwd,[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yaml`,`.eslintrc.yml`]);return n&&(r||i)?{detected:!0,reason:`ESLint dependency and configuration detected`}:r||i?{detected:!0,reason:`ESLint configuration detected`}:n?{detected:!1,reason:`ESLint dependency present without configuration`}:{detected:!1,reason:`no ESLint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`eslint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`ESLint: lint autofix`}]:[{id:`eslint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`ESLint: lint check`}]}},ga=class{id=`oxlint`;name=`Oxlint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`oxlint`),r=da(e.cwd,[`.oxlintrc.json`,`oxlint.json`,`oxlint.config.ts`,`oxlint.config.js`]);return n&&r?{detected:!0,reason:`Oxlint dependency and configuration detected`}:r?{detected:!0,reason:`Oxlint configuration detected`}:n?{detected:!1,reason:`Oxlint dependency present without configuration`}:{detected:!1,reason:`no Oxlint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxlint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxlint: lint autofix`}]:[{id:`oxlint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`Oxlint: lint check`}]}},_a=class{id=`oxfmt`;name=`Oxfmt`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=ua(t,`oxfmt`),r=da(e.cwd,[`.oxfmtrc.json`,`oxfmt.json`,`oxfmt.config.ts`,`oxfmt.config.js`]);return n&&r?{detected:!0,reason:`Oxfmt dependency and configuration detected`}:r?{detected:!0,reason:`Oxfmt configuration detected`}:n?{detected:!1,reason:`Oxfmt dependency present without configuration`}:{detected:!1,reason:`no Oxfmt dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxfmt-format`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxfmt: format`}]:[{id:`oxfmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Oxfmt: format check`}]}},va=class{id=`javascript`;name=`JavaScript/TypeScript`;scriptAdapter=new ca;vitePlusAdapter=new fa;biomeAdapter=new pa;prettierAdapter=new ma;eslintAdapter=new ha;oxlintAdapter=new ga;oxfmtAdapter=new _a;detect(e){return!!e.jsEnv?.hasPackageJson}getAdapters(e){return[this.scriptAdapter,this.vitePlusAdapter,this.biomeAdapter,this.oxfmtAdapter,this.prettierAdapter,this.oxlintAdapter,this.eslintAdapter]}},ya=class{id=`ruff`;name=`Ruff`;capabilities=[`lint`,`format`];detect(e){return e.hasPythonSource??or(e.cwd)?{detected:!0,reason:`default Python toolchain`}:{detected:!1,reason:`no Python source files detected`}}plan(e,t){let n=[];return t===`fix`?n.push({id:`ruff-lint-fix`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: lint autofix`},{id:`ruff-format`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: format`}):n.push({id:`ruff-lint-check`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: lint check`},{id:`ruff-format-check`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: format check`}),n}},ba=class{id=`python`;name=`Python`;ruffAdapter=new ya;detect(e){return e.hasPythonSource??or(e.cwd)}getAdapters(e){return[this.ruffAdapter]}},xa=class{providers=/* @__PURE__ */ new Map;standaloneAdapters=/* @__PURE__ */ new Map;registerProvider(e){this.providers.set(e.id,e)}getProvider(e){return this.providers.get(e)}getProviders(){return Array.from(this.providers.values())}registerAdapter(e){this.standaloneAdapters.set(e.id,e)}getAdapter(e){return this.standaloneAdapters.get(e)}getStandaloneAdapters(){return Array.from(this.standaloneAdapters.values())}clear(){this.providers.clear(),this.standaloneAdapters.clear()}};function Sa(){let e=new xa;return e.registerProvider(new ba),e.registerProvider(new va),e}const Ca=Sa();async function wa(e,t=process.cwd()){let n=`${e.command} ${e.args.join(` `)}`.trim();if(en(`Installing JS dependencies: ${n}`),await Yt(e.command,e.args,{cwd:t,ignoreReturnCode:!0})!==0)throw Error(`JS dependency installation failed executing "${n}". Check dependency constraints or lockfile compatibility.`)}async function Ta(e=process.cwd()){let t=fn(e);if(!t.hasPackageJson){en(`No package.json found. Skipping scripts.`);return}if(t.packageJsonError)throw Error(t.packageJsonError);let n=cn(process.env.PACKAGE_MANAGER||_n(t).name),r=(await Lr(Ca,{cwd:e,jsEnv:t,jsPm:n,hasPythonSource:!1},`fix`)).tasks.filter(e=>e.toolId!==`ruff`);if(r.length===0){en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`);return}await wa(vn(n),e);let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}}async function Ea(e,t,n=process.cwd()){let r=`${e} ${t.join(` `)}`.trim();if(en(`Executing: ${r}`),await Yt(e,t,{cwd:n,ignoreReturnCode:!0})!==0)throw Error(`Python command "${r}" failed. Check Python environment and dependency configuration.`)}async function Da(e,t=process.cwd()){Dr(e,`Invalid Python environment: "pmInfo" must be an object`);let n=e.name===`pip`?`pip`:e.name;if(!await Vt(n,!1)&&!e.isStandalone){let e=`Required Python package manager '${n}' is not available in PATH.`;throw Error(e)}if(!e.isStandalone&&e.installCommands.length>0){let n=e.installCommands;en(`Installing Python dependencies: ${n.map(e=>`${e.executable} ${e.args.join(` `)}`).join(` && `)}`);for(let{executable:e,args:r}of n)await Ea(e,r,t)}}async function Oa(e=process.cwd(),t,n){if(!(t??or(e)))return;let r;if(n)r=n;else{if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);r=(await Lr(Ca,{cwd:e,hasPythonSource:!0},`fix`)).tasks.filter(e=>e.toolId===`ruff`)}let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}}async function ka(e,t){if(process.env.JS_SETUP_OUTCOME===`failure`||process.env.NODE_SETUP_OUTCOME===`failure`||process.env.BUN_SETUP_OUTCOME===`failure`||process.env.PNPM_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`JavaScript runtime or package manager setup failed.`);try{if(t){let n=fn(e);if(!n.hasPackageJson)return en(`No package.json found. Skipping scripts.`),null;if(n.packageJsonError)throw Error(n.packageJsonError);if(t.length===0)return en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`),null;await wa(vn(cn(process.env.PACKAGE_MANAGER||_n(n).name)),e);let r=(await new Ar().executeTasks(t)).filter(e=>e.error);if(r.length>0){let e=r.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` -`))}return null}return await Ta(e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Aa(e,t){if(process.env.PYTHON_SETUP_OUTCOME===`failure`||process.env.UV_SETUP_OUTCOME===`failure`||process.env.PY_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Python runtime or package manager setup failed.`);let n=t&&`pmInfo`in t?t.pmInfo:Tr(e,void 0,{ctx:t?.ctx,hasSource:t?.hasSource});if(!n)return null;try{return await Da(n,e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function ja(e,t,n){if(process.env.RUFF_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Ruff setup failed.`);try{return await Oa(e,t,n),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Ma(e,t,n){let r=t??or(e);if(!r)return[];let i=[],a=ir(e),o=await Aa(e,{ctx:a,hasSource:!0,pmInfo:Tr(e,void 0,{ctx:a,hasSource:!0,isProject:!0})});o&&i.push(o);let s=await ja(e,r,n);return s&&i.push(s),i}async function Na(e=process.cwd()){let t=or(e),n;try{let r=fn(e),i={cwd:e,jsEnv:r,jsPm:cn(process.env.PACKAGE_MANAGER||_n(r).name),hasPythonSource:t};n=await Lr(Ca,i,`fix`),en(n.summary)}catch{}let r=[],i=n?n.tasks.filter(e=>e.toolId!==`ruff`):void 0,a=n?n.tasks.filter(e=>e.toolId===`ruff`):void 0,o=await ka(e,i);o&&r.push(o);let s=await Ma(e,t,a);r.push(...s),r.length>0&&(Zt(`Failed to run scripts: ${r.map(e=>e.message).join(` -`)}`),process.env.NODE_ENV!==`test`&&process.exit(1))}process.env.NODE_ENV!==`test`&&Or(import.meta.url)&&Na();export{Ta as executeJsWorkflow,Da as executePythonWorkflow,Oa as executeRuffAutofix,Na as run,cn as sanitizePackageManager}; \ No newline at end of file +`;)n++;return n>t?n-1:t}function Gr(e,t){return t.inSingleQuote||t.inDoubleQuote||t.isEscaped?!1:e.length===0||/\s/.test(e[e.length-1])}function Kr(e,t){return t.isEscaped=!1,{ch:e,advance:!0}}function qr(e,t,n,r){let i=e[t];if(n.isEscaped)return{newCmd:r+Kr(i,n).ch,nextIndex:t,sepLen:0};if(i===`\\`&&!n.inSingleQuote)return n.isEscaped=!0,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`'`&&!n.inDoubleQuote)return n.inSingleQuote=!n.inSingleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`"`&&!n.inSingleQuote)return n.inDoubleQuote=!n.inDoubleQuote,{newCmd:r+i,nextIndex:t,sepLen:0};if(i===`#`&&Gr(r,n))return{newCmd:r,nextIndex:Wr(e,t),sepLen:0};let a=Ur(e,t,n);return{newCmd:r+(a===0?i:``),nextIndex:t,sepLen:a}}function Jr(e){let t=[],n=``,r={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1,hasSyntaxError:!1};for(let i=0;i0?(n.trim()&&t.push(n.trim()),n=``,i+=a.sepLen-1):(n=a.newCmd,i=a.nextIndex)}return(r.inSingleQuote||r.inDoubleQuote||r.isEscaped)&&(r.hasSyntaxError=!0),n.trim()&&t.push(n.trim()),{commands:t,hasSyntaxError:r.hasSyntaxError}}function Yr(e,t,n){return t.isEscaped=!1,n+e}function Xr(e,t){return e===`'`&&!t.inDoubleQuote?(t.inSingleQuote=!t.inSingleQuote,!0):e===`"`&&!t.inSingleQuote&&(t.inDoubleQuote=!t.inDoubleQuote,!0)}const Zr=/* @__PURE__ */ new Set([`@`,`*`,`#`,`?`,`-`,`$`,`!`,`0`]);function Qr(e,t,n){if(n.inSingleQuote||n.isEscaped||e[t]!==`$`||t+1>=e.length)return!1;let r=e[t+1];return!!(r===`{`||Zr.has(r)||r>=`1`&&r<=`9`||r===`_`||r>=`a`&&r<=`z`||r>=`A`&&r<=`Z`)}function $r(e,t,n){if(n.inSingleQuote||n.inDoubleQuote||n.isEscaped||e[t]!==`&`)return!1;let r=t>0?e[t-1]:``,i=t+1`}function ei(e,t,n){if(n.inSingleQuote||n.isEscaped)return!1;let r=e[t];return r==="`"||r===`$`&&t+1`)&&t+1`||r===`<`||r===`&`&&t+1`}function ri(e,t,n){return $r(e,t,n.state)||Qr(e,t,n.state)||ei(e,t,n.state)||ti(e,t,n.state)?(n.inspection.hasUnsupportedSyntax=!0,!0):ni(e,t,n.state)?(n.inspection.hasRedirection=!0,n.inspection.hasUnsupportedSyntax=!0,!0):!1}function ii(e,t,n,r){let i=e[t];return n.state.isEscaped?{word:Yr(i,n.state,r),hasChars:!0,skipped:!1}:i===`\\`&&!n.state.inSingleQuote?(n.state.isEscaped=!0,{word:r,hasChars:!1,skipped:!0}):(ri(e,t,n),Xr(i,n.state)?{word:r,hasChars:!0,skipped:!0}:{word:r+i,hasChars:!0,skipped:!1})}function ai(e){let t={tokens:[],hasUnsupportedSyntax:!1,hasRedirection:!1,hasSyntaxError:!1},n={inSingleQuote:!1,inDoubleQuote:!1,isEscaped:!1},r={inspection:t,state:n},i=``,a=!1;for(let o=0;o0&&r.push(i)}return{invocations:r,hasSyntaxError:n}}function di(e){return ui(e).invocations}function fi(e,t,n={},r=/* @__PURE__ */ new Set){if(!e||!t)return!1;let i=di(n[e]===void 0?e:n[e]);for(let e of i){if(li(e,t))return!0;let i=Bi(e);if(i){if(i===t)return!0;if(!r.has(i)&&n[i]!==void 0){r.add(i);try{if(fi(n[i],t,n,r))return!0}finally{r.delete(i)}}}let a=Vi(e);if(a!==void 0&&fi(a,t,n,r))return!0}return!1}function pi(e,t,n){return!n||n===t?!1:!fi(e[t]||``,n,e)}function mi(e,t,n){return!n||n===t?!1:!fi(e[t]||``,n,e)}function hi(e){let[t]=e;return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||(e===`--fix`||e.startsWith(`--fix=`))&&(t!==`eslint`||e!==`--fix-dry-run`))}function gi(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function _i(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function vi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`))}function yi(e){let[t]=e;return t===`eslint`&&e.some(e=>(e===`--fix`||e.startsWith(`--fix=`))&&e!==`--fix-dry-run`)}function bi(e){let[t]=e;return t===`oxlint`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function xi(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Si(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`))}function Ci(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:!e.some(e=>e===`--check`||e===`-c`)}function wi(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Ti(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)&&e!==`--fix-dry-run`||e===`-o`||e.startsWith(`-o=`)||e===`--output-file`||e.startsWith(`--output-file=`)||e===`--cache`||e===`--cache-file`||e.startsWith(`--cache-file=`)||e===`--cache-location`||e.startsWith(`--cache-location=`))}function Ei(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--cache`||e===`--cache-location`||e.startsWith(`--cache-location=`)||e===`--insert-pragma`)}function Di(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--fix`||e.startsWith(`--fix=`)||e===`--reporter-file`||e.startsWith(`--reporter-file=`)||e===`--log-file`||e.startsWith(`--log-file=`))}function Oi(e){return e.some(e=>e===`--fix`||e.startsWith(`--fix=`)||e===`--fix-suggestions`||e===`--fix-dangerously`||e===`--init`)}function ki(e){return e.some(e=>e===`-w`||e===`--write`||e.startsWith(`--write=`)||e===`--init`||e===`--migrate`||e.startsWith(`--migrate=`))}function Ai(e){let[t]=e;return t===`prettier`&&e.some(e=>e===`--check`||e===`-c`||e===`--list-different`||e===`-l`)&&!Ei(e)}function ji(e){let[t]=e;return t===`oxfmt`&&e.some(e=>e===`--check`||e===`-c`)&&!ki(e)}function Mi(e){let[t,n]=e;return t!==`biome`||n!==`format`?!1:!Di(e)}function Ni(e){let[t]=e;return t===`eslint`&&!Ti(e)}function Pi(e){let[t]=e;return t===`oxlint`&&!Oi(e)}function Fi(e){let[t,n]=e;return t!==`biome`||n!==`lint`?!1:!Di(e)}function Ii(e){let[t,n]=e;return t!==`biome`||n!==`check`?!1:!Di(e)}function Li(e){let[t,n]=e;return t!==`vp`||n!==`fmt`?!1:e.some(e=>e===`--check`||e===`-c`)&&!ki(e)}function Ri(e){let[t,n]=e;return t!==`vp`||n!==`lint`?!1:!Oi(e)}function zi(e){let[t,n]=e;return t!==`vp`||n!==`check`?!1:!e.some(e=>e===`--fix`||e.startsWith(`--fix=`))}function Bi(e){if(e.length===0)return;let[t,n,r]=e;if((t===`npm`||t===`pnpm`||t===`yarn`||t===`bun`)&&n===`run`&&r)return r;if((t===`pnpm`||t===`bun`||t===`yarn`)&&n&&!n.startsWith(`-`))return n}function Vi(e){if(e.length>=3&&(e[0]===`sh`||e[0]===`bash`)&&e[1]===`-c`)return e[2]}function Hi(e){if(e.length===0)return e;let[t]=e;if(t!==`cross-env`&&t!==`cross-env-shell`)return e;let n=1;for(;n{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Yi(e,t,n)}finally{n.delete(r)}}let i=Vi(e);return i===void 0?gi(e)||_i(e)||vi(e)||Ci(e):Yi(i,t,n)})}function Xi(e,t={},n=/* @__PURE__ */ new Set){return di(e).some(e=>{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Xi(e,t,n)}finally{n.delete(r)}}let i=Vi(e);return i===void 0?yi(e)||bi(e)||xi(e)||wi(e):Xi(i,t,n)})}function Zi(e,t={},n=/* @__PURE__ */ new Set){return di(e).some(e=>{let r=Bi(e);if(r){if(n.has(r))return!1;let e=t[r];if(!e)return!1;n.add(r);try{return Zi(e,t,n)}finally{n.delete(r)}}let i=Vi(e);if(i!==void 0)return Zi(i,t,n);if(Si(e))return!0;let[a,o]=e;return a===`vp`&&o===`check`&&e.some(e=>e===`--fix`||e.startsWith(`--fix=`))})}function Qi(e,t,n,r){return t&&fi(e,t,n)?!0:r(e)}function $i(e,t,n,r,i){let a=Qi(t,r,e,t=>Yi(t,e)),o=Qi(t,i,e,t=>Xi(t,e)),s=Zi(t,e);return a&&o?[{capability:`format`,capabilities:[`format`,`lint`],scriptName:n}]:a&&!s?[{capability:`format`,scriptName:n}]:o&&!s?[{capability:`lint`,scriptName:n}]:s?[{capability:`autofix`,scriptName:n}]:[{capability:`typecheck`,capabilities:[],scriptName:n}]}function ea(e,t){return Yi(t[e],t)?{capability:`format`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function ta(e,t){return Xi(t[e],t)?{capability:`lint`,scriptName:e}:{capability:`typecheck`,capabilities:[],scriptName:e}}function na(e,t,n){let r=[];return e&&r.push(ea(e,n)),t&&r.push(ta(t,n)),r}function ra(e,t,n,r,i){r&&pi(t,n,r)&&e.push(ea(r,t)),i&&mi(t,n,i)&&e.push(ta(i,t))}function ia(e){let t=e.fix?`fix`:e[`check:fix`]?`check:fix`:void 0,n=Vr(e,`fix`),r=Hr(e,`fix`);if(!t)return na(n,r,e);let i=$i(e,e[t]||``,t,n,r);return ra(i,e,t,n,r),i}function aa(e){let t=[],n=Vr(e,`check`),r=Hr(e,`check`);return n&&t.push({capability:`format`,scriptName:n}),r&&t.push({capability:`lint`,scriptName:r}),t}function oa(e,t){return t===`fix`?ia(e):aa(e)}var sa=class{id=`npm-scripts`;name=`package.json scripts`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson?.scripts;if(!t||Object.keys(t).length===0)return{detected:!1,reason:`no scripts declared in package.json`};let n=oa(t,`fix`),r=oa(t,`check`),i=[...n,...r];return i.length>0?{detected:!0,reason:`found supported scripts: ${Array.from(new Set(i.map(e=>`"${e.scriptName}"`))).join(`, `)}`}:{detected:!1,reason:`no supported autofix or check scripts found in package.json`}}plan(e,t){let n=oa(e.jsEnv?.packageJson?.scripts||{},t),r=cn(e.jsPm||`npm`);return n.map(n=>({id:`script-${n.scriptName}`,toolId:this.id,capability:n.capability,capabilities:n.capabilities,executable:r,args:[`run`,n.scriptName],cwd:e.cwd,mode:t,description:`package.json script: ${r} run ${n.scriptName}`}))}};function ca(e){return e?Object.values(e).some(t=>Ui(t,e)):!1}function la(e,t){return e?!!(e.dependencies?.[t]||e.devDependencies?.[t]||e.peerDependencies?.[t]||e.optionalDependencies?.[t]):!1}function ua(e,t){for(let n of t)if(f.existsSync(p.join(e,n)))return!0;return!1}var da=class{id=`vite-plus`;name=`Vite+`;capabilities=[`autofix`,`format`,`lint`];detect(e){let t=e.jsEnv?.packageJson,n=sn(t),r=ua(e.cwd,[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.cjs`]);return n||r&&ca(t?.scripts)?{detected:!0,reason:`Vite+ dependency and/or configuration detected`}:{detected:!1,reason:`no Vite+ dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`vite-plus-fmt`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp fmt`},{id:`vite-plus-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`,`--fix`],cwd:e.cwd,mode:`fix`,description:`Vite+: vp lint --fix`}]:[{id:`vite-plus-fmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`format`,executable:`vp`,args:[`fmt`,`--check`],cwd:e.cwd,mode:`check`,description:`Vite+: vp fmt --check`},{id:`vite-plus-lint`,toolId:this.id,toolName:this.name,requiredPackage:`vite-plus`,capability:`lint`,executable:`vp`,args:[`lint`],cwd:e.cwd,mode:`check`,description:`Vite+: vp lint`}]}},fa=class{id=`biome`;name=`Biome`;capabilities=[`format`,`lint`,`assist`];detect(e){let t=e.jsEnv?.packageJson,n=la(t,`@biomejs/biome`),r=ua(e.cwd,[`biome.json`,`biome.jsonc`]);return n&&r?{detected:!0,reason:`Biome dependency and configuration detected`}:r?{detected:!0,reason:`Biome configuration detected`}:n?{detected:!1,reason:`Biome dependency present without configuration file`}:{detected:!1,reason:`no Biome dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`biome-format-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: format --write .`},{id:`biome-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: lint --write .`},{id:`biome-assist-fix`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--write`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`fix`,description:`Biome: safe assist actions (--write)`}]:[{id:`biome-format-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`format`,executable:`biome`,args:[`format`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: format .`},{id:`biome-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`lint`,executable:`biome`,args:[`lint`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: lint .`},{id:`biome-assist-check`,toolId:this.id,toolName:this.name,requiredPackage:`@biomejs/biome`,capability:`assist`,executable:`biome`,args:[`check`,`--formatter-enabled=false`,`--linter-enabled=false`,`.`],cwd:e.cwd,mode:`check`,description:`Biome: check assist actions`}]}},pa=class{id=`prettier`;name=`Prettier`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=la(t,`prettier`),r=!!t?.prettier,i=ua(e.cwd,[`.prettierrc`,`.prettierrc.json`,`.prettierrc.yml`,`.prettierrc.yaml`,`.prettierrc.json5`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`]);return n&&(r||i)?{detected:!0,reason:`Prettier dependency and configuration detected`}:r||i?{detected:!0,reason:`Prettier configuration detected`}:n?{detected:!1,reason:`Prettier dependency present without configuration`}:{detected:!1,reason:`no Prettier dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`prettier-format`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Prettier: format`}]:[{id:`prettier-check`,toolId:this.id,toolName:this.name,requiredPackage:`prettier`,capability:`format`,executable:`prettier`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Prettier: format check`}]}},ma=class{id=`eslint`;name=`ESLint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=la(t,`eslint`),r=!!t?.eslintConfig,i=ua(e.cwd,[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yaml`,`.eslintrc.yml`]);return n&&(r||i)?{detected:!0,reason:`ESLint dependency and configuration detected`}:r||i?{detected:!0,reason:`ESLint configuration detected`}:n?{detected:!1,reason:`ESLint dependency present without configuration`}:{detected:!1,reason:`no ESLint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`eslint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`ESLint: lint autofix`}]:[{id:`eslint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`eslint`,capability:`lint`,executable:`eslint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`ESLint: lint check`}]}},ha=class{id=`oxlint`;name=`Oxlint`;capabilities=[`lint`];detect(e){let t=e.jsEnv?.packageJson,n=la(t,`oxlint`),r=ua(e.cwd,[`.oxlintrc.json`,`oxlint.json`,`oxlint.config.ts`,`oxlint.config.js`]);return n&&r?{detected:!0,reason:`Oxlint dependency and configuration detected`}:r?{detected:!0,reason:`Oxlint configuration detected`}:n?{detected:!1,reason:`Oxlint dependency present without configuration`}:{detected:!1,reason:`no Oxlint dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxlint-lint-fix`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxlint: lint autofix`}]:[{id:`oxlint-lint-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxlint`,capability:`lint`,executable:`oxlint`,args:[`.`],cwd:e.cwd,mode:`check`,description:`Oxlint: lint check`}]}},ga=class{id=`oxfmt`;name=`Oxfmt`;capabilities=[`format`];detect(e){let t=e.jsEnv?.packageJson,n=la(t,`oxfmt`),r=ua(e.cwd,[`.oxfmtrc.json`,`oxfmt.json`,`oxfmt.config.ts`,`oxfmt.config.js`]);return n&&r?{detected:!0,reason:`Oxfmt dependency and configuration detected`}:r?{detected:!0,reason:`Oxfmt configuration detected`}:n?{detected:!1,reason:`Oxfmt dependency present without configuration`}:{detected:!1,reason:`no Oxfmt dependency or configuration`}}plan(e,t){return t===`fix`?[{id:`oxfmt-format`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--write`,`.`],cwd:e.cwd,mode:`fix`,description:`Oxfmt: format`}]:[{id:`oxfmt-check`,toolId:this.id,toolName:this.name,requiredPackage:`oxfmt`,capability:`format`,executable:`oxfmt`,args:[`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Oxfmt: format check`}]}},_a=class{id=`javascript`;name=`JavaScript/TypeScript`;scriptAdapter=new sa;vitePlusAdapter=new da;biomeAdapter=new fa;prettierAdapter=new pa;eslintAdapter=new ma;oxlintAdapter=new ha;oxfmtAdapter=new ga;detect(e){return!!e.jsEnv?.hasPackageJson}getAdapters(e){return[this.scriptAdapter,this.vitePlusAdapter,this.biomeAdapter,this.oxfmtAdapter,this.prettierAdapter,this.oxlintAdapter,this.eslintAdapter]}},va=class{id=`ruff`;name=`Ruff`;capabilities=[`lint`,`format`];detect(e){return e.hasPythonSource??or(e.cwd)?{detected:!0,reason:`default Python toolchain`}:{detected:!1,reason:`no Python source files detected`}}plan(e,t){let n=[];return t===`fix`?n.push({id:`ruff-lint-fix`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`--fix`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: lint autofix`},{id:`ruff-format`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`.`],cwd:e.cwd,mode:`fix`,description:`Ruff: format`}):n.push({id:`ruff-lint-check`,toolId:this.id,capability:`lint`,executable:`ruff`,args:[`check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: lint check`},{id:`ruff-format-check`,toolId:this.id,capability:`format`,executable:`ruff`,args:[`format`,`--check`,`.`],cwd:e.cwd,mode:`check`,description:`Ruff: format check`}),n}},ya=class{id=`python`;name=`Python`;ruffAdapter=new va;detect(e){return e.hasPythonSource??or(e.cwd)}getAdapters(e){return[this.ruffAdapter]}},ba=class{providers=/* @__PURE__ */ new Map;standaloneAdapters=/* @__PURE__ */ new Map;registerProvider(e){this.providers.set(e.id,e)}getProvider(e){return this.providers.get(e)}getProviders(){return Array.from(this.providers.values())}registerAdapter(e){this.standaloneAdapters.set(e.id,e)}getAdapter(e){return this.standaloneAdapters.get(e)}getStandaloneAdapters(){return Array.from(this.standaloneAdapters.values())}clear(){this.providers.clear(),this.standaloneAdapters.clear()}};function xa(){let e=new ba;return e.registerProvider(new ya),e.registerProvider(new _a),e}const Sa=xa();async function Ca(e,t=process.cwd()){let n=`${e.command} ${e.args.join(` `)}`.trim();if(en(`Installing JS dependencies: ${n}`),await Yt(e.command,e.args,{cwd:t,ignoreReturnCode:!0})!==0)throw Error(`JS dependency installation failed executing "${n}". Check dependency constraints or lockfile compatibility.`)}async function wa(e=process.cwd()){let t=fn(e);if(!t.hasPackageJson){en(`No package.json found. Skipping scripts.`);return}if(t.packageJsonError)throw Error(t.packageJsonError);let n=cn(process.env.PACKAGE_MANAGER||_n(t).name),r=(await Lr(Sa,{cwd:e,jsEnv:t,jsPm:n,hasPythonSource:!1},`fix`)).tasks.filter(e=>e.toolId!==`ruff`);if(r.length===0){en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`);return}await Ca(vn(n),e);let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}}async function Ta(e,t,n=process.cwd()){let r=`${e} ${t.join(` `)}`.trim();if(en(`Executing: ${r}`),await Yt(e,t,{cwd:n,ignoreReturnCode:!0})!==0)throw Error(`Python command "${r}" failed. Check Python environment and dependency configuration.`)}async function Ea(e,t=process.cwd()){Dr(e,`Invalid Python environment: "pmInfo" must be an object`);let n=e.name===`pip`?`pip`:e.name;if(!await Vt(n,!1)&&!e.isStandalone){let e=`Required Python package manager '${n}' is not available in PATH.`;throw Error(e)}if(!e.isStandalone&&e.installCommands.length>0){let n=e.installCommands;en(`Installing Python dependencies: ${n.map(e=>`${e.executable} ${e.args.join(` `)}`).join(` && `)}`);for(let{executable:e,args:r}of n)await Ta(e,r,t)}}async function Da(e=process.cwd(),t,n){if(!(t??or(e)))return;let r;if(n)r=n;else{if(!await Vt(`ruff`,!1))throw Error(`Required Python binary 'ruff' is not available in PATH.`);r=(await Lr(Sa,{cwd:e,hasPythonSource:!0},`fix`)).tasks.filter(e=>e.toolId===`ruff`)}let i=(await new Ar().executeTasks(r)).filter(e=>e.error);if(i.length>0){let e=i.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}}async function Oa(e,t){if(process.env.JS_SETUP_OUTCOME===`failure`||process.env.NODE_SETUP_OUTCOME===`failure`||process.env.BUN_SETUP_OUTCOME===`failure`||process.env.PNPM_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`JavaScript runtime or package manager setup failed.`);try{if(t){let n=fn(e);if(!n.hasPackageJson)return en(`No package.json found. Skipping scripts.`),null;if(n.packageJsonError)throw Error(n.packageJsonError);if(t.length===0)return en(`No matching scripts (fix, format, lint, check, etc.) found in package.json.`),null;await Ca(vn(cn(process.env.PACKAGE_MANAGER||_n(n).name)),e);let r=(await new Ar().executeTasks(t)).filter(e=>e.error);if(r.length>0){let e=r.map(e=>e.error?.message||`Task ${e.task.id} failed`);throw Error(e.join(` +`))}return null}return await wa(e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function ka(e,t){if(process.env.PYTHON_SETUP_OUTCOME===`failure`||process.env.UV_SETUP_OUTCOME===`failure`||process.env.PY_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Python runtime or package manager setup failed.`);let n=t&&`pmInfo`in t?t.pmInfo:Tr(e,void 0,{ctx:t?.ctx,hasSource:t?.hasSource});if(!n)return null;try{return await Ea(n,e),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function Aa(e,t,n){if(process.env.RUFF_SETUP_OUTCOME===`failure`)return/* @__PURE__ */ Error(`Ruff setup failed.`);try{return await Da(e,t,n),null}catch(e){return e instanceof Error?e:Error(String(e))}}async function ja(e,t,n){let r=t??or(e);if(!r)return[];let i=[],a=ir(e),o=await ka(e,{ctx:a,hasSource:!0,pmInfo:Tr(e,void 0,{ctx:a,hasSource:!0,isProject:!0})});o&&i.push(o);let s=await Aa(e,r,n);return s&&i.push(s),i}async function Ma(e=process.cwd()){let t=or(e),n;try{let r=fn(e),i={cwd:e,jsEnv:r,jsPm:cn(process.env.PACKAGE_MANAGER||_n(r).name),hasPythonSource:t};n=await Lr(Sa,i,`fix`),en(n.summary)}catch{}let r=[],i=n?n.tasks.filter(e=>e.toolId!==`ruff`):void 0,a=n?n.tasks.filter(e=>e.toolId===`ruff`):void 0,o=await Oa(e,i);o&&r.push(o);let s=await ja(e,t,a);r.push(...s),r.length>0&&(Zt(`Failed to run scripts: ${r.map(e=>e.message).join(` +`)}`),process.env.NODE_ENV!==`test`&&process.exit(1))}process.env.NODE_ENV!==`test`&&Or(import.meta.url)&&Ma();export{wa as executeJsWorkflow,Ea as executePythonWorkflow,Da as executeRuffAutofix,Ma as run,cn as sanitizePackageManager}; \ No newline at end of file diff --git a/src/autofix/adapters/javascript/script-adapter.ts b/src/autofix/adapters/javascript/script-adapter.ts index 8bb35fef..af8581af 100644 --- a/src/autofix/adapters/javascript/script-adapter.ts +++ b/src/autofix/adapters/javascript/script-adapter.ts @@ -190,7 +190,7 @@ function splitChainedCommandsDetailed(shellText: string): SplitResult { return { commands, hasSyntaxError: state.hasSyntaxError }; } -function splitChainedCommands(shellText: string): string[] { +export function splitChainedCommands(shellText: string): string[] { return splitChainedCommandsDetailed(shellText).commands; } @@ -240,6 +240,7 @@ interface CommandInspection { tokens: string[]; hasUnsupportedSyntax: boolean; hasRedirection: boolean; + hasSyntaxError: boolean; } function isBackgroundOp(cmd: string, index: number, state: TokenizerState): boolean { @@ -343,6 +344,7 @@ function inspectAndTokenizeCommandLine(cmd: string): CommandInspection { tokens: [], hasUnsupportedSyntax: false, hasRedirection: false, + hasSyntaxError: false, }; const state: TokenizerState = { inSingleQuote: false, inDoubleQuote: false, isEscaped: false }; const ctx: TokenizeScanContext = { inspection, state }; @@ -368,6 +370,7 @@ function inspectAndTokenizeCommandLine(cmd: string): CommandInspection { if (state.inSingleQuote || state.inDoubleQuote || state.isEscaped) { inspection.hasUnsupportedSyntax = true; + inspection.hasSyntaxError = true; } if (hasCharsInWord) { @@ -377,7 +380,7 @@ function inspectAndTokenizeCommandLine(cmd: string): CommandInspection { return inspection; } -function tokenizeCommandLine(cmd: string): string[] { +export function tokenizeCommandLine(cmd: string): string[] { return inspectAndTokenizeCommandLine(cmd).tokens; } @@ -416,18 +419,33 @@ function matchesPmDelegation(cmdTokens: string[], targetScriptName: string): boo return false; } -export function parseCommandInvocations(scriptBody: string): string[][] { - if (!scriptBody) return []; - const commands = splitChainedCommands(scriptBody); +export interface ParsedCommandInvocations { + invocations: string[][]; + hasSyntaxError: boolean; +} + +export function parseCommandInvocationsDetailed(scriptBody: string): ParsedCommandInvocations { + if (!scriptBody) return { invocations: [], hasSyntaxError: false }; + const splitResult = splitChainedCommandsDetailed(scriptBody); + let hasSyntaxError = splitResult.hasSyntaxError; const invocations: string[][] = []; - for (const cmd of commands) { - const rawTokens = tokenizeCommandLine(cmd); - const cmdTokens = getCommandInvocationTokens(rawTokens); + + for (const cmd of splitResult.commands) { + const inspection = inspectAndTokenizeCommandLine(cmd); + if (inspection.hasSyntaxError) { + hasSyntaxError = true; + } + const cmdTokens = getCommandInvocationTokens(inspection.tokens); if (cmdTokens.length > 0) { invocations.push(cmdTokens); } } - return invocations; + + return { invocations, hasSyntaxError }; +} + +export function parseCommandInvocations(scriptBody: string): string[][] { + return parseCommandInvocationsDetailed(scriptBody).invocations; } /** @@ -781,7 +799,10 @@ export function hasVitePlusCommand( activePath: Set = new Set(), ): boolean { if (!scriptBody) return false; - const invocations = parseCommandInvocations(scriptBody); + const { invocations, hasSyntaxError } = parseCommandInvocationsDetailed(scriptBody); + if (hasSyntaxError) { + return false; + } for (const rawTokens of invocations) { const tokens = unwrapEnvironmentWrapper(rawTokens); diff --git a/tests/autofix-architecture.test.ts b/tests/autofix-architecture.test.ts index 4c77532d..a6ed04cc 100644 --- a/tests/autofix-architecture.test.ts +++ b/tests/autofix-architecture.test.ts @@ -1915,6 +1915,83 @@ describe("Refactored Autofix Architecture & Tool Adapters", () => { const plan = await planExecution(registry, { cwd: tempDir }, "fix"); expect(plan.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); }); + + it("rejects malformed commands with confirmed shell syntax errors during Vite+ detection", async () => { + // 1. Unterminated single quote + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + broken1: "vp fmt 'unterminated", + }, + }), + ); + fs.writeFileSync(path.join(tempDir, "vite.config.ts"), "export default {};"); + + const registry = createDefaultRegistry(); + const planSingle = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planSingle.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + + // 2. Unterminated double quote + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + broken2: 'vp fmt "unterminated', + }, + }), + ); + const planDouble = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planDouble.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + + // 3. Command ending with an incomplete trailing escape \ + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + broken3: "vp fmt \\", + }, + }), + ); + const planEscape = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planEscape.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + + // 4. Malformed nested shell-wrapper invocation (unterminated quote in sh -c argument) + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + broken4: "sh -c 'vp check", + }, + }), + ); + const planMalformedSh = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planMalformedSh.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + + // 5. Malformed nested shell-wrapper invocation (unterminated quote inside wrapped script) + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + broken5: 'bash -c "vp fmt \'unterminated"', + }, + }), + ); + const planMalformedBash = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planMalformedBash.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + + // 6. Malformed command containing vp in argument position + fs.writeFileSync( + path.join(tempDir, "package.json"), + JSON.stringify({ + scripts: { + broken6: "grep 'unterminated vp", + }, + }), + ); + const planGrepMalformed = await planExecution(registry, { cwd: tempDir }, "fix"); + expect(planGrepMalformed.selectedTools.map((t) => t.id)).not.toContain("vite-plus"); + }); }); describe("Multi-Language Monorepo Capability Isolation", () => {