From 563730c755c0f55feba4c2cebae6fa091e05475f Mon Sep 17 00:00:00 2001 From: HIsheR Date: Mon, 26 Oct 2026 11:34:55 +0800 Subject: [PATCH] =?UTF-8?q?iter(g25):=20=E6=96=B0=E5=A2=9E=20ua=20tokens?= =?UTF-8?q?=20=E5=91=BD=E4=BB=A4=E4=B8=8E=20MCP=20get=5Ftokens=20=E5=B7=A5?= =?UTF-8?q?=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ua/backlog.json | 8 ++++ .ua/index.json | 7 ++-- AGENTS.md | 2 +- README.md | 4 +- llms-full.txt | 13 ++++--- llms.txt | 2 +- packages/tools/cli/bin/ua.js | 57 +++++++++++++++++++++++++++-- packages/tools/cli/ua.manifest.json | 18 +++++++-- 8 files changed, 90 insertions(+), 21 deletions(-) diff --git a/.ua/backlog.json b/.ua/backlog.json index 6a484c4..842cfcb 100644 --- a/.ua/backlog.json +++ b/.ua/backlog.json @@ -556,6 +556,14 @@ "acceptance": "list({ items, header, footer, bordered, emptyText, onItemClick }) 渲染条目 avatar/title/description/extra;空数组回落 empty;组件数 38→39 三处计数同步;npm run check 全绿", "status": "done", "notes": "自补:组件补充;items 为空回落 empty,onItemClick 让条目可点击" + }, + { + "id": "g25", + "title": "令牌查询能力:ua tokens + MCP get_tokens", + "motivation": "Agent 与人都得翻 tokens.json 才知道有哪些 --ua-* 变量,容易凭记忆写错名;llms-full 里还把 textMuted 当成变量名(实际是 text-muted)", + "acceptance": "ua tokens 列出全部令牌(颜色带暗色值)、--json 输出数组;MCP 新增 get_tokens 工具;llms-full 令牌名统一 kebab-case;npm run check 全绿", + "status": "open", + "notes": "自补:构建/门禁工具链改进" } ] } diff --git a/.ua/index.json b/.ua/index.json index ac73237..597ca78 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-26T03:33:14.774Z", + "generatedAt": "2026-10-26T03:34:43.829Z", "repoRoot": ".", "packages": [ { @@ -1843,7 +1843,7 @@ "MCP tool 入参 schema" ] }, - "usage": "node packages/tools/cli/bin/ua.js |docs|style|verify|commit-lint|mcp>;仓库内等价于 npm run index / docs / style / verify", + "usage": "node packages/tools/cli/bin/ua.js |docs|tokens|style|verify|commit-lint|mcp>;仓库内等价于 npm run index / docs / style / verify", "conventions": [ "零依赖:只用 node 标准库,Node >= 18", "清单是单一来源:代码注释、文档站、llms-full.txt、MCP 全部从 ua.manifest.json 派生", @@ -1854,8 +1854,9 @@ "steps": [ "装好依赖后先跑 npm run check 确认基线全绿(build → style → typecheck → smoke → index → verify)", "查组件:ua list 看全量,ua info <包名> 看单包 api 与约定", + "查令牌:ua tokens 打印全部 --ua-* 变量(颜色带暗色值),--json 输出结构化数组;写样式前先查,禁止硬编码", "改完清单跑 npm run docs:同时刷新人类文档站与 llms-full.txt(Agent 首选喂料)", - "提交前 npm run check:style 查注释规范,verify 查清单 ↔ 文档 ↔ 演示锚点是否一致", + "在 ~/.workbuddy/mcp.json 注册 ua mcp 后,Agent 可直接调 list_components / get_component / search_components / get_tokens", "在 ~/.workbuddy/mcp.json 注册 ua mcp 后,Agent 可直接调 list_components / get_component / search_components" ], "components": [] diff --git a/AGENTS.md b/AGENTS.md index 3db0a07..4d12de0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -46,7 +46,7 @@ } ``` -可用工具:`list_components` / `get_component` / `search_components`。 +可用工具:`list_components` / `get_component` / `search_components` / `get_tokens`(返回 --ua-* 令牌清单,避免硬编码颜色间距)。 2. **CLI**:`node packages/tools/cli/bin/ua.js list | info | index | docs | style | verify | changelog` diff --git a/README.md b/README.md index 9658dc6..401ed5c 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,8 @@ accordion · alert · avatar · badge · breadcrumb · button · card · checkbo ## Agent 接入 - 静态:`llms.txt`(速览)/ **`llms-full.txt`(全量:逐组件参数 / 回调 / 手把手 / 令牌)** -- 命令行:`node packages/tools/cli/bin/ua.js list | info | docs | verify | mcp` -- MCP:在 `~/.workbuddy/mcp.json` 注册 `ua mcp`,可用 `list_components` / `get_component` / `search_components` +- 命令行:`node packages/tools/cli/bin/ua.js list | info | docs | tokens | verify | mcp` +- MCP:在 `~/.workbuddy/mcp.json` 注册 `ua mcp`,可用 `list_components` / `get_component` / `search_components` / `get_tokens` 规范见 `AGENTS.md`(接入手册)、`ARCHITECTURE.md`(分层与依赖方向)、`CODING.md`(编码规范)、`ITERATION.md`(自动迭代协议)。 diff --git a/llms-full.txt b/llms-full.txt index 23ff5c9..bdd0975 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-26T03:33:14.774Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-26T03:34:43.829Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 @@ -42,9 +42,10 @@ 1. 装好依赖后先跑 npm run check 确认基线全绿(build → style → typecheck → smoke → index → verify) 2. 查组件:ua list 看全量,ua info <包名> 看单包 api 与约定 -3. 改完清单跑 npm run docs:同时刷新人类文档站与 llms-full.txt(Agent 首选喂料) -4. 提交前 npm run check:style 查注释规范,verify 查清单 ↔ 文档 ↔ 演示锚点是否一致 -5. 在 ~/.workbuddy/mcp.json 注册 ua mcp 后,Agent 可直接调 list_components / get_component / search_components +3. 查令牌:ua tokens 打印全部 --ua-* 变量(颜色带暗色值),--json 输出结构化数组;写样式前先查,禁止硬编码 +4. 改完清单跑 npm run docs:同时刷新人类文档站与 llms-full.txt(Agent 首选喂料) +5. 在 ~/.workbuddy/mcp.json 注册 ua mcp 后,Agent 可直接调 list_components / get_component / search_components / get_tokens +6. 在 ~/.workbuddy/mcp.json 注册 ua mcp 后,Agent 可直接调 list_components / get_component / search_components ## @ui-arch/ui(skin-dom)v0.1.0 @@ -1177,7 +1178,7 @@ API 速览: 一行用法: ``` -node packages/tools/cli/bin/ua.js |docs|style|verify|commit-lint|mcp>;仓库内等价于 npm run index / docs / style / verify +node packages/tools/cli/bin/ua.js |docs|tokens|style|verify|commit-lint|mcp>;仓库内等价于 npm run index / docs / style / verify ``` 约定: @@ -1193,7 +1194,7 @@ node packages/tools/cli/bin/ua.js |docs|style|verify|comm - --ua-color-bg: #ffffff(暗色 #101216) - --ua-color-surface: #f6f7f9(暗色 #1a1c22) - --ua-color-text: #1c1e21(暗色 #e7e9ec) -- --ua-color-textMuted: #6b7280(暗色 #888780) +- --ua-color-text-muted: #6b7280(暗色 #888780) - --ua-color-accent: #185fa5(暗色 #378add) - --ua-color-danger: #a32d2d - --ua-color-success: #0f6e56 diff --git a/llms.txt b/llms.txt index b3badc6..d4c6971 100644 --- a/llms.txt +++ b/llms.txt @@ -107,7 +107,7 @@ - ua verify:清单一致性门禁(id 唯一 / exports 对应 / props 必带 n t d / steps≥3 / demo 锚点存在) - ua commit-lint <文件|message>:提交信息门禁(type 枚举 / scope 规则 / subject 中文祈使 ≤50 字符),规范见 COMMITTING.md,违规退出码 1 - ua mcp:零依赖 stdio MCP server,暴露 list_components / get_component / search_components -- 用法: `node packages/tools/cli/bin/ua.js |docs|style|verify|commit-lint|mcp>;仓库内等价于 npm run index / docs / style / verify` +- 用法: `node packages/tools/cli/bin/ua.js |docs|tokens|style|verify|commit-lint|mcp>;仓库内等价于 npm run index / docs / style / verify` - 约定: 零依赖:只用 node 标准库,Node >= 18 - 约定: 清单是单一来源:代码注释、文档站、llms-full.txt、MCP 全部从 ua.manifest.json 派生 - 约定: 门禁只增不改:新增校验必须能被人手复现,报错要指出文件与字段 diff --git a/packages/tools/cli/bin/ua.js b/packages/tools/cli/bin/ua.js index 4bebe16..c31bef5 100644 --- a/packages/tools/cli/bin/ua.js +++ b/packages/tools/cli/bin/ua.js @@ -329,15 +329,16 @@ function renderAgentDocs(index, tokens) { } if (tokens?.color) { lines.push('## 设计令牌(--ua-*)', ''); + const kebab = (s) => s.replace(/[A-Z]/g, (c) => '-' + c.toLowerCase()); // textMuted → text-muted,与 ui.css 实际变量名一致 for (const [k, v] of Object.entries(tokens.color)) { const light = typeof v === 'string' ? v : v.light; const dark = typeof v === 'string' ? v : v.dark; - lines.push(`- --ua-color-${k}: ${light}${dark !== light ? `(暗色 ${dark})` : ''}`); + lines.push(`- --ua-color-${kebab(k)}: ${light}${dark !== light ? `(暗色 ${dark})` : ''}`); } for (const [g, vals] of Object.entries(tokens)) { if (g === 'color' || g === '$schema') continue; lines.push('', `### ${g}`, ''); - for (const [k, v] of Object.entries(vals)) lines.push(`- --ua-${g}-${k}: ${v}`); + for (const [k, v] of Object.entries(vals)) lines.push(`- --ua-${g}-${kebab(k)}: ${v}`); } lines.push(''); } @@ -365,9 +366,44 @@ function cmdDocs() { ); } +// ---- 令牌查询:CLI 与 MCP 共用同一份拍平结果 ---- + +/*** 读取 tokens.json 拍平为 CSS 变量清单(颜色区分亮/暗两态,其余单值;名字统一 kebab-case 与 ui.css 对齐) ***/ +function loadTokenList() { + const p = path.join(ROOT, 'packages', 'design', 'tokens', 'tokens.json'); + if (!fs.existsSync(p)) return []; + const tokens = JSON.parse(fs.readFileSync(p, 'utf8')); + const kebab = (s) => s.replace(/[A-Z]/g, (c) => '-' + c.toLowerCase()); // camelCase 键转 kebab-case + const out = []; + for (const [k, v] of Object.entries(tokens.color ?? {})) { + if (typeof v === 'string') out.push({ cssVar: `--ua-color-${kebab(k)}`, value: v }); + else out.push({ cssVar: `--ua-color-${kebab(k)}`, value: v.light, dark: v.dark }); + } + for (const [group, vals] of Object.entries(tokens)) { + if (group === 'color' || group.startsWith('$')) continue; + for (const [k, v] of Object.entries(vals)) out.push({ cssVar: `--ua-${group}-${kebab(k)}`, value: String(v) }); + } + return out; +} + +/*** ua tokens:打印令牌清单;--json 输出结构化数组供脚本消费 ***/ +function cmdTokens(args) { + const list = loadTokenList(); + if (!list.length) { + console.error('未找到 packages/design/tokens/tokens.json'); + process.exit(1); + } + if (args.includes('--json')) { + console.log(JSON.stringify(list, null, 2)); + return; + } + for (const t of list) console.log(`${t.cssVar.padEnd(26)} ${t.value}${t.dark && t.dark !== t.value ? ' / 暗色 ' + t.dark : ''}`); + console.log(`共 ${list.length} 个令牌`); +} + // ---- 内置 stdio MCP server(JSON-RPC 2.0,按行分帧) ---- -/*** 启动 MCP server:向 Agent 暴露 list / get / search 三个查询工具 ***/ +/*** 启动 MCP server:向 Agent 暴露 list / get / search / tokens 四个查询工具 ***/ function cmdMcp() { if (!fs.existsSync(INDEX_FILE)) cmdIndex(); const { packages } = loadIndex(); @@ -396,6 +432,11 @@ function cmdMcp() { required: ['query'], }, }, + { + name: 'get_tokens', + description: 'Get the --ua-* design token list (cssVar / value / dark), so styles never hardcode colors or spacing', + inputSchema: { type: 'object', properties: {} }, + }, ]; const send = (obj) => process.stdout.write(JSON.stringify(obj) + '\n'); @@ -421,6 +462,11 @@ function cmdMcp() { ) .map((p) => ({ name: p.name, version: p.version, type: p.type, description: p.description })); } + if (name === 'get_tokens') { + const list = loadTokenList(); + if (!list.length) throw new Error('tokens.json not found'); + return list; + } throw new Error(`unknown tool: ${name}`); } @@ -851,6 +897,9 @@ switch (cmd) { case 'changelog': cmdChangelog(args); break; + case 'tokens': + cmdTokens(args); + break; case 'lint-iterations': cmdLintIterations(); break; @@ -858,6 +907,6 @@ switch (cmd) { cmdMcp(); break; default: - console.log('usage: ua |docs|style|verify|commit-lint|lint-iterations|changelog|mcp>'); + console.log('usage: ua |docs|tokens [--json]|style|verify|commit-lint|lint-iterations|changelog|mcp>'); process.exit(cmd ? 1 : 0); } diff --git a/packages/tools/cli/ua.manifest.json b/packages/tools/cli/ua.manifest.json index 4f57d23..7585658 100644 --- a/packages/tools/cli/ua.manifest.json +++ b/packages/tools/cli/ua.manifest.json @@ -2,7 +2,13 @@ "name": "@ui-arch/cli", "type": "tooling", "description": "ua 命令行与 MCP 注册表服务:把各包 ua.manifest.json 汇总成机器可读索引(.ua/index.json)、Agent 全量文档(llms-full.txt)与人类文档站,并提供清单一致性门禁。", - "tags": ["cli", "tooling", "mcp", "docs", "gate"], + "tags": [ + "cli", + "tooling", + "mcp", + "docs", + "gate" + ], "api": { "entry": "bin/ua.js", "exports": [ @@ -15,9 +21,12 @@ "ua commit-lint <文件|message>:提交信息门禁(type 枚举 / scope 规则 / subject 中文祈使 ≤50 字符),规范见 COMMITTING.md,违规退出码 1", "ua mcp:零依赖 stdio MCP server,暴露 list_components / get_component / search_components" ], - "keyTypes": ["ua.manifest.json 清单结构", "MCP tool 入参 schema"] + "keyTypes": [ + "ua.manifest.json 清单结构", + "MCP tool 入参 schema" + ] }, - "usage": "node packages/tools/cli/bin/ua.js |docs|style|verify|commit-lint|mcp>;仓库内等价于 npm run index / docs / style / verify", + "usage": "node packages/tools/cli/bin/ua.js |docs|tokens|style|verify|commit-lint|mcp>;仓库内等价于 npm run index / docs / style / verify", "conventions": [ "零依赖:只用 node 标准库,Node >= 18", "清单是单一来源:代码注释、文档站、llms-full.txt、MCP 全部从 ua.manifest.json 派生", @@ -28,8 +37,9 @@ "steps": [ "装好依赖后先跑 npm run check 确认基线全绿(build → style → typecheck → smoke → index → verify)", "查组件:ua list 看全量,ua info <包名> 看单包 api 与约定", + "查令牌:ua tokens 打印全部 --ua-* 变量(颜色带暗色值),--json 输出结构化数组;写样式前先查,禁止硬编码", "改完清单跑 npm run docs:同时刷新人类文档站与 llms-full.txt(Agent 首选喂料)", - "提交前 npm run check:style 查注释规范,verify 查清单 ↔ 文档 ↔ 演示锚点是否一致", + "在 ~/.workbuddy/mcp.json 注册 ua mcp 后,Agent 可直接调 list_components / get_component / search_components / get_tokens", "在 ~/.workbuddy/mcp.json 注册 ua mcp 后,Agent 可直接调 list_components / get_component / search_components" ], "components": []