RTK 的 JavaScript/TypeScript/Node 命令过滤器包管理器自动检测、跨生态 lint 路由与三层解析【免费下载链接】rtkCLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies项目地址: https://gitcode.com/GitHub_Trending/rtk4/rtk本篇基于 RTK 仓库 src/cmds/js/README.md 展开系统讲解 RTK 为 JavaScript/TypeScript/Node 生态提供的命令过滤模块package_manager_exec()如何自动检测 pnpm/yarn/npm 并构造执行命令rtk lint如何作为跨生态路由器把 Python 项目委派给mypy_cmd/ruff_cmd以及vitest_cmd与playwright_cmd如何借助parser/模块实现 JSON → 正则 → 透传的三层降级解析。读完后你可以理解 RTK 在 JS 生态下的完整调用链并能据此在自己的 CLI 代理中设计类似的结构化输出压缩方案。模块总览RTK 的命令过滤模块按语言/工具链分生态组织JS 生态目录 src/cmds/js/ 包含以下 9 个 Rust 源文件见 模块目录 通过automod::dir!自动注册文件对应子命令核心能力npm_cmd.rsrtk npm、rtk npx自动注入run子命令剥离 npm 样板输出pnpm_cmd.rsrtk pnpm list/outdated/install依赖树 JSON 解析prod/dev 分组列表vitest_cmd.rsrtk vitest、rtk jest三层测试输出解析README 重点模块playwright_cmd.rsrtk playwrightE2E 测试结果提取README 重点模块tsc_cmd.rsrtk tscTypeScript 诊断按文件/错误码分组流式过滤lint_cmd.rsrtk lint跨生态 lint 路由器README 重点模块prettier_cmd.rsrtk prettier仅显示需要格式化的文件同时被rtk format复用next_cmd.rsrtk next build提取路由指标与 bundle 体积prisma_cmd.rsrtk prisma generate/migrate/db push剥离 ASCII 艺术图提取变更统计按 src/cmds/README.md 的边界约定本目录的模块只负责执行外部命令 过滤其输出并通过core/tracking记录 token 节省量选择 Rust 模块而非 TOML 过滤器的原因在于它们需要解析结构化输出JSON、注入 CLI flag如--reporterjson以及跨命令路由。包管理器自动检测utils::package_manager_exec()JS 生态 README 的第一条 Specifics 指出所有 JS 模块应使用utils::package_manager_exec()而不是硬编码某个包管理器。其实现位于 src/core/utils.rs由两个函数构成。检测规则以 lockfile 为准detect_package_manager()在当前工作目录按优先级探测 lockfilepub fn detect_package_manager() - static str { if std::path::Path::new(pnpm-lock.yaml).exists() { pnpm } else if std::path::Path::new(yarn.lock).exists() { yarn } else { npm } }检测顺序是pnpm-lock.yaml→yarn.lock→ 默认npm。也就是说在 pnpm 项目中RTK 会优先走pnpm exec而不是猜测用户全局装了哪个工具。执行构造先查 PATH再回退到包管理器 execpackage_manager_exec(tool)的构造逻辑是pub fn package_manager_exec(tool: str) - Command { if tool_exists(tool) { resolved_command(tool) // 工具已在 PATH 上直接执行 } else { let pm detect_package_manager(); match pm { pnpm { /* pnpm exec -- tool */ } yarn { /* yarn exec -- tool */ } _ { /* npx --no-install -- tool */ } } } }两个关键设计点工具优先如果vitest、prettier等工具本身已在 PATH全局安装直接执行该工具不经过包管理器包裹减少一层进程开销npm 回退用--no-install避免npx在工具缺失时联网下载RTK 只代理不安装。同一文件中还有一个 Windows 适配细节resolve_binary 的注释Windows 上 Node.js 工具常以.CMD/.BAT/.PS1shim 形式安装而 Rust 的Command::new()不识别 PATHEXT因此 RTK 使用whichcrate 做 PATHPATHEXT 双重解析——否则Command::new(vitest)在vitest.CMD位于 PATH 时仍会失败。这个函数被 prettier_cmd.rspackage_manager_exec(prettier)、vitest_cmd.rsvitest/jest 分支和 lint_cmd.rsJS linter 分支统一复用。而 playwright_cmd.rs 是刻意的例外它不复用package_manager_exec的工具优先逻辑而是永远走包管理器 exec——源码注释解释了原因which playwright可能匹配到 pyenv 的 Python shim 或其他非 Node 二进制playwright这个名字跨语言存在歧义所以直接内联了detect_package_manager()pnpm/yarn exec的构造。跨生态 lint 路由rtk lintREADME 的第二个要点是lint_cmd.rs是一个跨生态路由器——检测 Python 项目并委派给mypy_cmd或ruff_cmd。这使得用户不需要知道项目在 JS 还是 Python 生态rtk lint一条命令通吃。src/cmds/js/lint_cmd.rs 的路由分四步。第一步剥离包管理器前缀用户可能写rtk lint npx eslint src/或rtk lint pnpm exec biome check。strip_pm_prefix()会跳过开头的npx/bunx/pnpm/yarn/exec参数返回应跳过的个数后续逻辑在有效参数上工作。单测test_strip_pm_prefix_pnpm_exec验证了[pnpm, exec, eslint]返回 2跳过两个前缀。第二步推断 linter 名detect_linter()的规则如果首个参数是路径含/或.、以-开头的 flag、或参数为空则默认eslint且视为隐式否则把首个参数当作 linter 名且视为显式。测试test_detect_linter_default_on_flag覆盖--max-warnings0默认 eslint 的场景。第三步按 linter 类型选执行路径并注入 JSON flaglet mut cmd if is_python_linter(linter) { resolved_command(linter) // ruff/pylint/mypy/flake8pip 安装直接在 PATH 上 } else { package_manager_exec(linter) // eslint/biome 等走 npm 生态检测 };其中is_python_linter()的匹配集合是ruff | pylint | mypy | flake8lint_cmd.rs#L56-L58。随后按 linter 注入结构化输出 flaglinter注入的 flag说明eslint-f json强制 JSON reporterruffcheck --output-formatjson若用户已带--output-format则不重复注入pylint--output-formatjson2同上用户显式指定时跳过mypy无默认文本输出走文本过滤对用户参数--output-format开头的会被二次去重对ruff/pylint/mypy/eslint四个 linter如果用户没给路径自动补.检查当前目录。进程若被信号杀死退出码 128典型为 OOM会打印前 5 行 stderr 并原样返回退出码。第四步按 linter 分发过滤器——Python 侧委派给 python 模块let filtered match linter { eslint filter_eslint_json(result.stdout), ruff ruff_cmd::filter_ruff_check_json(result.stdout), // 复用 python 模块 pylint filter_pylint_json(result.stdout), mypy mypy_cmd::filter_mypy_output(raw), // 复用 python 模块 _ filter_generic_lint(raw), };这就是 README 所说routes tocmds/python/mypy_cmdandcmds/python/ruff_cmd的实现mypy与ruff的过滤逻辑不重复实现而是直接调用 src/cmds/python/mypy_cmd.rs 和 src/cmds/python/ruff_cmd.rs 导出的函数。filter_eslint_json()本身展示了 RTK 的典型压缩策略lint_cmd.rs#L220-L316解析 ESLint 的 JSON 结果数组后输出总量行ESLint: N errors, M warnings in K files、Top 10 规则按出现次数排序、Top 文件上限CAP_WARNINGS每个文件下再列该文件前 3 条规则超出部分以… N more files收尾并附 tee 恢复提示。JSON 解析失败时降级为truncate到passthrough_max_chars的原样透传保证过滤结果永不比原始输出更差。compact_path()还会把/Users/.../src/utils.ts压缩成src/utils.ts以省 token单测test_compact_path覆盖 macOS、Windows 反斜杠与裸文件名三种形态。vitest_cmd三层降级解析Tier 1/2/3README 第三、四条 Specifics 分别说vitest_cmd.rs与playwright_cmd.rsuse theparser/module for structured output parsing。src/parser/ 提供了统一的OutputParser/ParseResult抽象ParseResult有三种形态FullTier 1 完整解析、DegradedTier 2 部分信息 降级警告、PassthroughTier 3 截断透传。参数构造默认注入 JSON reporterrun_test()vitest_cmd.rs#L202-L226同时服务Commands::Vitest与Commands::Jest两个子命令。vitest 分支由build_vitest_effective_args()构造参数默认前置run并注入--reporterjson若用户显式带了--reporter或--reporterxxxhas_explicit_vitest_reporter()则不注入、整个输出走透传模式passthrough true尊重用户想要的 reporter 格式用户传入的run、--json*、--watch*参数会被去重跳过should_skip_vitest_arg()。jest 分支则强制--no-watch和--json并跳过用户传入的run/--json*/--reporter*/--watch*参数。Tier 1JSON 解析 前缀提取回退VitestParser::parse()先直接serde_json反序列化 vitest 的testResults结构失败时调用extract_json_object()从混合输出中提取JSON 对象再解析。这个回退针对的是真实场景pnpm 会打印Scope: all N workspace projects前缀、dotenv 会打印加载日志JSON 不在 stdout 开头。对应的单测test_vitest_parser_with_pnpm_prefix和test_vitest_parser_with_dotenv_prefix验证这两类前缀下仍返回 Tier 1 结果。解析成功后从numTotalTests/numPassedTests/numFailedTests/numPendingTests与每个assertionResults中status failed的failureMessages构造TestResult失败用例名 文件 错误信息。Tier 2正则提取统计降级模式JSON 解析失败时用两个正则降级static TESTS_RE: LazyLockRegex LazyLock::new(|| Regex::new(rTests\s(?:(\d)\sfailed\s\|\s)?(\d)\spassed).unwrap()); static DURATION_RE: LazyLockRegex LazyLock::new(|| Regex::new(rDuration\s([\d.])(ms|s)).unwrap());即从Tests 3 failed | 10 passed这类摘要行提取通过/失败数Duration 450ms提取耗时秒会自动换算为毫秒。源码注释明确 Tier 2 only fires if user overrides--reporterflag。降级时emit_degradation_warning()会在 verbose 模式打印警告。Tier 3截断透传正则也提取不到有效数据total 0时进入ParseResult::Passthrough输出经truncate_passthrough()截断并打All parsing tiers failed警告。截断时会通过force_tee_hint附上完整输出恢复提示单测test_vitest_explicit_reporter_truncated_output_adds_recovery_hint验证了[RTK:PASSTHROUGH] Output truncated标记与 tee 提示路径。三层设计的测试覆盖很完整test_vitest_parser_jsonTier 1、test_vitest_parser_regex_fallbackTier 2、test_vitest_parser_passthroughTier 3分别断言result.tier()为 1/2/3。playwright_cmd递归收集 suites → specs → tests 结构playwright_cmd.rs 的PlaywrightParser针对 Playwright JSON reporter 的嵌套结构定义了解析树statssuites可嵌套 describe 块→specs单个 test 函数跨多个 project/browser→tests每个 project 的执行状态expected/unexpected/skipped/flaky→results每次尝试passed/failed/timedOut/interruptederrors数组。collect_test_results()递归遍历嵌套 suite对ok false的 spec 找到第一个unexpected执行、再找到failed/timedOut的 attempt取errors[0].message作为失败信息playwright_cmd.rs#L125-L163。值得注意的细节duration 是浮点数真实 Playwright 输出为3519.7039999999997故结构体用#[serde(default)] duration: f64单测test_playwright_parser_json_float_duration专门验证浮点耗时的解析与取整3519参数注入仅当首个参数是test时注入test --reporterjson并剥离用户自己的--reporter参数以避免冲突playwright_cmd.rs#L262-L277Tier 2 正则(\d)\s(passed|failed|flaky|skipped)匹配摘要计数、\((\d(?:\.\d)?)(ms|s|m)\)匹配耗时支持 ms/s/m 三种单位换算退出码被显式保留if !result.success() { return Ok(result.exit_code); }注释写明是Preserve exit code for CI/CD。生态内其他命令的压缩策略rtk npm智能注入runnpm_cmd.rs 维护了一个 60 项的NPM_SUBCOMMANDS白名单install/i/ci/outdated/audit/publish/test/t/start等。路由规则rtk npm run build→ 显式run原样执行rtk npm install→ 白名单内子命令原样执行rtk npm build→ 首个参数既不是run也不在白名单、且不以-开头 → 自动改写为npm run build。测试test_npm_subcommand_routing直接遍历整个白名单断言不注入 run并对build/dev/lint/typecheck/deploy断言应注入 run白名单常量在生产代码与测试间共享以避免漂移。输出过滤filter_npm_output剥离 project1.0.0 build样板行、npm WARN/npm notice行、进度条字符全空时输出ok。exec()入口还让rtk npx tool走同一条过滤管线并支持SKIP_ENV_VALIDATION1环境变量。rtk prettiercheck 模式与 write 模式区分prettier_cmd.rs 的过滤器区分两种模式check 模式下收集以.ts/.tsx/.js/.jsx/.json/.md/.css/.scss结尾的文件行输出Prettier: N files need formatting 编号列表上限CAP_WARNINGSN files already formattedwrite 模式输出含modified/formatted则只输出Prettier: N files formatted。空输出会被判定为Error: prettier produced no output而非误报全部已格式化注释标记为 issue #221 的回归防护对应单测test_filter_empty_output。rtk tsc流式诊断分组与假绿防护tsc_cmd.rs 用三条正则识别三种诊断形态默认格式file(line,col): error TSxxxx: msg、--pretty格式file:line:col - error TSxxxx: msg先剥 ANSI、以及无文件的error TSxxxx: msg全局错误。它走runner::run_streamed()流式路径BlockStreamFilter实时累计错误数、文件集合、错误码计数末尾输出TypeScript: N errors in M files Top 5 错误码。一个重要的防假绿设计当编译器非零退出但 RTK 一条诊断都没解析出来二进制缺失、无 tsconfig、输出不可解析时format_summary()不会打印 No errors found而是输出TypeScript: compiler exited with code N, but RTK parsed no diagnostics并保留原始输出的头部 5 行 尾部行MAX_UNPARSED_HEAD_LINES/MAX_UNPARSED_LINES因为 tsc 习惯把真正的原因如Unknown compiler option打印在前面。单测test_tsc_stream_failed_without_project_keeps_cause用真实 fixture tests/fixtures/tsc_no_project_raw.txt 验证了Version 6.0.3等关键信息被保留。rtk next build/rtk pnpm/rtk prismanext_cmd.rs按行首符号○/●/◐/λ统计静态/动态路由正则提取路由 bundle 体积输出N routes (X static, Y dynamic) 按体积降序的 Top 路由表并计算 First Load JS 相对单路由的增幅超 10% 标记[warn]pnpm_cmd.rslist --depthN --json与outdated --format json同样走三层解析JSON → 文本行提取 → 透传列表输出按[prod]/[dev]分组、单组上限CAP_LISTING--prod/--dev过滤时关闭截断以便 LLM 找到全部包install则剥离进度条只保留汇总行与错误行prisma_cmd.rs覆盖generate/migrate dev|status|deploy/db push五个场景过滤器剥离 box-drawing ASCII 艺术█▀▄┌└│等字符提取 migration 名、CREATE TABLE/ALTER TABLE/CREATE INDEX计数输出形如Migration: 20260128_add_sessions 1 table(s)Applied | Pending: 0的紧凑摘要且所有路径都经never_worse()守卫。跨模块协作rtk format如何复用prettier_cmdREADME 的 Cross-command 一节最后一条prettier_cmd同时被cmds/system/format_cmd作为格式分发目标调用。src/cmds/system/format_cmd.rs 的detect_formatter()检测逻辑首个参数若是prettier | black | ruff | biome之一直接采用显式指定优先否则读pyproject.toml含[tool.black]→ black含[tool.ruff.format]/[tool.ruff]→ ruff再否则检查package.json或.prettierrc*→ prettier兜底选ruff。选定 prettier 后执行用package_manager_exec(prettier)与 JS 生态共享的包管理器检测输出过滤直接调用prettier_cmd::filter_prettier_output()——即 src/cmds/js/prettier_cmd.rs#L29 中pub fn导出的那个函数。ruff/black 分支则调用ruff_cmd::filter_ruff_format()与本地filter_black_output()并分别为 black 补--check、为 ruff 补format子命令。这解释了为什么prettier_cmd虽然位于js/目录其过滤函数却要做pub导出供system/生态复用——README 所说的format dispatcher target。验证入口与参考路径以上行为均有对应单测可直接验证均为各源文件内#[cfg(test)] mod tests可用cargo test过滤运行包管理器前缀剥离与 linter 检测src/cmds/js/lint_cmd.rs#L624-L707vitest 三层解析与参数构造src/cmds/js/vitest_cmd.rs#L413-L606playwright JSON/浮点耗时/正则降级src/cmds/js/playwright_cmd.rs#L329-L474tsc 流式过滤与 fixture 级回归src/cmds/js/tsc_cmd.rs#L474-L708fixture 位于 tests/fixtures/tsc_pretty_raw.txt、tests/fixtures/tsc_global_config_error_raw.txtnpm 子命令路由白名单src/cmds/js/npm_cmd.rs#L193-L229。关键源码路径汇总路径内容src/cmds/js/README.md本文主体文档src/core/utils.rsdetect_package_manager()/package_manager_exec()/resolve_binary()src/cmds/js/lint_cmd.rs跨生态 lint 路由src/cmds/js/vitest_cmd.rsvitest/jest 三层解析src/cmds/js/playwright_cmd.rsPlaywright E2E 结果提取src/cmds/js/tsc_cmd.rstsc 流式诊断过滤src/cmds/js/npm_cmd.rsnpm/npx 路由与样板剥离src/cmds/js/prettier_cmd.rsPrettier 过滤被 format_cmd 复用src/cmds/system/format_cmd.rs格式分发器src/parser/mod.rsOutputParser/ParseResult三层抽象src/cmds/README.md命令模块执行流与 FilterMode 说明适用前提以上行为均基于当前仓库源码detect_package_manager()只识别pnpm-lock.yaml与yarn.lock两种 lockfile其他包管理器bun 等会落到 npm/npx --no-install回退分支rtk lint对未在路由表中的 linter 走filter_generic_lint()的按行统计兜底。【免费下载链接】rtkCLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies项目地址: https://gitcode.com/GitHub_Trending/rtk4/rtk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
