Skip to content

feat: 为 @nutui/nutui-react-taro 补齐 AI-Coding 能力(CLI / MCP / Skill + 站点文档) - #3500

Merged
xiaoyatong merged 3 commits into
jdf2e:feat_v4.xfrom
alvinhui:feature/taro-ai-coding
Jul 30, 2026
Merged

feat: 为 @nutui/nutui-react-taro 补齐 AI-Coding 能力(CLI / MCP / Skill + 站点文档)#3500
xiaoyatong merged 3 commits into
jdf2e:feat_v4.xfrom
alvinhui:feature/taro-ai-coding

Conversation

@alvinhui

@alvinhui alvinhui commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

背景

本仓库产出两个 npm 包:@nutui/nutui-react(H5)与 @nutui/nutui-react-taro(Taro 跨端)。此前面向 AI-Coding 的能力(CLI + MCP + Skill + 站点 ai/* 文档)只覆盖 H5 端:

  • CLI 包 @nutui/nutui-react-cli 仅服务 H5(数据快照只取 H5 端 docs/demos)。
  • 站点 ai-taro/ 只有 llms.md,而 nav 的 AI 子菜单(For Agents / CLI / MCP)为 H5/Taro 共用,导致 Taro 站点这三个菜单点进去 404

本 PR 用与 H5 完全对称的思路,给 Taro 端补齐全套能力。

改动概览

数据层(scripts/)

  • create-properties.js:传 taro 参数时输出 properties-taro.json(扫 doc.taro.md),不再覆盖 H5 的 properties.json
  • build-meta.mjs:每个组件新增 apiTaro 字段(Taro 端 Props),与 H5 的 api 并存。实测 29 个组件两端 Props 存在真实差异(如 Button 的 type:H5 含 service、Taro 不含)。
  • package.json:新增 generate:props / generate:props:taro 脚本;prebuild:site / prebuild:taro:site 分别串联对应端的 props 生成。
  • 顺带修复了过时的 properties.json(与当前 doc.md 重新同步,记录数 930 → 1174)。

CLI 层(packages/)

  • 新建 @nutui/nutui-react-cli-core(private,不发布):承载全部命令 / MCP / 数据查询逻辑,平台差异收敛到 CliConfig 接口。
  • @nutui/nutui-react-cli(H5)瘦身为薄壳:仅保留构造 H5 CliConfig 的入口,委托 core,行为零回归。
  • 新建 @nutui/nutui-react-taro-cli:bin: nutui-react-taro,MCP server nutui-react-taro,仅中文文档,数据取 apiTaro / demos.taro。含独立 SKILL.md 与 README。
  • 两个发布包经 tsup 把 core 源码 bundle 进各自 dist/cli.js(零运行时依赖);core 以 workspace:* devDependency 引入,发布安全(消费者不会去 registry 找未发布的 core)。

站点文档(src/sites/sites-react/doc/docs/ai-taro/)

  • 新增 For Agents / CLI / MCP 各中英双语共 6 篇,补上 Taro 站点原本 404 的三个 AI 菜单。aiTaroRoutes 已按 glob 自动收录,无需改路由 / nav。

验证

  • 三包 typecheck 通过(core / H5 / Taro)
  • 两个 CLI 包 build 成功,产物已内联 core、无对 core 的运行时 import
  • Taro CLI:list 头部显示「Taro 多端」、info Button 取 apiTaro(无 service)、demo 取 Taro 示例、doc --lang en 因单语言不注册该选项
  • Taro MCP:server name nutui-react-taro、5 个 nutui_* 工具、nutui_doc 的 lang enum 仅 ["zh"]
  • H5 CLI / MCP 回归无异常(server、doc 双语、list 头部均不变)
  • npm run build:taro:site 成功,6 篇 ai-taro 文档均编译为独立 chunk

备注

  • properties.json 的大范围 diff 是过时数据的同步刷新,与本 PR 同批提交。

Summary by CodeRabbit

  • 新功能

    • 新增 NutUI React Taro 离线知识查询 CLI,支持组件列表、Props、文档、示例、Design Token 查询及 JSON 输出。
    • 支持 MCP 服务,可供 AI 工具调用组件知识与页面生成提示。
    • 新增组件属性数据与 Taro 专属文档、示例内容。
  • 文档

    • 新增 CLI、MCP、AI Agent 及 Skill 使用指南,涵盖安装、配置和常用命令。

@github-actions github-actions Bot added action:review This PR needs more reviews (less than 2 approvals) and removed size/XXL labels Jul 30, 2026
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 31ed4977-8b71-494c-9cd4-d73e23c1fc2a

📥 Commits

Reviewing files that changed from the base of the PR and between d6ee5b9 and ca92cbb.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (47)
  • package.json
  • packages/nutui-react-cli-core/.gitignore
  • packages/nutui-react-cli-core/package.json
  • packages/nutui-react-cli-core/scripts/prepare-data.mjs
  • packages/nutui-react-cli-core/src/cli.ts
  • packages/nutui-react-cli-core/src/commands/_shared.ts
  • packages/nutui-react-cli-core/src/commands/demo.ts
  • packages/nutui-react-cli-core/src/commands/doc.ts
  • packages/nutui-react-cli-core/src/commands/info.ts
  • packages/nutui-react-cli-core/src/commands/list.ts
  • packages/nutui-react-cli-core/src/commands/mcp.ts
  • packages/nutui-react-cli-core/src/commands/token.ts
  • packages/nutui-react-cli-core/src/config.ts
  • packages/nutui-react-cli-core/src/data.ts
  • packages/nutui-react-cli-core/src/error.ts
  • packages/nutui-react-cli-core/src/format.ts
  • packages/nutui-react-cli-core/src/index.ts
  • packages/nutui-react-cli-core/src/mcp/prompts.ts
  • packages/nutui-react-cli-core/src/mcp/tools.ts
  • packages/nutui-react-cli-core/src/types.ts
  • packages/nutui-react-cli-core/tsconfig.json
  • packages/nutui-react-cli/package.json
  • packages/nutui-react-cli/scripts/prepare-data.mjs
  • packages/nutui-react-cli/src/cli.ts
  • packages/nutui-react-cli/src/mcp/prompts.ts
  • packages/nutui-react-cli/src/mcp/tools.ts
  • packages/nutui-react-cli/tsup.config.ts
  • packages/nutui-react-taro-cli/.gitignore
  • packages/nutui-react-taro-cli/README.md
  • packages/nutui-react-taro-cli/package.json
  • packages/nutui-react-taro-cli/scripts/prepare-data.mjs
  • packages/nutui-react-taro-cli/skills/.npmignore
  • packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md
  • packages/nutui-react-taro-cli/src/cli.ts
  • packages/nutui-react-taro-cli/tsconfig.json
  • packages/nutui-react-taro-cli/tsup.config.ts
  • pnpm-workspace.yaml
  • scripts/build-meta.mjs
  • scripts/create-properties.js
  • scripts/properties-taro.json
  • scripts/properties.json
  • src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/cli.md
  • src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/for-agents.md
  • src/sites/sites-react/doc/docs/ai-taro/mcp.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/mcp.md
💤 Files with no reviewable changes (2)
  • packages/nutui-react-cli/src/mcp/prompts.ts
  • packages/nutui-react-cli/src/mcp/tools.ts

Walkthrough

新增可配置的 CLI core、Taro CLI 与 MCP 能力,统一 H5/Taro 数据快照生成流程,并扩展属性元数据与相关文档、技能说明。

Changes

CLI 平台化与 Taro 支持

Layer / File(s) Summary
双端属性与数据快照生成
package.json, scripts/*, packages/nutui-react-cli*/scripts/*
构建流程新增 H5/Taro 属性生成;build-meta 输出 apiTaro 与统计字段;core 统一生成 H5/Taro 的 data 快照。
Core 配置、数据访问与命令运行时
packages/nutui-react-cli-core/src/*, packages/nutui-react-cli-core/package.json
新增 CliConfig、统一 CLI 解析、数据目录注入、格式化输出和结构化错误;各命令改为使用配置加载元数据。
MCP 能力与 H5 入口适配
packages/nutui-react-cli-core/src/mcp/*, packages/nutui-react-cli/src/*
MCP 工具、提示词和服务初始化改为配置驱动;H5 CLI 入口委托 core 执行并将 core 打包进产物。
Taro CLI 包与发布构建
packages/nutui-react-taro-cli/*, pnpm-workspace.yaml
新增 Taro CLI 包、入口、数据准备脚本、构建配置、发布元数据与技能文件。
Taro CLI 文档与集成说明
src/sites/sites-react/doc/docs/ai-taro/*
新增 CLI、Agent、MCP 的中英文使用文档及集成配置说明。

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant TaroCLI
  participant CoreCLI
  participant DataSnapshot
  participant MCPClient
  User->>TaroCLI: nutui-react-taro command
  TaroCLI->>CoreCLI: runCli(config, argv)
  CoreCLI->>DataSnapshot: loadMeta/readDoc/readDemo
  DataSnapshot-->>CoreCLI: component data
  MCPClient->>TaroCLI: MCP tool request
  TaroCLI-->>MCPClient: structured tool result
Loading

Possibly related PRs

Suggested reviewers: oasis-cloud, alex-huxiyang, xiaoyatong

Poem

小兔敲键盘,CLI 跑得欢,
H5、Taro 数据齐聚一盘。
MCP 递工具,文档随手看,
Props 新鲜出,页面写得安。
兔耳摇一摇,发布向前赶。

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.48% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 标题准确概括了为 Taro 端补齐 AI-Coding 能力的核心变更,且简洁明确。
Description check ✅ Passed 描述覆盖了背景、改动、验证与结果,虽未按模板完整填项但整体已较完整。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.44%. Comparing base (a938cf8) to head (ca92cbb).
⚠️ Report is 17 commits behind head on feat_v4.x.

Additional details and impacted files
@@              Coverage Diff              @@
##           feat_v4.x    #3500      +/-   ##
=============================================
+ Coverage      88.33%   88.44%   +0.10%     
=============================================
  Files            295      296       +1     
  Lines          19747    19812      +65     
  Branches        3117     3134      +17     
=============================================
+ Hits           17443    17522      +79     
+ Misses          2298     2284      -14     
  Partials           6        6              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (3)
packages/nutui-react-cli-core/src/mcp/tools.ts (1)

46-48: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

isError 的判定比 toMcpResult 宽松。

这里只检查 'error' in x,而 toMcpResult 还要求 error === true。目前 Component 没有 error 字段,所以行为正确;但两处判定不一致,后续给 Component 加同名字段就会静默把组件当错误处理。建议对齐为同一个谓词。

♻️ 建议对齐判定
 function isError(x: unknown): x is ReturnType<typeof createError> {
-  return !!x && typeof x === 'object' && 'error' in x
+  return (
+    !!x &&
+    typeof x === 'object' &&
+    (x as { error?: unknown }).error === true
+  )
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-cli-core/src/mcp/tools.ts` around lines 46 - 48, 统一
isError 与 toMcpResult 的错误判定条件:在 isError 中不仅检查对象包含 error 属性,还必须验证其值为 true。保持
createError 返回类型保护及其他调用方行为不变,确保带有非布尔或 false 值 error 字段的 Component 不会被识别为错误。
packages/nutui-react-taro-cli/tsup.config.ts (1)

1-4: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

让版本读取相对于配置文件,而不是当前工作目录。

Line 4 的路径由 process.cwd() 解析;若从 monorepo 根目录直接调用 tsup,可能读取根 package.json,导致 __CLI_VERSION__ 注入错误版本。请改为基于 import.meta.url 定位本包的 package.json,或确认 CI/发布脚本始终在该包目录执行。

建议修改
 import { readFileSync } from 'node:fs'
+import { fileURLToPath } from 'node:url'
 import { defineConfig } from 'tsup'

-const { version } = JSON.parse(readFileSync('package.json', 'utf-8'))
+const packageJson = fileURLToPath(new URL('./package.json', import.meta.url))
+const { version } = JSON.parse(readFileSync(packageJson, 'utf-8'))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-taro-cli/tsup.config.ts` around lines 1 - 4, 将 tsup
配置中读取 package.json 的逻辑改为相对于配置文件位置解析,使用 import.meta.url 定位本包的 package.json,避免依赖
process.cwd() 导致从 monorepo 根目录执行时读取错误版本。保持 version 解析及后续 __CLI_VERSION__ 注入行为不变。
scripts/build-meta.mjs (1)

306-309: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

摘要与实际代码不一致:未打印 taro 端缺失 API 表组件列表。

变更说明称"在存在'无 API 表(taro)'组件时打印对应组件列表",但实际代码只对 noApiIds(H5)做了 if (noApiIds.length) console.log(...)noApiTaroIds 仅用于计算 apiTaroComponentCount,从未被打印,H5/taro 两端诊断信息不对称。

♻️ 建议补充 taro 端缺失组件打印,保持两端一致
   if (noApiIds.length) {
     console.log(`   无 API 表(H5)的组件 (${noApiIds.length}): ${noApiIds.join(', ')}`)
   }
+  if (noApiTaroIds.length) {
+    console.log(`   无 API 表(taro)的组件 (${noApiTaroIds.length}): ${noApiTaroIds.join(', ')}`)
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/build-meta.mjs` around lines 306 - 309, 在构建元数据输出逻辑中补充对 noApiTaroIds
的条件打印:参照 noApiIds 的输出方式,当 noApiTaroIds.length 大于零时打印 taro 端缺失 API 表组件数量及组件列表,保持与
H5 端诊断信息一致。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/nutui-react-cli-core/package.json`:
- Around line 1-22: 同步更新 pnpm-lock.yaml 以匹配
packages/nutui-react-cli-core/package.json 中新增的 dependencies 和
devDependencies;在仓库根目录运行非 frozen-lockfile 模式的 pnpm
install,确认生成该包的依赖条目及对应解析版本,并提交更新后的锁文件。

In `@packages/nutui-react-cli-core/scripts/prepare-data.mjs`:
- Around line 21-56: Update regenerateMeta and the shared meta generation flow
to serialize writes to meta/components.json using a temporary output followed by
an atomic rename, preventing concurrent prepare-data executions from
interleaving. In readMeta, distinguish a missing BUILD_META_SCRIPT
(published-package fallback) from an existing script that fails: propagate the
latter error and fail the build even when an old META_PATH exists, while
preserving fallback only for the missing-script case. Verify the nutui-react-cli
and nutui-react-taro-cli prepare-data orchestration does not invoke these
generators concurrently.

In `@packages/nutui-react-cli-core/src/data.ts`:
- Around line 64-70: 在 MCP 调用处校验 params.lang 必须属于 config.langs,并更新 readDoc
以拒绝包含路径分隔符的 lang;同时通过 path.resolve 验证最终文件路径仍位于组件的 docs 目录内,越界时返回 null。

In `@packages/nutui-react-cli-core/src/mcp/tools.ts`:
- Around line 210-247: 在 doc 和 demo 分支中分别对 params.lang 与 params.name
执行服务端白名单校验,不要依赖 inputSchema 的 enum;仅允许配置支持的语言以及 listDemos(config.dataDir, comp)
返回的示例名,校验失败时通过现有 toMcpResult/createError 错误流程返回,并仅在校验通过后调用 readDoc 或
readDemo,确保输入不能用于路径遍历。

In `@packages/nutui-react-cli/package.json`:
- Around line 45-48: 调整 packages/nutui-react-cli 的依赖分区:将 yargs 从 dependencies 移回
devDependencies,并在 devDependencies 中补回 `@modelcontextprotocol/sdk`,确保
tsup.config.ts 的 noExternal 列表中这两个包及 `@nutui/nutui-react-cli-core` 都有显式依赖声明。

In `@packages/nutui-react-taro-cli/package.json`:
- Around line 46-55: 同步更新根目录 pnpm-lock.yaml,使
packages/nutui-react-taro-cli/package.json 中的依赖声明与锁文件 specifier 完全一致。运行 pnpm
install 生成锁文件后,使用 pnpm install --frozen-lockfile 验证安装成功,不要关闭 frozen-lockfile 检查。

In `@packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md`:
- Around line 130-133: Update the --format json documentation to state that it
applies to all query commands and explicitly excludes mcp, which uses MCP stdio
rather than the CLI format parameter. Apply this wording consistently in
packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md lines 130-133,
src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md lines 11-14, and
src/sites/sites-react/doc/docs/ai-taro/cli.md lines 11-14.
- Around line 12-13: 统一固定 CLI 与 Skill 工具版本:在
packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md 的
allowed-tools、Skill 示例和 MCP 配置中使用明确版本,并同步调整命令匹配模式;在
src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md 的 npm/npx 与 skills 示例、以及
src/sites/sites-react/doc/docs/ai-taro/cli.md
的对应示例中使用相同固定版本,确保所有文档和配置保持一致。涉及位置:SKILL.md 12-13、25-32、98-103;cli.en-US.md
20-28、76-80;cli.md 20-28、76-80。

---

Nitpick comments:
In `@packages/nutui-react-cli-core/src/mcp/tools.ts`:
- Around line 46-48: 统一 isError 与 toMcpResult 的错误判定条件:在 isError 中不仅检查对象包含 error
属性,还必须验证其值为 true。保持 createError 返回类型保护及其他调用方行为不变,确保带有非布尔或 false 值 error 字段的
Component 不会被识别为错误。

In `@packages/nutui-react-taro-cli/tsup.config.ts`:
- Around line 1-4: 将 tsup 配置中读取 package.json 的逻辑改为相对于配置文件位置解析,使用 import.meta.url
定位本包的 package.json,避免依赖 process.cwd() 导致从 monorepo 根目录执行时读取错误版本。保持 version 解析及后续
__CLI_VERSION__ 注入行为不变。

In `@scripts/build-meta.mjs`:
- Around line 306-309: 在构建元数据输出逻辑中补充对 noApiTaroIds 的条件打印:参照 noApiIds 的输出方式,当
noApiTaroIds.length 大于零时打印 taro 端缺失 API 表组件数量及组件列表,保持与 H5 端诊断信息一致。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 986bda10-2aee-483d-bfaa-8d72c625f27e

📥 Commits

Reviewing files that changed from the base of the PR and between d6ee5b9 and 9be4316.

📒 Files selected for processing (47)
  • package.json
  • packages/nutui-react-cli-core/.gitignore
  • packages/nutui-react-cli-core/package.json
  • packages/nutui-react-cli-core/scripts/prepare-data.mjs
  • packages/nutui-react-cli-core/src/cli.ts
  • packages/nutui-react-cli-core/src/commands/_shared.ts
  • packages/nutui-react-cli-core/src/commands/demo.ts
  • packages/nutui-react-cli-core/src/commands/doc.ts
  • packages/nutui-react-cli-core/src/commands/info.ts
  • packages/nutui-react-cli-core/src/commands/list.ts
  • packages/nutui-react-cli-core/src/commands/mcp.ts
  • packages/nutui-react-cli-core/src/commands/token.ts
  • packages/nutui-react-cli-core/src/config.ts
  • packages/nutui-react-cli-core/src/data.ts
  • packages/nutui-react-cli-core/src/error.ts
  • packages/nutui-react-cli-core/src/format.ts
  • packages/nutui-react-cli-core/src/index.ts
  • packages/nutui-react-cli-core/src/mcp/prompts.ts
  • packages/nutui-react-cli-core/src/mcp/tools.ts
  • packages/nutui-react-cli-core/src/types.ts
  • packages/nutui-react-cli-core/tsconfig.json
  • packages/nutui-react-cli/package.json
  • packages/nutui-react-cli/scripts/prepare-data.mjs
  • packages/nutui-react-cli/src/cli.ts
  • packages/nutui-react-cli/src/mcp/prompts.ts
  • packages/nutui-react-cli/src/mcp/tools.ts
  • packages/nutui-react-cli/tsup.config.ts
  • packages/nutui-react-taro-cli/.gitignore
  • packages/nutui-react-taro-cli/README.md
  • packages/nutui-react-taro-cli/package.json
  • packages/nutui-react-taro-cli/scripts/prepare-data.mjs
  • packages/nutui-react-taro-cli/skills/.npmignore
  • packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md
  • packages/nutui-react-taro-cli/src/cli.ts
  • packages/nutui-react-taro-cli/tsconfig.json
  • packages/nutui-react-taro-cli/tsup.config.ts
  • pnpm-workspace.yaml
  • scripts/build-meta.mjs
  • scripts/create-properties.js
  • scripts/properties-taro.json
  • scripts/properties.json
  • src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/cli.md
  • src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/for-agents.md
  • src/sites/sites-react/doc/docs/ai-taro/mcp.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/mcp.md
💤 Files with no reviewable changes (2)
  • packages/nutui-react-cli/src/mcp/tools.ts
  • packages/nutui-react-cli/src/mcp/prompts.ts

Comment thread packages/nutui-react-cli-core/package.json
Comment on lines +21 to +56
function regenerateMeta() {
if (!fs.existsSync(BUILD_META_SCRIPT)) {
// 脱离 monorepo(如已发布包被重新 build),无源码可生成,沿用现有快照。
console.log('ℹ️ 未找到 build-meta 脚本,跳过 meta 重生成(沿用现有快照)')
return
}
console.log('🔄 重新生成 meta/components.json(generate:meta)...')
execFileSync(process.execPath, [BUILD_META_SCRIPT], { stdio: 'inherit' })
}

function readMeta() {
try {
regenerateMeta()
} catch (err) {
// meta 生成失败:有旧快照则告警后沿用,否则无从继续。
if (fs.existsSync(META_PATH)) {
console.warn(
`⚠️ meta 重生成失败(${err.message}),沿用现有 ${path.relative(REPO_ROOT, META_PATH)}`
)
} else {
console.error(
`❌ meta 重生成失败且无现有快照:${err.message}\n` +
` 请在仓库根手动执行:npm run generate:meta`
)
process.exit(1)
}
}
if (!fs.existsSync(META_PATH)) {
console.error(
`❌ 未找到 ${path.relative(REPO_ROOT, META_PATH)}。\n` +
` 它是构建产物,请先在仓库根执行:npm run generate:meta`
)
process.exit(1)
}
return JSON.parse(fs.readFileSync(META_PATH, 'utf-8'))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

共享文件 meta/components.json 存在潜在并发写入风险,且失败时静默回退。

regenerateMeta() 会对仓库根共享文件 meta/components.json 执行"子进程重新生成",而该函数会被 nutui-react-clinutui-react-taro-cli 两个叶子包各自的 prepare-data.mjs 分别调用。如果两者的 prepare-data 脚本在 CI/构建流水线中被并行触发(例如通过 pnpm -r --parallel 之类的编排),会出现对同一文件的并发"生成+写入",存在数据损坏(TOCTOU/写入交叉)的风险。

此外,readMeta() 在 monorepo 内 regenerateMeta() 失败但存在旧快照时,只会 console.warn 并继续使用旧快照(Line 36-39),不会让构建失败,这可能掩盖 properties.json / build-meta.mjs 管线中的真实回归,导致 CLI 数据快照静默使用过期数据。

建议:

  1. 为共享的 meta/components.json 写入增加临时文件+原子 rename,或在编排层确保 prepare-data 脚本串行执行,避免并发写入同一文件。
  2. 考虑将"monorepo 内脚本存在但执行失败"与"脱离 monorepo 无脚本"两种场景区分处理:前者应让构建失败(而非仅告警),避免静默使用过期数据。

请确认这两个叶子包的 prepare-data 脚本在实际构建/发布流程中是否存在并行调用的可能。

#!/bin/bash
# 检查是否存在跨包并行调用 prepare-data 的编排脚本
rg -n 'prepare-data' --type=json --type=yaml -g '!node_modules' -C2
rg -nP '"prepare-data"' package.json packages/*/package.json -C2
fd -g 'turbo.json' -x cat {}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-cli-core/scripts/prepare-data.mjs` around lines 21 - 56,
Update regenerateMeta and the shared meta generation flow to serialize writes to
meta/components.json using a temporary output followed by an atomic rename,
preventing concurrent prepare-data executions from interleaving. In readMeta,
distinguish a missing BUILD_META_SCRIPT (published-package fallback) from an
existing script that fails: propagate the latter error and fail the build even
when an old META_PATH exists, while preserving fallback only for the
missing-script case. Verify the nutui-react-cli and nutui-react-taro-cli
prepare-data orchestration does not invoke these generators concurrently.

Comment on lines +64 to 70
export function readDoc(
dataDir: string,
component: Component,
lang: Lang
): string | null {
const file = path.join(dataDir, 'docs', component.id, `${lang}.md`)
return fs.existsSync(file) ? fs.readFileSync(file, 'utf-8') : null

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

限制 lang,避免 MCP 文档读取路径穿越。

Line 69 直接将运行时 lang 拼入路径;MCP 处理器会把未校验的 params.lang 传入这里。../../… 可逃逸组件文档目录并读取可访问的 .md 文件。应在调用处校验其属于 config.langs,并在此处额外拒绝路径分隔符或通过 path.resolve 验证目标仍位于文档目录内。

建议修复
 export function readDoc(
   dataDir: string,
   component: Component,
   lang: Lang
 ): string | null {
+  if (lang.includes('/') || lang.includes('\\') || lang.includes('..')) {
+    return null
+  }
   const file = path.join(dataDir, 'docs', component.id, `${lang}.md`)
   return fs.existsSync(file) ? fs.readFileSync(file, 'utf-8') : null
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function readDoc(
dataDir: string,
component: Component,
lang: Lang
): string | null {
const file = path.join(dataDir, 'docs', component.id, `${lang}.md`)
return fs.existsSync(file) ? fs.readFileSync(file, 'utf-8') : null
export function readDoc(
dataDir: string,
component: Component,
lang: Lang
): string | null {
if (lang.includes('/') || lang.includes('\\') || lang.includes('..')) {
return null
}
const file = path.join(dataDir, 'docs', component.id, `${lang}.md`)
return fs.existsSync(file) ? fs.readFileSync(file, 'utf-8') : null
}
🧰 Tools
🪛 ast-grep (0.45.0)

[warning] 69-69: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.readFileSync(file, 'utf-8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(detect-non-literal-fs-filename-typescript)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-cli-core/src/data.ts` around lines 64 - 70, 在 MCP 调用处校验
params.lang 必须属于 config.langs,并更新 readDoc 以拒绝包含路径分隔符的 lang;同时通过 path.resolve
验证最终文件路径仍位于组件的 docs 目录内,越界时返回 null。

Source: Linters/SAST tools

Comment on lines +210 to +247
case 'doc': {
const comp = resolve(config, meta, params.component as string)
if (isError(comp)) return toMcpResult(comp)
const lang = (params.lang as Lang) ?? config.defaultLang
const content = readDoc(config.dataDir, comp, lang)
if (content === null) {
const langName = config.langLabel[lang] ?? lang
return toMcpResult(
createError(
ErrorCodes.DOC_NOT_FOUND,
`${comp.name} ${comp.cName} 暂无${langName}文档。`
)
)
}
return toMcpResult({ name: comp.name, lang, doc: content })
}

case 'demo': {
const comp = resolve(config, meta, params.component as string)
if (isError(comp)) return toMcpResult(comp)
const demos = listDemos(config.dataDir, comp)
const demoName = params.name as string | undefined
if (!demoName) {
return toMcpResult({ component: comp.name, demos })
}
const code = readDemo(config.dataDir, comp, demoName)
if (code === null) {
return toMcpResult(
createError(
ErrorCodes.DEMO_NOT_FOUND,
`${comp.name} 未找到示例「${demoName}」。`,
demos.length
? `可选:${demos.join(' / ')}`
: `该组件暂无 ${config.demoLabel} 示例。`
)
)
}
return toMcpResult({ component: comp.name, demo: demoName, code })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

langname 未做白名单校验,存在路径遍历读取任意文件的风险。

params.langparams.name 直接透传给 readDoc / readDemo,两者均用 path.join(dataDir, ...) 拼接文件名。inputSchemaenum 只是给客户端的提示,MCP SDK 不会强制校验入参,因此 lang: '../../../../etc/passwd' 之类的值可逃出 dataDir 并把文件内容返回给 Agent。componentresolveComponent 已被白名单化,这两个参数是缺口。

🔒️ 建议的校验修复
       case 'doc': {
         const comp = resolve(config, meta, params.component as string)
         if (isError(comp)) return toMcpResult(comp)
-        const lang = (params.lang as Lang) ?? config.defaultLang
+        const rawLang = (params.lang as string) ?? config.defaultLang
+        if (!config.langs.includes(rawLang)) {
+          return toMcpResult(
+            createError(
+              ErrorCodes.DOC_NOT_FOUND,
+              `不支持的文档语言「${rawLang}」,可选:${config.langs.join(' / ')}。`
+            )
+          )
+        }
+        const lang = rawLang as Lang
         const content = readDoc(config.dataDir, comp, lang)
         const demos = listDemos(config.dataDir, comp)
         const demoName = params.name as string | undefined
         if (!demoName) {
           return toMcpResult({ component: comp.name, demos })
         }
+        if (!demos.includes(demoName)) {
+          return toMcpResult(
+            createError(
+              ErrorCodes.DEMO_NOT_FOUND,
+              `${comp.name} 未找到示例「${demoName}」。`,
+              demos.length
+                ? `可选:${demos.join(' / ')}`
+                : `该组件暂无 ${config.demoLabel} 示例。`
+            )
+          )
+        }
         const code = readDemo(config.dataDir, comp, demoName)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case 'doc': {
const comp = resolve(config, meta, params.component as string)
if (isError(comp)) return toMcpResult(comp)
const lang = (params.lang as Lang) ?? config.defaultLang
const content = readDoc(config.dataDir, comp, lang)
if (content === null) {
const langName = config.langLabel[lang] ?? lang
return toMcpResult(
createError(
ErrorCodes.DOC_NOT_FOUND,
`${comp.name} ${comp.cName} 暂无${langName}文档。`
)
)
}
return toMcpResult({ name: comp.name, lang, doc: content })
}
case 'demo': {
const comp = resolve(config, meta, params.component as string)
if (isError(comp)) return toMcpResult(comp)
const demos = listDemos(config.dataDir, comp)
const demoName = params.name as string | undefined
if (!demoName) {
return toMcpResult({ component: comp.name, demos })
}
const code = readDemo(config.dataDir, comp, demoName)
if (code === null) {
return toMcpResult(
createError(
ErrorCodes.DEMO_NOT_FOUND,
`${comp.name} 未找到示例「${demoName}」。`,
demos.length
? `可选:${demos.join(' / ')}`
: `该组件暂无 ${config.demoLabel} 示例。`
)
)
}
return toMcpResult({ component: comp.name, demo: demoName, code })
case 'doc': {
const comp = resolve(config, meta, params.component as string)
if (isError(comp)) return toMcpResult(comp)
const rawLang = (params.lang as string) ?? config.defaultLang
if (!config.langs.includes(rawLang)) {
return toMcpResult(
createError(
ErrorCodes.DOC_NOT_FOUND,
`不支持的文档语言「${rawLang}」,可选:${config.langs.join(' / ')}。`
)
)
}
const lang = rawLang as Lang
const content = readDoc(config.dataDir, comp, lang)
if (content === null) {
const langName = config.langLabel[lang] ?? lang
return toMcpResult(
createError(
ErrorCodes.DOC_NOT_FOUND,
`${comp.name} ${comp.cName} 暂无${langName}文档。`
)
)
}
return toMcpResult({ name: comp.name, lang, doc: content })
}
case 'demo': {
const comp = resolve(config, meta, params.component as string)
if (isError(comp)) return toMcpResult(comp)
const demos = listDemos(config.dataDir, comp)
const demoName = params.name as string | undefined
if (!demoName) {
return toMcpResult({ component: comp.name, demos })
}
if (!demos.includes(demoName)) {
return toMcpResult(
createError(
ErrorCodes.DEMO_NOT_FOUND,
`${comp.name} 未找到示例「${demoName}」。`,
demos.length
? `可选:${demos.join(' / ')}`
: `该组件暂无 ${config.demoLabel} 示例。`
)
)
}
const code = readDemo(config.dataDir, comp, demoName)
if (code === null) {
return toMcpResult(
createError(
ErrorCodes.DEMO_NOT_FOUND,
`${comp.name} 未找到示例「${demoName}」。`,
demos.length
? `可选:${demos.join(' / ')}`
: `该组件暂无 ${config.demoLabel} 示例。`
)
)
}
return toMcpResult({ component: comp.name, demo: demoName, code })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-cli-core/src/mcp/tools.ts` around lines 210 - 247, 在 doc
和 demo 分支中分别对 params.lang 与 params.name 执行服务端白名单校验,不要依赖 inputSchema 的
enum;仅允许配置支持的语言以及 listDemos(config.dataDir, comp) 返回的示例名,校验失败时通过现有
toMcpResult/createError 错误流程返回,并仅在校验通过后调用 readDoc 或 readDemo,确保输入不能用于路径遍历。

Comment on lines 45 to +48
"yargs": "^17.7.2"
},
"devDependencies": {
"@nutui/nutui-react-cli-core": "workspace:*",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

依赖分区与 noExternal bundle 列表已脱节。

tsup.config.tsyargs@modelcontextprotocol/sdk@nutui/nutui-react-cli-core 全部 noExternal,产物号称自包含:

  • yargs 移入 dependencies 会让终端用户在 npx 时多装一份已被内联的包,与「零安装依赖即可运行」相悖,放回 devDependencies 更一致。
  • @modelcontextprotocol/sdkdevDependencies 移除但仍在 noExternal 中。它现在只能靠 core 包的 node_modules 被解析到;pnpm 严格隔离下这属于隐式依赖,core 一旦调整依赖或安装布局变化,本包构建就会失败。建议保留为本包 devDependencies
#!/bin/bash
# 本包依赖声明现状
fd -t f 'package.json' packages/nutui-react-cli -d 1 | xargs -r jq '{version, dependencies, devDependencies}'

# core 包是否显式声明 sdk 与 yargs
fd -t f 'package.json' packages/nutui-react-cli-core -d 1 | xargs -r jq '{name, private, dependencies, devDependencies, peerDependencies}'

# Taro CLI 包的分区是否与本包一致
fd -t f 'package.json' packages/nutui-react-taro-cli -d 1 | xargs -r jq '{dependencies, devDependencies}'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-cli/package.json` around lines 45 - 48, 调整
packages/nutui-react-cli 的依赖分区:将 yargs 从 dependencies 移回 devDependencies,并在
devDependencies 中补回 `@modelcontextprotocol/sdk`,确保 tsup.config.ts 的 noExternal
列表中这两个包及 `@nutui/nutui-react-cli-core` 都有显式依赖声明。

Comment thread packages/nutui-react-taro-cli/package.json
Comment thread packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md
Comment on lines +130 to +133
## Key Rules

1. **Always query before writing** — Don't guess NutUI Taro APIs, prop names, or enum values from memory. Run `nutui-react-taro info` (and `nutui-react-taro demo` for a working example) first. Taro props can differ from the H5 package.
2. **Use `--format json`** — Every command supports it. Parse the JSON output rather than regex-matching the human-readable text.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

统一修正 --format json 的适用范围。 mcp 命令使用 MCP stdio 协议,不消费 CLI 的 format 参数;因此不应描述为所有命令都输出 CLI JSON。

  • packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md#L130-L133:改为“所有查询命令支持”,并排除 mcp
  • src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md#L11-L14:将 “Every command” 改为查询命令。
  • src/sites/sites-react/doc/docs/ai-taro/cli.md#L11-L14:将“所有命令”改为查询命令。
🧰 Tools
🪛 SkillSpector (2.4.4)

[warning] 13: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[warning] 26: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[warning] 32: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[warning] 1: [RP1] null: MCP server references in the skill manifest without version pinning are a rug-pull risk.

Remediation: Always pin MCP server versions in manifest references.

(MCP Rug Pull (RP1))

📍 Affects 3 files
  • packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md#L130-L133 (this comment)
  • src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md#L11-L14
  • src/sites/sites-react/doc/docs/ai-taro/cli.md#L11-L14
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md` around lines
130 - 133, Update the --format json documentation to state that it applies to
all query commands and explicitly excludes mcp, which uses MCP stdio rather than
the CLI format parameter. Apply this wording consistently in
packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md lines 130-133,
src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md lines 11-14, and
src/sites/sites-react/doc/docs/ai-taro/cli.md lines 11-14.

@xiaoyatong
xiaoyatong merged commit 6efc38c into jdf2e:feat_v4.x Jul 30, 2026
7 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (2)
scripts/build-meta.mjs (1)

306-310: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

noApiTaroIds 只参与计数,未输出明细。 H5 侧会列出缺少 API 表的组件 id,taro 侧同样收集了 noApiTaroIds 却没有打印,排查 Taro 端缺表组件时只能看到一个总数。

🔎 建议补充 taro 侧明细输出
   if (noApiIds.length) {
     console.log(`   无 API 表(H5)的组件 (${noApiIds.length}): ${noApiIds.join(', ')}`)
   }
+  if (noApiTaroIds.length) {
+    console.log(`   无 API 表(taro)的组件 (${noApiTaroIds.length}): ${noApiTaroIds.join(', ')}`)
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/build-meta.mjs` around lines 306 - 310, 在构建元数据的汇总输出中补充 noApiTaroIds
的明细日志:参考 noApiIds 的条件判断和输出格式,当 noApiTaroIds 非空时打印缺少 Taro API 表的组件数量及其 ID 列表,保留现有
H5 输出不变。
packages/nutui-react-cli-core/scripts/prepare-data.mjs (1)

58-65: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

注释与实现不一致。 该函数并未使用 posix basename(basename 由调用方在 demos 分支处理),注释容易误导后续维护者。

📝 建议修正注释
-// meta 里的路径始终是 posix 相对仓库根路径,用 posix 取 basename,再 join 到本地。
+// meta 里的路径始终是 posix 相对仓库根路径,这里按仓库根解析后复制到目标绝对路径。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-cli-core/scripts/prepare-data.mjs` around lines 58 - 65,
更新 copyRepoFile 上方注释,使其准确描述函数当前行为:relPosixPath 作为相对仓库根路径用于拼接源文件路径;移除关于使用 posix
basename 或由该函数执行本地 join 的误导性表述。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/nutui-react-cli-core/src/data.ts`:
- Around line 62-71: 在 readDoc 中先校验 lang 不包含路径分隔符“/”或“\”,发现非法值时直接返回
null,再执行现有的文档路径拼接与读取逻辑;保持合法语言值及文件不存在时的行为不变,并与 readDemo 的防护方式一致。

In `@packages/nutui-react-cli-core/src/mcp/tools.ts`:
- Around line 210-225: 在 MCP 请求处理的 doc 分支中校验
params.lang,仅允许配置支持的语言值,并拒绝包含路径分隔符或其他非法路径片段的输入;校验通过后再调用
readDoc,确保外部输入不会被拼接为任意文件路径。复用 readDemo 的语言白名单校验方式,并保留默认语言处理逻辑。

In `@packages/nutui-react-taro-cli/README.md`:
- Line 106: 将 packages/nutui-react-taro-cli/README.md 第106行的 skills add
命令、src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md 第24行及
src/sites/sites-react/doc/docs/ai-taro/for-agents.md 第24行的相关 npx 命令统一改为带 -y
参数,覆盖 skills add 和 `@nutui/nutui-react-taro-cli` info Button,确保首次执行时保持非交互式。
- Around line 73-86: Update the MCP configuration documentation in
packages/nutui-react-taro-cli/README.md (lines 73-86),
src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md (lines 31-42),
src/sites/sites-react/doc/docs/ai-taro/for-agents.md (lines 29-42),
src/sites/sites-react/doc/docs/ai-taro/mcp.en-US.md (lines 36-47), and
src/sites/sites-react/doc/docs/ai-taro/mcp.md (lines 36-47) to preserve
mcpServers for Claude and Cursor while providing a separate VS Code
.vscode/mcp.json example using the top-level servers field.

In `@packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md`:
- Around line 11-14: 统一锁定 CLI、Skill 和 MCP 使用的 `@nutui/nutui-react-taro-cli`
精确版本,移除“始终使用最新版”等未锁定表述。更新
packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md 的
allowed-tools(11-14)、CLI 示例(23-32)及 MCP args(98-104);更新
src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md(24-28、76-80)和
src/sites/sites-react/doc/docs/ai-taro/cli.md(24-28、76-80),将 npx、npm i -D 及
skills add 命令统一使用同一明确版本。

In `@scripts/properties-taro.json`:
- Around line 3082-3091: 修正源文档 doc.taro.md 中 Form.labelPosition
表格行的反引号与竖线转义,使类型和默认值分别正确解析为 'top' 与 'left';同时将 Row.onClick 的英文说明 “Fired when
clicked” 改为与中文文档一致的描述。完成后重新执行 npm run generate:props:taro 生成
scripts/properties-taro.json,勿直接修改生成文件。

In `@scripts/properties.json`:
- Around line 7615-7621: 修正 doc.md 中 Popup.portal 和 TextArea.status
的类型字符串,移除多余的反引号并保持类型内容准确;随后运行 npm run generate:props,更新由属性文档生成的站点 API 表及
llms/MCP 输出。

In `@src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md`:
- Around line 85-89: Update all four documented MCP links in
src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md lines 85-89 and 91, and
src/sites/sites-react/doc/docs/ai-taro/cli.md lines 85-89 and 91, to preserve
the Taro route context: use /en-US/ai-taro/mcp and /en-US/ai-taro/for-agents in
the English page, and /zh-CN/ai-taro/mcp and /zh-CN/ai-taro/for-agents in the
Chinese page.

---

Nitpick comments:
In `@packages/nutui-react-cli-core/scripts/prepare-data.mjs`:
- Around line 58-65: 更新 copyRepoFile 上方注释,使其准确描述函数当前行为:relPosixPath
作为相对仓库根路径用于拼接源文件路径;移除关于使用 posix basename 或由该函数执行本地 join 的误导性表述。

In `@scripts/build-meta.mjs`:
- Around line 306-310: 在构建元数据的汇总输出中补充 noApiTaroIds 的明细日志:参考 noApiIds
的条件判断和输出格式,当 noApiTaroIds 非空时打印缺少 Taro API 表的组件数量及其 ID 列表,保留现有 H5 输出不变。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 31ed4977-8b71-494c-9cd4-d73e23c1fc2a

📥 Commits

Reviewing files that changed from the base of the PR and between d6ee5b9 and ca92cbb.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (47)
  • package.json
  • packages/nutui-react-cli-core/.gitignore
  • packages/nutui-react-cli-core/package.json
  • packages/nutui-react-cli-core/scripts/prepare-data.mjs
  • packages/nutui-react-cli-core/src/cli.ts
  • packages/nutui-react-cli-core/src/commands/_shared.ts
  • packages/nutui-react-cli-core/src/commands/demo.ts
  • packages/nutui-react-cli-core/src/commands/doc.ts
  • packages/nutui-react-cli-core/src/commands/info.ts
  • packages/nutui-react-cli-core/src/commands/list.ts
  • packages/nutui-react-cli-core/src/commands/mcp.ts
  • packages/nutui-react-cli-core/src/commands/token.ts
  • packages/nutui-react-cli-core/src/config.ts
  • packages/nutui-react-cli-core/src/data.ts
  • packages/nutui-react-cli-core/src/error.ts
  • packages/nutui-react-cli-core/src/format.ts
  • packages/nutui-react-cli-core/src/index.ts
  • packages/nutui-react-cli-core/src/mcp/prompts.ts
  • packages/nutui-react-cli-core/src/mcp/tools.ts
  • packages/nutui-react-cli-core/src/types.ts
  • packages/nutui-react-cli-core/tsconfig.json
  • packages/nutui-react-cli/package.json
  • packages/nutui-react-cli/scripts/prepare-data.mjs
  • packages/nutui-react-cli/src/cli.ts
  • packages/nutui-react-cli/src/mcp/prompts.ts
  • packages/nutui-react-cli/src/mcp/tools.ts
  • packages/nutui-react-cli/tsup.config.ts
  • packages/nutui-react-taro-cli/.gitignore
  • packages/nutui-react-taro-cli/README.md
  • packages/nutui-react-taro-cli/package.json
  • packages/nutui-react-taro-cli/scripts/prepare-data.mjs
  • packages/nutui-react-taro-cli/skills/.npmignore
  • packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md
  • packages/nutui-react-taro-cli/src/cli.ts
  • packages/nutui-react-taro-cli/tsconfig.json
  • packages/nutui-react-taro-cli/tsup.config.ts
  • pnpm-workspace.yaml
  • scripts/build-meta.mjs
  • scripts/create-properties.js
  • scripts/properties-taro.json
  • scripts/properties.json
  • src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/cli.md
  • src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/for-agents.md
  • src/sites/sites-react/doc/docs/ai-taro/mcp.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/mcp.md
💤 Files with no reviewable changes (2)
  • packages/nutui-react-cli/src/mcp/prompts.ts
  • packages/nutui-react-cli/src/mcp/tools.ts

Comment on lines +62 to 71
// 读取组件某语言的文档原文。快照期 prepare-data 已按 <lang>.md 落盘(zh.md / en.md),
// 故此处直接以 lang 寻址,无需 key 映射。缺失(如 Taro 无英文)返回 null。
export function readDoc(
dataDir: string,
component: Component,
lang: Lang
): string | null {
const file = path.join(dataDir, 'docs', component.id, `${lang}.md`)
return fs.existsSync(file) ? fs.readFileSync(file, 'utf-8') : null
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

readDoc 缺少对 lang 的路径穿越防护,存在任意 .md 文件读取风险。

readDoc 直接将 lang 拼进 ${lang}.md 而不做校验,与两个函数之后 readDemoname 的防御处理(拦截 /\\)不一致。CLI 入口通过 yargs choices: config.langs 限制了 --lang 取值,但 MCP doc 工具(mcp/tools.tscreateToolHandler)直接把外部传入的 params.lang 透传给 readDoc,未做任何白名单校验:

const lang = (params.lang as Lang) ?? config.defaultLang
const content = readDoc(config.dataDir, comp, lang)

当 MCP 客户端(或被提示注入操纵的 Agent)传入形如 ../../../../some/pathlang 时,可越出 dataDir/docs/<component.id>/ 目录读取文件系统中任意以 .md 结尾的文件内容并通过工具结果返回。建议直接在 readDoc 内部补上与 readDemo 一致的分隔符校验,一次性覆盖 CLI 与 MCP 两条调用链。

🛡️ 建议修复
 export function readDoc(
   dataDir: string,
   component: Component,
   lang: Lang
 ): string | null {
+  // 防御路径穿越:lang 可能来自 MCP 工具调用的外部输入。
+  if (lang.includes('/') || lang.includes('\\')) {
+    return null
+  }
   const file = path.join(dataDir, 'docs', component.id, `${lang}.md`)
   return fs.existsSync(file) ? fs.readFileSync(file, 'utf-8') : null
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// 读取组件某语言的文档原文。快照期 prepare-data 已按 <lang>.md 落盘(zh.md / en.md),
// 故此处直接以 lang 寻址,无需 key 映射。缺失(如 Taro 无英文)返回 null。
export function readDoc(
dataDir: string,
component: Component,
lang: Lang
): string | null {
const file = path.join(dataDir, 'docs', component.id, `${lang}.md`)
return fs.existsSync(file) ? fs.readFileSync(file, 'utf-8') : null
}
// 读取组件某语言的文档原文。快照期 prepare-data 已按 <lang>.md 落盘(zh.md / en.md),
// 故此处直接以 lang 寻址,无需 key 映射。缺失(如 Taro 无英文)返回 null。
export function readDoc(
dataDir: string,
component: Component,
lang: Lang
): string | null {
// 防御路径穿越:lang 可能来自 MCP 工具调用的外部输入。
if (lang.includes('/') || lang.includes('\\')) {
return null
}
const file = path.join(dataDir, 'docs', component.id, `${lang}.md`)
return fs.existsSync(file) ? fs.readFileSync(file, 'utf-8') : null
}
🧰 Tools
🪛 ast-grep (0.45.0)

[warning] 69-69: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.readFileSync(file, 'utf-8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(detect-non-literal-fs-filename-typescript)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-cli-core/src/data.ts` around lines 62 - 71, 在 readDoc
中先校验 lang 不包含路径分隔符“/”或“\”,发现非法值时直接返回
null,再执行现有的文档路径拼接与读取逻辑;保持合法语言值及文件不存在时的行为不变,并与 readDemo 的防护方式一致。

Comment on lines +210 to +225
case 'doc': {
const comp = resolve(config, meta, params.component as string)
if (isError(comp)) return toMcpResult(comp)
const lang = (params.lang as Lang) ?? config.defaultLang
const content = readDoc(config.dataDir, comp, lang)
if (content === null) {
const langName = config.langLabel[lang] ?? lang
return toMcpResult(
createError(
ErrorCodes.DOC_NOT_FOUND,
`${comp.name} ${comp.cName} 暂无${langName}文档。`
)
)
}
return toMcpResult({ name: comp.name, lang, doc: content })
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
fd -a 'tools\.ts|data\.ts|cli\.ts' . | sed 's#^\./##' | head -100

echo
echo "== relevant snippets =="
if [ -f packages/nutui-react-cli-core/src/mcp/tools.ts ]; then
  echo "--- tools.ts around doc case ---"
  nl -ba packages/nutui-react-cli-core/src/mcp/tools.ts | sed -n '170,240p'
fi

if [ -f packages/nutui-react-cli-core/src/mcp/data.ts ]; then
  echo "--- data.ts readDoc/readDemo snippets ---"
  rg -n "function readDoc|const readDoc|readDoc|function readDemo|const readDemo|readDemo|path\\.join|split|includes|config\\.langs" packages/nutui-react-cli-core/src/mcp/data.ts
  nl -ba packages/nutui-react-cli-core/src/mcp/data.ts | sed -n '1,220p'
fi

if [ -f packages/nutui-react-cli-core/src/cli.ts ]; then
  echo "--- cli.ts lang option ---"
  nl -ba packages/nutui-react-cli-core/src/cli.ts | sed -n '1,220p'
fi

echo
echo "== package/sdk dependency versions if available =="
for f in package.json packages/nutui-react-cli-core/package.json pnpm-lock.yaml package-lock.json yarn.lock; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    rg -n '"`@modelcontextprotocol/sdk`"|version' "$f" | head -80 || true
  fi
done

Repository: jdf2e/nutui-react

Length of output: 575


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== installed tools =="
command -v sed awk grep node python3 || true

echo "== relevant snippets =="
echo "--- tools.ts around doc case ---"
sed -n '170,240p' packages/nutui-react-cli-core/src/mcp/tools.ts | awk '{printf "%5d\t%s\n", NR+169, $0}'

echo "--- data.ts outline/search ---"
grep -nE "readDoc|readDemo|path\\.join|\\.split\\(|include|config\\.langs|existsSync|readFileSync|resolve|basename" packages/nutui-react-cli-core/src/data.ts || true

echo "--- data.ts snippets mentioning readDoc/readDemo and paths ---"
python3 - <<'PY'
from pathlib import Path
p=Path('packages/nutui-react-cli-core/src/data.ts')
lines=p.read_text().splitlines()
for i,l in enumerate(lines,1):
    if 'function readDoc' in l or 'const readDoc' in l or 'function readDemo' in l or 'const readDemo' in l or 'path.join' in l or 'config.langs' in l:
        start=max(1,i-8); end=min(len(lines),i+25)
        print(f'### {p}:{i}')
        for n in range(start,end+1):
            print(f'{n:5d}\t{lines[n-1]}')
        print()
PY

echo "--- cli.ts lang option snippets ---"
grep -nE "lang|choices|option|defaultLang|yargs|doc|nutui" packages/nutui-react-cli-core/src/cli.ts packages/nutui-react-cli/src/cli.ts || true
for f in packages/nutui-react-cli-core/src/cli.ts packages/nutui-react-cli/src/cli.ts packages/nutui-react-taro-cli/src/cli.ts; do
  if [ -f "$f" ]; then
    echo "### $f lang-related"
    sed -n '/lang/,+80p' "$f" | awk '{printf "%5d\t%s\n", NR, $0}'
  fi
done

echo "== package/sdk dependency versions if available =="
for f in package.json packages/nutui-react-cli-core/package.json pnpm-lock.yaml package-lock.json yarn.lock; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    grep -nE '"`@modelcontextprotocol/sdk`"|version' "$f" | head -120 || true
  fi
done

echo "== read-only path traversal probe from data.ts logic =="
python3 - <<'PY'
from pathlib import PurePosixPath, Path
# Model the likely readDoc path construction from data.ts without importing repo code.
data_dir = '/tmp/nutui-docs'
component = type('C', (), {'id':'button', 'name':'button', 'cName':'BTN'})()
lang = '../../../secret'
read_doc_path = str(PurePosixPath(data_dir, 'docs', component.id, f'{lang}.md'))
print(f'data_dir={data_dir} component.id={component.id} lang={lang!r}')
print(f'constructed_path={read_doc_path}')
print(f'normalized_starts_with_data_dir={PurePosixPath(read_doc_path).is_relative_to(data_dir)}')
print(f'substring_contains_conf={read_doc_path.find('docs/nutui.config.json') != -1}')
PY

Repository: jdf2e/nutui-react

Length of output: 23689


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== installed tools =="
command -v sed awk grep node python3 || true

echo "== relevant snippets =="
echo "--- tools.ts around doc case ---"
sed -n '170,240p' packages/nutui-react-cli-core/src/mcp/tools.ts | awk '{printf "%5d\t%s\n", NR+169, $0}'

echo "--- data.ts outline/search ---"
grep -nE "readDoc|readDemo|path\\.join|\\.split\\(|include|config\\.langs|existsSync|readFileSync|resolve|basename" packages/nutui-react-cli-core/src/data.ts || true

echo "--- data.ts snippets mentioning readDoc/readDemo and paths ---"
python3 - <<'PY'
from pathlib import Path
p=Path('packages/nutui-react-cli-core/src/data.ts')
lines=p.read_text().splitlines()
for i,l in enumerate(lines,1):
    if 'function readDoc' in l or 'const readDoc' in l or 'function readDemo' in l or 'const readDemo' in l or 'path.join' in l or 'config.langs' in l:
        start=max(1,i-8); end=min(len(lines),i+25)
        for n in range(start,end+1):
            print(f'{n:5d}\t{lines[n-1]}')
        print()
PY

echo "--- cli.ts lang option snippets ---"
grep -nE "lang|choices|option|defaultLang|yargs|doc|nutui" packages/nutui-react-cli-core/src/cli.ts packages/nutui-react-cli/src/cli.ts || true
for f in packages/nutui-react-cli-core/src/cli.ts packages/nutui-react-cli/src/cli.ts packages/nutui-react-taro-cli/src/cli.ts; do
  if [ -f "$f" ]; then
    echo "### $f lang-related"
    sed -n '/lang/,+80p' "$f" | awk '{printf "%5d\t%s\n", NR, $0}'
  fi
done

echo "== package/sdk dependency versions if available =="
for f in package.json packages/nutui-react-cli-core/package.json pnpm-lock.yaml package-lock.json yarn.lock; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    grep -nE '"`@modelcontextprotocol/sdk`"|version' "$f" | head -120 || true
  fi
done

echo "== read-only path traversal probe from data.ts logic =="
python3 - <<'PY'
from pathlib import PurePosixPath
data_dir = '/tmp/nutui-docs'
component_id = 'button'
for lang in ['zh-CN', '../../../secret', '../docs/nutui.config.json']:
    path = str(PurePosixPath(data_dir, 'docs', component_id, f'{lang}.md'))
    rel_ok = Path(path).is_relative_to(data_dir) if hasattr(PurePosixPath, 'is_relative_to') else Path(path).resolve().parent == Path(data_dir).resolve().parent
    conf_hit = 'docs/nutui.config.json' in path
    print(f'lang={lang!r:24} path={path} relative_to_data={rel_ok} contains_config_path={conf_hit}')
PY

Repository: jdf2e/nutui-react

Length of output: 23293


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== deterministic path traversal probe =="
node - <<'JS'
const path = require('node:path');

const dataDir = '/tmp/nutui-docs';
const component = { id: 'button' };

for (const lang of ['zh', '../../../secret', '../docs/nutui.config.json']) {
  const file = path.join(dataDir, 'docs', component.id, `${lang}.md`);
  console.log(JSON.stringify({ lang, constructedPath: file }));
}
JS

echo
echo "== MCP tools definitions around runCli/server/register call =="
rg -n "buildToolDefinitions|setRequestHandler|CallToolRequestSchema|registerTool|Server|runCli|mcp:" packages/nutui-react-cli-core/src packages/nutui-react-cli/src packages/nutui-react-taro-cli/src || true

Repository: jdf2e/nutui-react

Length of output: 3373


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== deterministic path traversal probe =="
node - <<'JS'
const path = require('node:path');

const dataDir = '/tmp'nutui-docs';
const component = { id: 'button' };

for (const lang of ['zh', '../../../secret', '../docs/nutui.config.json']) {
  const file = path.join(dataDir, 'docs', component.id, `${lang}.md`);
  console.log(JSON.stringify({ lang, constructedPath: file }));
}
JS

echo
echo "== MCP tools definitions around runCli/server/register call =="
rg -n "buildToolDefinitions|setRequestHandler|CallToolRequestSchema|registerTool|Server|runCli|mcp:" packages/nutui-react-cli-core/src packages/nutui-react-cli/src packages/nutui-react-taro-cli/src || true

Repository: jdf2e/nutui-react

Length of output: 824


在 MCP 入口校验 lang,不要让 readDoc 直接凭 path.join 处理外部输入。

doc 工具通过 setRequestHandler(CallToolRequestSchema, ...) 处理请求,工具定义的 enum 只是 Schema 说明;lang 会进入 readDoc,而 readDoc${lang}.md 直接拼接路径,../../../secret 这类输入会构造出 /tmp/secret.md 并读取。CLI 的 yargs choices 不能覆盖 MCP 工具调用路径,需在 handler 或 readDoc 内比照 readDemo 做语言白名单/路径分隔符拦截。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-cli-core/src/mcp/tools.ts` around lines 210 - 225, 在 MCP
请求处理的 doc 分支中校验 params.lang,仅允许配置支持的语言值,并拒绝包含路径分隔符或其他非法路径片段的输入;校验通过后再调用
readDoc,确保外部输入不会被拼接为任意文件路径。复用 readDemo 的语言白名单校验方式,并保留默认语言处理逻辑。

Comment thread packages/nutui-react-taro-cli/README.md

```bash
npm i -D @nutui/nutui-react-taro-cli
npx skills add ./node_modules/@nutui/nutui-react-taro-cli/skills/nutui-react-taro

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

npm npx default behavior prompts before executing package prompt question confirmation --yes

💡 Result:

By default, npx prompts the user for confirmation before installing any package that is not already present in the local project dependencies [1][2]. This safety measure is designed to prevent security issues and user errors resulting from mistyped package names [1][3][2]. When npx triggers this prompt, it pauses execution and requires the user to manually type "yes" to proceed with the installation and execution of the package [4]. To suppress this prompt and automatically allow the installation, you can use the --yes (or -y) flag [1][2]. For example: npx --yes package-name Additionally, the prompt is automatically bypassed in environments where standard input (stdin) is not available, such as in many non-interactive CI/CD pipelines [4]. You can also force this behavior by setting the environment variable npm_config_yes=true [4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
git ls-files | rg '(^|/)README\.md$|for-agents\.(en-US|zh-CN)?\.md$' || true

echo
echo "== command occurrences =="
rg -n "npx (skills add|`@nutui/nutui-react-taro-cli` info Button)|ForAgent|for agents|agent" \
  packages/nutui-react-taro-cli/README.md \
  src/sites/sites-react/doc/docs/ai-taro || true

echo
echo "== relevant doc slices =="
sed -n '96,112p' packages/nutui-react-taro-cli/README.md || true
sed -n '18,30p' src/sites/sites-react/doc/docs/ai-taro/for-agents.md || true
if [ -f src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md ]; then
  sed -n '18,30p' src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md || true
fi

Repository: jdf2e/nutui-react

Length of output: 6683


统一为 Agent 就绪的非交互式 npx 命令。

这些命令面向 Agent 自动化流程,首次执行未缓存的 npm 包时应避免等待安装确认;建议把示例中的 npx skills addnpx @nutui/nutui-react-taro-cli info Button 改为 npx -y ...,并补全相关 for-agents*.md 文件中的同类命令。

📍 Affects 3 files
  • packages/nutui-react-taro-cli/README.md#L106-L106 (this comment)
  • src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md#L24-L24
  • src/sites/sites-react/doc/docs/ai-taro/for-agents.md#L24-L24
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-taro-cli/README.md` at line 106, 将
packages/nutui-react-taro-cli/README.md 第106行的 skills add
命令、src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md 第24行及
src/sites/sites-react/doc/docs/ai-taro/for-agents.md 第24行的相关 npx 命令统一改为带 -y
参数,覆盖 skills add 和 `@nutui/nutui-react-taro-cli` info Button,确保首次执行时保持非交互式。

Comment thread packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md
Comment thread src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 8

🧹 Nitpick comments (2)
scripts/build-meta.mjs (1)

306-310: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

noApiTaroIds 只参与计数,未输出明细。 H5 侧会列出缺少 API 表的组件 id,taro 侧同样收集了 noApiTaroIds 却没有打印,排查 Taro 端缺表组件时只能看到一个总数。

🔎 建议补充 taro 侧明细输出
   if (noApiIds.length) {
     console.log(`   无 API 表(H5)的组件 (${noApiIds.length}): ${noApiIds.join(', ')}`)
   }
+  if (noApiTaroIds.length) {
+    console.log(`   无 API 表(taro)的组件 (${noApiTaroIds.length}): ${noApiTaroIds.join(', ')}`)
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/build-meta.mjs` around lines 306 - 310, 在构建元数据的汇总输出中补充 noApiTaroIds
的明细日志:参考 noApiIds 的条件判断和输出格式,当 noApiTaroIds 非空时打印缺少 Taro API 表的组件数量及其 ID 列表,保留现有
H5 输出不变。
packages/nutui-react-cli-core/scripts/prepare-data.mjs (1)

58-65: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

注释与实现不一致。 该函数并未使用 posix basename(basename 由调用方在 demos 分支处理),注释容易误导后续维护者。

📝 建议修正注释
-// meta 里的路径始终是 posix 相对仓库根路径,用 posix 取 basename,再 join 到本地。
+// meta 里的路径始终是 posix 相对仓库根路径,这里按仓库根解析后复制到目标绝对路径。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nutui-react-cli-core/scripts/prepare-data.mjs` around lines 58 - 65,
更新 copyRepoFile 上方注释,使其准确描述函数当前行为:relPosixPath 作为相对仓库根路径用于拼接源文件路径;移除关于使用 posix
basename 或由该函数执行本地 join 的误导性表述。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/nutui-react-cli-core/src/data.ts`:
- Around line 62-71: 在 readDoc 中先校验 lang 不包含路径分隔符“/”或“\”,发现非法值时直接返回
null,再执行现有的文档路径拼接与读取逻辑;保持合法语言值及文件不存在时的行为不变,并与 readDemo 的防护方式一致。

In `@packages/nutui-react-cli-core/src/mcp/tools.ts`:
- Around line 210-225: 在 MCP 请求处理的 doc 分支中校验
params.lang,仅允许配置支持的语言值,并拒绝包含路径分隔符或其他非法路径片段的输入;校验通过后再调用
readDoc,确保外部输入不会被拼接为任意文件路径。复用 readDemo 的语言白名单校验方式,并保留默认语言处理逻辑。

In `@packages/nutui-react-taro-cli/README.md`:
- Line 106: 将 packages/nutui-react-taro-cli/README.md 第106行的 skills add
命令、src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md 第24行及
src/sites/sites-react/doc/docs/ai-taro/for-agents.md 第24行的相关 npx 命令统一改为带 -y
参数,覆盖 skills add 和 `@nutui/nutui-react-taro-cli` info Button,确保首次执行时保持非交互式。
- Around line 73-86: Update the MCP configuration documentation in
packages/nutui-react-taro-cli/README.md (lines 73-86),
src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md (lines 31-42),
src/sites/sites-react/doc/docs/ai-taro/for-agents.md (lines 29-42),
src/sites/sites-react/doc/docs/ai-taro/mcp.en-US.md (lines 36-47), and
src/sites/sites-react/doc/docs/ai-taro/mcp.md (lines 36-47) to preserve
mcpServers for Claude and Cursor while providing a separate VS Code
.vscode/mcp.json example using the top-level servers field.

In `@packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md`:
- Around line 11-14: 统一锁定 CLI、Skill 和 MCP 使用的 `@nutui/nutui-react-taro-cli`
精确版本,移除“始终使用最新版”等未锁定表述。更新
packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md 的
allowed-tools(11-14)、CLI 示例(23-32)及 MCP args(98-104);更新
src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md(24-28、76-80)和
src/sites/sites-react/doc/docs/ai-taro/cli.md(24-28、76-80),将 npx、npm i -D 及
skills add 命令统一使用同一明确版本。

In `@scripts/properties-taro.json`:
- Around line 3082-3091: 修正源文档 doc.taro.md 中 Form.labelPosition
表格行的反引号与竖线转义,使类型和默认值分别正确解析为 'top' 与 'left';同时将 Row.onClick 的英文说明 “Fired when
clicked” 改为与中文文档一致的描述。完成后重新执行 npm run generate:props:taro 生成
scripts/properties-taro.json,勿直接修改生成文件。

In `@scripts/properties.json`:
- Around line 7615-7621: 修正 doc.md 中 Popup.portal 和 TextArea.status
的类型字符串,移除多余的反引号并保持类型内容准确;随后运行 npm run generate:props,更新由属性文档生成的站点 API 表及
llms/MCP 输出。

In `@src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md`:
- Around line 85-89: Update all four documented MCP links in
src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md lines 85-89 and 91, and
src/sites/sites-react/doc/docs/ai-taro/cli.md lines 85-89 and 91, to preserve
the Taro route context: use /en-US/ai-taro/mcp and /en-US/ai-taro/for-agents in
the English page, and /zh-CN/ai-taro/mcp and /zh-CN/ai-taro/for-agents in the
Chinese page.

---

Nitpick comments:
In `@packages/nutui-react-cli-core/scripts/prepare-data.mjs`:
- Around line 58-65: 更新 copyRepoFile 上方注释,使其准确描述函数当前行为:relPosixPath
作为相对仓库根路径用于拼接源文件路径;移除关于使用 posix basename 或由该函数执行本地 join 的误导性表述。

In `@scripts/build-meta.mjs`:
- Around line 306-310: 在构建元数据的汇总输出中补充 noApiTaroIds 的明细日志:参考 noApiIds
的条件判断和输出格式,当 noApiTaroIds 非空时打印缺少 Taro API 表的组件数量及其 ID 列表,保留现有 H5 输出不变。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 31ed4977-8b71-494c-9cd4-d73e23c1fc2a

📥 Commits

Reviewing files that changed from the base of the PR and between d6ee5b9 and ca92cbb.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (47)
  • package.json
  • packages/nutui-react-cli-core/.gitignore
  • packages/nutui-react-cli-core/package.json
  • packages/nutui-react-cli-core/scripts/prepare-data.mjs
  • packages/nutui-react-cli-core/src/cli.ts
  • packages/nutui-react-cli-core/src/commands/_shared.ts
  • packages/nutui-react-cli-core/src/commands/demo.ts
  • packages/nutui-react-cli-core/src/commands/doc.ts
  • packages/nutui-react-cli-core/src/commands/info.ts
  • packages/nutui-react-cli-core/src/commands/list.ts
  • packages/nutui-react-cli-core/src/commands/mcp.ts
  • packages/nutui-react-cli-core/src/commands/token.ts
  • packages/nutui-react-cli-core/src/config.ts
  • packages/nutui-react-cli-core/src/data.ts
  • packages/nutui-react-cli-core/src/error.ts
  • packages/nutui-react-cli-core/src/format.ts
  • packages/nutui-react-cli-core/src/index.ts
  • packages/nutui-react-cli-core/src/mcp/prompts.ts
  • packages/nutui-react-cli-core/src/mcp/tools.ts
  • packages/nutui-react-cli-core/src/types.ts
  • packages/nutui-react-cli-core/tsconfig.json
  • packages/nutui-react-cli/package.json
  • packages/nutui-react-cli/scripts/prepare-data.mjs
  • packages/nutui-react-cli/src/cli.ts
  • packages/nutui-react-cli/src/mcp/prompts.ts
  • packages/nutui-react-cli/src/mcp/tools.ts
  • packages/nutui-react-cli/tsup.config.ts
  • packages/nutui-react-taro-cli/.gitignore
  • packages/nutui-react-taro-cli/README.md
  • packages/nutui-react-taro-cli/package.json
  • packages/nutui-react-taro-cli/scripts/prepare-data.mjs
  • packages/nutui-react-taro-cli/skills/.npmignore
  • packages/nutui-react-taro-cli/skills/nutui-react-taro/SKILL.md
  • packages/nutui-react-taro-cli/src/cli.ts
  • packages/nutui-react-taro-cli/tsconfig.json
  • packages/nutui-react-taro-cli/tsup.config.ts
  • pnpm-workspace.yaml
  • scripts/build-meta.mjs
  • scripts/create-properties.js
  • scripts/properties-taro.json
  • scripts/properties.json
  • src/sites/sites-react/doc/docs/ai-taro/cli.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/cli.md
  • src/sites/sites-react/doc/docs/ai-taro/for-agents.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/for-agents.md
  • src/sites/sites-react/doc/docs/ai-taro/mcp.en-US.md
  • src/sites/sites-react/doc/docs/ai-taro/mcp.md
💤 Files with no reviewable changes (2)
  • packages/nutui-react-cli/src/mcp/prompts.ts
  • packages/nutui-react-cli/src/mcp/tools.ts
🛑 Comments failed to post (2)
scripts/properties-taro.json (1)

3082-3091: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

生成物暴露了源 doc.taro.md 的表格书写问题。 Form.labelPosition 的类型被解析成 "\\`\\`'top'"、默认值成 "'left'\\",说明源 markdown 该行的反引号/竖线转义有误;这些值会原样进入 apiTaro 并出现在站点 API 表与 CLI/MCP 输出里。另外第 758 行 Row.onClick 的说明为英文 “Fired when clicked”,与中文文档不一致。请修改对应组件的 doc.taro.md 后重新执行 npm run generate:props:taro,而不是直接改本文件。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/properties-taro.json` around lines 3082 - 3091, 修正源文档 doc.taro.md 中
Form.labelPosition 表格行的反引号与竖线转义,使类型和默认值分别正确解析为 'top' 与 'left';同时将 Row.onClick
的英文说明 “Fired when clicked” 改为与中文文档一致的描述。完成后重新执行 npm run generate:props:taro 生成
scripts/properties-taro.json,勿直接修改生成文件。
scripts/properties.json (1)

7615-7621: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Popup.portal 的类型字符串反引号不配对。 "`HTMLElement` | `(() => HTMLElement)` | null`" 末尾多出一个反引号,渲染到站点 API 表与 llms/MCP 输出时会出现残留符号。类似的还有 TextArea.status"`default /\\ error`"(第 5739 行)。请修正对应 doc.md 表格后重跑 npm run generate:props

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/properties.json` around lines 7615 - 7621, 修正 doc.md 中 Popup.portal 和
TextArea.status 的类型字符串,移除多余的反引号并保持类型内容准确;随后运行 npm run
generate:props,更新由属性文档生成的站点 API 表及 llms/MCP 输出。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action:review This PR needs more reviews (less than 2 approvals) size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants