
Wxa Skills Eval
- 33 installs
- 169 repo stars
- Updated July 28, 2026
- wechat-miniprogram/ai-mode-skills
Helps with ai & agent building tasks during AI-assisted development.
About
wxa-skills-eval is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- wxa-skills-eval
- AI & Agent Building
- AI-coding skill
Wxa Skills Eval by the numbers
- 33 all-time installs (skills.sh)
- +2 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #8,944 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/wechat-miniprogram/ai-mode-skills --skill wxa-skills-evalAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 33 |
|---|---|
| repo stars | ★ 169 |
| Last updated | July 28, 2026 |
| Repository | wechat-miniprogram/ai-mode-skills ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
wxa-skills-eval
一句话定位:基于开发者声明的 Skill,自动构造真实用户任务,模拟用户与小程序 Agent 多轮对话完成任务,并对全过程进行评测与缺陷归因,输出 HTML 报告 + 可机读 JSON。
何时加载
满足任一条件即应加载:
- 需要评测、调试、定位 wxapp 中 AI Skill(
app.json::agent.skills)的端到端质量 - 希望以"模拟真实用户"的方式回归 Skill 行为,提前发现意图理解、参数抽取、调用链路或最终回复中的缺陷
运行环境
- 已支持 macOS 与 Windows 两个平台(自动按平台适配 DevTools CLI 路径与命令行调用)
- 新版开发者工具(macOS
.pkg/ Windows 安装包)安装后自动注册wechatidecli环境变量,评测工具会优先探测使用,无需手动配置路径 - 旧版开发者工具需通过
DEVTOOLS_ENV_APP_PATH环境变量或--devtools-app-path参数配置安装路径;详见 `references/configuration.md`
核心能力
- 自动构造用户任务:基于开发者在
app.json::agent.skills中声明的 Skill,结合小程序页面与原子能力,自动生成贴近真实场景的用户任务用例 - 模拟用户多轮对话:以模拟用户身份与小程序 Agent 进行多轮交互,期间触发 Skill 完成任务,覆盖意图理解、参数收集、调用执行、结果回复完整链路
- 端到端评测与缺陷归因:自动判定任务是否被正确完成,并将失败原因归因到具体环节(意图、轨迹、Skill 调用、回复等),帮助开发者快速定位 Skill 设计缺陷
- 结果 + 可视化报告:同时产出 HTML 报告(人工查看)与 JSON 数据(CI / 自动化集成)
- 续跑友好:节点产物落盘后再次运行自动跳过;显式
--from <node>可强制从某节点重跑
完整执行流程与节点划分见 `references/pipeline.md`。
快速开始
默认即推荐:本工具默认启动 Web UI 并自动打开浏览器,便于人工查看实时进度、节点产物与报告。除非用户明确说"CI 环境"、"无人值守"、"不要 UI"、"纯命令行",否则一律不要加 --headless。# 【默认推荐】启动 Web UI 并自动打开浏览器,人工可视化查看进度
node wxa-skills-eval/cli/index.js run \
-p /absolute/path/to/miniprogram \
--cases 5
# 【可选】仅启动 Web UI 评测界面(在页面内手动配置参数后发起评测)
node wxa-skills-eval/cli/index.js serve --port 3200
# 【仅 CI 场景使用】headless 模式 — 不启动 Web UI,纯命令行输出
# 仅在以下场景使用:CI/CD 流水线、服务器无桌面环境、用户明确要求不开 UI
# 正常交互场景(包括 AI 助手代跑)请勿加 --headless
node wxa-skills-eval/cli/index.js run --headless \
-p /absolute/path/to/miniprogram \
--cases 5
# 续跑 / 断点续跑(默认同样走 UI 模式)
node wxa-skills-eval/cli/index.js run --resume -p ...
node wxa-skills-eval/cli/index.js run --from eval -p ...关键路径
| 路径 | 用途 |
|---|---|
cli/index.js | CLI 主入口(解析子命令 run / serve) |
.env.example | 环境变量模板(必填项见 `references/configuration.md`) |
data/runs/<runId>/ | 单次评测的产物与元数据(run.json / progress.jsonl / cli_trace.jsonl / 节点产物) |
data/runs/index.json | 评测历史轻量索引(丢了可一键重建:POST /api/eval/history/rebuild) |
CLI 选项简表
| 短选项 | 长选项 | 说明 |
|---|---|---|
-p | --project-path | 小程序项目绝对路径(必填) |
-c | --cases | 每次评测生成的 case 数(默认 1) |
| — | --skills <CSV> | 参与评测的 skill 名(多个用英文逗号分隔,留空 = 评测全部);旧参数 --skill-name 已废弃 |
| — | --from <node[:idx]> | 从指定节点重跑(如 eval 或 gen_intent:1),UI / headless 行为一致 |
| — | --resume | 断点续跑:自动定位最近一次同项目同 skills 的未完成 run,复用已有产物,UI / headless 行为一致 |
| — | --reuse-shared-nodes | 项目与 skill 指纹一致时,复用上次的 shared 节点产物(explore / entity_pool / gen_api_deps 等),可显著加速重复评测;指纹不一致会自动 fallback 全跑 |
| — | --headless | 仅 CI 场景:不启动 Web UI,纯命令行输出;日常交互评测请勿使用,保持默认 UI 模式 |
| — | --port <n> | Web UI 端口(默认 3200) |
| — | --auto-port | 端口被占用时自动选下一个可用端口 |
| — | --devtools-app-path <path> | 微信开发者工具路径(覆盖 .env 配置;新版开发者工具有 wechatidecli 时无需填写) |
| — | --env <path> | 指定 .env 文件路径(默认读项目根目录) |
| — | --custom-testcases <path> | 自定义测试集文件路径(跳过探索/生成,直接评测) |
| — | --api-blacklist <json> | 接口黑名单(JSON 格式 {"skillName":["api1"]},被列入的接口在评测过程中跳过;若某 skill 全部接口都在黑名单中则自动从本次 run 中剔除该 skill;若所有 skill 都被黑名单覆盖则直接 fail-fast) |
自定义评测集(多 skill 支持)
--custom-testcases <path> 与 Web UI「自定义评测集文件」均支持多 skill 评测。
评测集文件格式:
{
"skills": ["traffic-12123-query", "traffic-12123-payment"],
"cases": [
{ "intent": "查询本月交通违章", "checklist": [...] }
]
}skills[]:本次评测涉及的 skill 名(多 skill 时由 orchestrator 在同一 run 内统一调度)- 老格式
skillName: "..."仍兼容,等价于skills: ["..."] - 不写
skills/skillName时由 CLI--skills/ Web UI「参与评测的 Skills」勾选项兜底
skills 解析优先级:CLI/Web 显式传入 > 文件顶层 skills[] > 文件顶层 skillName
测试集回写策略(best-effort,失败不影响主流程):
- 单 skill:执行完成后自动把 case 入库到该 skill 的测试集(沉淀回归用例)
- 多 skill:跳过回写——多 skill 模式下无法判断每条 intent 应归属哪个 skill;若需沉淀请拆成单 skill 文件单独跑
进一步阅读
- `references/pipeline.md` — 13 节点执行顺序、依赖关系、续跑机制
- `references/devtools-adapter.md` — DevTools CLI 接入要点
- `references/configuration.md` —
.env全部环境变量与生效节点 - `references/troubleshooting.md` — 常见报错排查
# wxa-skills-eval 环境变量(完整清单见 references/configuration.md)
# ── 必填:LLM 服务配置 ───────────────────────────────────────────────
WXA_SKILL_EVAL_LLM_BASE_URL=https://api.openai.com/v1
WXA_SKILL_EVAL_LLM_API_KEY=sk-xxxxxxxxxxxxxxxx
WXA_SKILL_EVAL_LLM_MODEL=gpt-4o
# ── 可选:LLM 客户端调优 ─────────────────────────────────────────────
# WXA_SKILL_EVAL_LLM_TIMEOUT=60
# WXA_SKILL_EVAL_LLM_MAX_RETRIES=3
# LLM 全局并发上限(正整数,默认 3)
# WXA_SKILL_EVAL_LLM_CONCURRENCY=3
# LLM 是否使用流式接口(开发者对接的 LLM 仅暴露 stream 接口时启用,1/true 启用,默认 0)
# WXA_SKILL_EVAL_LLM_STREAM=0
# ── 可选:节点行为调优(调小加快调试迭代)───────────────────────────
# gen_trajectory 最大对话轮数
# WXA_SKILL_EVAL_MAX_TRAJECTORY_ROUNDS=12
# explore 每个 skill 生成的探索轨迹条数
# WXA_SKILL_EVAL_EXPLORE_N_TRAJECTORIES=3
# explore 每条轨迹最多工具调用次数(至少 3 才能通过合法性校验)
# WXA_SKILL_EVAL_EXPLORE_MAX_STEPS=10
# ── 可选:DevTools 适配器 ────────────────────────────────────────────
# 新版微信开发者工具(macOS .pkg / Windows 安装包)安装后会注册 wechatidecli 环境变量,
# 评测工具会自动探测该命令并优先使用,无需手动配置路径。
#
# 若未检测到 wechatidecli(旧版开发者工具),则回退到以下手动配置:
# 微信开发者工具安装路径(不配置时按平台默认探测)
# macOS 示例:DEVTOOLS_ENV_APP_PATH=/Applications/wechatwebdevtools.app
# Windows 示例:DEVTOOLS_ENV_APP_PATH=C:\Program Files (x86)\Tencent\微信web开发者工具
# (Windows 也可填 微信开发者工具.exe 文件路径,会自动取所在目录;校验依据是该目录下存在 cli.bat)
# DEVTOOLS_ENV_APP_PATH=/Applications/wechatwebdevtools.app
# DEVTOOLS_ENV_PROJECT_PATH=/absolute/path/to/miniprogram
# DEVTOOLS_ENV_CALL_TOOL_TIMEOUT=25
# DEVTOOLS_ENV_CHAT_TIMEOUT=50
# DEVTOOLS_ENV_LAUNCH_TIMEOUT=15
# DEVTOOLS_ENV_SKIP_AUTO_LAUNCH=1
# 仅本地开发调试用:强制覆盖最终 CLI 路径(优先级最高,会跳过 wechatidecli / appPath 探测)
# 配置错误时会在启动校验阶段立即报错。
# DEVTOOLS_CLI_OVERRIDE=/path/to/your/cli
# ── 调试 ─────────────────────────────────────────────────────────────
# WXA_SKILL_EVAL_DEBUG=1
{
"version": "0.1.18",
"build_time": "2026-06-11T08:52:49.486Z"
}
Changelog
本文件记录 wxa-skills-eval 对外发布的版本变更。 遵循 Keep a Changelog 规范,版本号遵循 SemVer。
[0.1.18] - 2026-06-11
✨ 新增
- 对外报告简化:报告结构精简,去掉文档质量板块,卡片直接展示
- Skill 校验:新增校验
app.json中agent.skills[].description必须存在且非空 - 自定义 LLM 请求头:支持传入自定义 LLM 请求 header
- 用例多样性提升:
gen_intent倾向于使用不同 entity,生成的用例覆盖更广
♻️ 优化
- 流程重构:LLM 请求全面并行化,评测速度大幅提升
🐛 修复
- LLM 输出不规范 JSON 导致解析失败
- LLM 超时走到全局 abort 被误判为"手动停止"
[0.1.17] - 2026-06-02
✨ 新增
- 新版开发者工具自动探测:安装新版微信开发者工具后会自动注册
wechatidecli环境变量,评测工具优先探测使用,无需再手动配置DEVTOOLS_ENV_APP_PATH或--devtools-app-path
♻️ 优化
- 评测对话生成 prompt 优化:精简
gen_trajectory阶段的上下文,提升归因、评测、explore、gen_intent等阶段的 KVCache 命中率,整体缩短 prompt 长度与评测耗时 - 评测结果产物瘦身:显著降低单次评测结果的磁盘体积
- 报告 UI 优化
🐛 修复
- 自定义评测集带
checklist时,checklist 未生效
[0.1.16] - 2026-05-27
♻️ 优化
- 优化测试用例生成策略,过滤掉不合理、无法完成的任务
- 实体探索阶段按接口依赖关系筛选候选接口,减少探索失败率
- 完善黑名单接口的屏蔽逻辑,确保敏感接口不会被误调用
🐛 修复
- 修复模型输出中文引号(如 "" '')导致 JSON 解析失败的问题
[0.1.15] - 2026-05-26
🐛 修复
- 修复 Windows 下 PowerShell 在 WebUI 选择文件夹失效问题
- 修复 Windows 对开发者工具 CLI 输出流中文乱码异常
- 修复评测过程中 LLM 输出不合法 JSON 问题
[0.1.14] - 2026-05-25
✨ 新增
- 取消 intent 长度限制与评测用例数量上限,支持更大规模的评测任务
🐛 修复
- 修复 explore 阶段的成功判定逻辑:只要有一条 trace 成功即视为通过
- 修复 win32 平台下 CLI 路径异常问题
[0.1.13] - 2026-05-22
✨ 新增
- 支持自定义评测集
- 支持评测接口黑名单(评测过程不去调用该接口,一般为敏感接口,如删除、退登等)
- 支持多 skills 协同评测,会生成跨 skills 协同完成任务的用例
📝 文档
- 修正
skill/references/pipeline.md:节点数 13 → 12,移除幻觉summary节点 skill/SKILL.md同步节点数描述与 runs 产物说明(补cli_trace.jsonl),frontmatterversion升至 0.1.13ARCHITECTURE.md修正progress.js描述(去 monkey-patch 误导),params字段补skills[]
[0.1.12] - 2026-05-21
✨ 新增
- 新增接口黑名单:可通过 Web UI 勾选或 CLI
--api-blacklist传入,评测过程中跳过指定接口;某 skill 全部接口被勾选时自动跳过该 skill 评测 - 进度页区分不同 skill:多 skill 评测时按 skill 分组展示节点进度,标题栏与步骤名附加
Skill X/Y计数与 skill 名称 - 支持传入自定义测试集(
--custom-testcases),跳过探索/生成阶段直接使用文件中的 intent 评测
[0.1.11] - 2026-05-20
♻️ 优化
- 优化评测 explore 阶段的耗时
🐛 修复
- 修复 intent 阶段错误导致的耗时异常
[0.1.10] - 2026-05-19
♻️ 优化
- 减少整体评测的 token 消耗
📝 文档
- 优化 Skill 文档:精简文档,聚焦使用者视角的前置准备、配置与排错
[0.1.9] - 2026-05-14
✨ 新增
- 增加对原子组件深色模式适配评测
- 支持评测 LLM 配置流式接口
{
"name": "wxa-skills-eval",
"version": "0.1.18",
"description": "小程序 Skill 评测工具",
"private": true,
"bin": {
"wxa-skills-eval": "./cli/index.js"
},
"engines": {
"node": ">=18.17"
}
}
Configuration — 环境变量与配置完全清单
1. LLM 服务配置(必填)
| 变量 | 必填 | 默认值 | 生效节点 / 模块 | 说明 |
|---|---|---|---|---|
WXA_SKILL_EVAL_LLM_BASE_URL | ✅ | — | core/llm/client.js(所有 LLM 节点) | OpenAI 兼容 API 的 BaseURL |
WXA_SKILL_EVAL_LLM_API_KEY | ✅ | — | 同上 | API 鉴权密钥 |
WXA_SKILL_EVAL_LLM_MODEL | ✅ | — | 同上 | 默认模型名(如 gpt-4o) |
2. LLM 客户端调优(可选)
| 变量 | 必填 | 默认值 | 生效节点 / 模块 | 说明 |
|---|---|---|---|---|
WXA_SKILL_EVAL_LLM_TIMEOUT | ❌ | 60 | core/llm/client.js | 单次请求超时(秒) |
WXA_SKILL_EVAL_LLM_MAX_RETRIES | ❌ | 3 | 同上 | 失败重试次数 |
WXA_SKILL_EVAL_LLM_CONCURRENCY | ❌ | 3 | core/llm/scheduler.js | LLM 全局并发上限;设为 1 等价串行 |
WXA_SKILL_EVAL_LLM_STREAM | ❌ | 0 | core/llm/client.js | 是否启用流式(SSE)调用,合法值:1/true 启用,0/false/未设置 关闭 |
3. 节点行为调优(可选)
| 变量 | 必填 | 默认值 | 生效节点 | 说明 |
|---|---|---|---|---|
WXA_SKILL_EVAL_MAX_TRAJECTORY_ROUNDS | ❌ | 12 | gen_trajectory | 单次生成的最大对话轮数 |
WXA_SKILL_EVAL_MAX_DISPATCH_PER_CASE | ❌ | 6 | gen_trajectory | 单 case 内允许的 dispatch 调用次数上限(防止模型反复调用工具) |
WXA_SKILL_EVAL_MAX_MDP_STEPS | ❌ | 8 | gen_trajectory | 单条轨迹的最大 MDP 步数,超出后强制终止 |
WXA_SKILL_EVAL_EXPLORE_N_TRAJECTORIES | ❌ | 3 | explore | 每个 skill 探索的轨迹条数 |
WXA_SKILL_EVAL_EXPLORE_MAX_STEPS | ❌ | 10 | explore | 每条探索轨迹的最大工具调用次数(≥3 才能通过校验) |
WXA_SKILL_EVAL_EXPANDED_GATING | ❌ | unset | gen_intent | 设为 off 关闭"raw-only 桶屏蔽 expanded 实体"的分流策略 |
WXA_SKILL_EVAL_EXPANDED_RATIO | ❌ | 30 | gen_intent | expanded 实体在采样中的占比(0–100,超出范围回退到 30) |
WXA_SKILL_EVAL_SEED_SAMPLING | ❌ | unset | gen_intent | seed 覆盖采样模式开关(具体取值见节点注释) |
WXA_SKILL_EVAL_ENTITY_BLACKLIST | ❌ | unset | gen_intent | 跨 case 已用实体软黑名单;设为 off 关闭 |
这些参数用于在调试期减少 LLM 消耗、加速迭代。生产评测建议保留默认。
4. DevTools 适配器(可选)
新版自动探测:新版微信开发者工具(macOS.pkg/ Windows 安装包)安装后会注册系统命令wechatidecli,评测工具启动时会自动通过which(macOS)/where(Windows)探测该命令。探测成功时无需手动配置DEVTOOLS_ENV_APP_PATH。以下环境变量仅在未安装新版开发者工具或需要手动覆盖时使用。
| 变量 | 必填 | 默认值 | 生效节点 | 说明 |
|---|---|---|---|---|
DEVTOOLS_ENV_APP_PATH | ❌ | 平台默认安装路径 | start / explore / gen_trajectory | 微信开发者工具安装路径。校验依据:该路径下能找到 cli(mac)或 cli.bat(Windows)。完整探测优先级见下方"CLI 路径探测优先级" |
DEVTOOLS_ENV_PROJECT_PATH | ⚠️ 二选一 | — | 同上 | 小程序项目绝对路径。与 CLI `-p / --project-path` 二选一必填:CLI 显式传入时优先;Web UI 仅将此变量作为表单初值预填(其次回退到上次评测历史),最终以用户提交的表单值为准 |
DEVTOOLS_ENV_CALL_TOOL_TIMEOUT | ❌ | 25 | 同上 | callTool 外层进程超时(秒);CLI 内层 --timeout = 该值 - 5s |
DEVTOOLS_ENV_CHAT_TIMEOUT | ❌ | 50 | 同上 | chat 外层进程超时(秒);CLI 内层 --timeout = 该值 - 5s |
DEVTOOLS_ENV_LAUNCH_TIMEOUT | ❌ | 15 | 同上 | auto 子进程端口就绪等待超时(秒) |
DEVTOOLS_ENV_SKIP_AUTO_LAUNCH | ❌ | unset | 同上 | 设为 1 跳过自动启动开发者工具(已自行打开时使用) |
CLI 路径探测优先级
| 优先级 | 来源 | 说明 |
|---|---|---|
| 1(最高) | DEVTOOLS_CLI_OVERRIDE 环境变量 | 直接覆盖最终 CLI 路径,仅用于本地开发调试。会做存在性 + 可执行权限校验(不跑 smoke test),配错路径在适配器首次取 CLI 时立即报错 |
| 2 | wechatidecli 系统命令 | 新版开发者工具注册的环境变量命令,自动探测 |
| 3 | --devtools-app-path / DEVTOOLS_ENV_APP_PATH | 用户手动配置的安装路径(兜底) |
| 4(最低) | 平台默认路径探测 | macOS: /Applications/wechatwebdevtools.app;Windows: 两个候选目录 |
DEVTOOLS_ENV_APP_PATH 各平台写法
| 平台 | 应填 | 探测顺序(未配置时) |
|---|---|---|
| macOS | .app 路径,例:/Applications/wechatwebdevtools.app | wechatidecli → 固定默认 /Applications/wechatwebdevtools.app |
| Windows | 安装目录(推荐),例:C:\Program Files (x86)\Tencent\微信web开发者工具;也可填 微信开发者工具.exe 文件路径(会自动取所在目录) | wechatidecli → 依次探测:C:\Program Files (x86)\Tencent\微信web开发者工具 → C:\Program Files\Tencent\微信web开发者工具 |
Windows 校验要求该路径下存在cli.bat;macOS 校验要求Contents/MacOS/cli存在且可执行。新版开发者工具用户无需关心这些细节,wechatidecli命令会自动被探测使用。
5. 调试
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
WXA_SKILL_EVAL_DEBUG | ❌ | unset | 设为 1 输出更详细的运行时日志 |
6. 配置加载顺序
1. process.env (shell/CI 已设置,优先级最高)
2. 产物根 wxa-skills-eval/.env (skill 标准位置)
3. process.cwd()/.env (在任意目录运行时的兑底)dotenv不会覆盖已存在的process.env。CI 环境中通过 secrets 注入 env 即可,无需写.env文件。
DevTools 接入 — 微信开发者工具准备与排错
本 Skill 通过 微信开发者工具 CLI 驱动小程序运行;以下两节帮你确保环境就绪、出错能快速定位。
1. 前置准备(必读)
| 项 | 要求 |
|---|---|
| 微信开发者工具 | 已安装。推荐使用新版(macOS .pkg / Windows 安装包),安装后自动注册 wechatidecli 环境变量,无需手动配置路径。旧版需配置 DEVTOOLS_ENV_APP_PATH(macOS 默认 /Applications/wechatwebdevtools.app;自定义路径需手动设置) |
| 服务端口 | 开发者工具 → 设置 → 安全 → 开启"服务端口" (必须,否则 `start` 节点直接失败) |
| 项目路径 | 绝对路径,且目录中同时存在 app.json 与 mcp.json |
| 首次连接 | 弹窗中点击"信任并打开"完成授权 |
工具路径、各类超时等可在 .env 中调整,详见 `configuration.md` 第 4 节。评测过程中,开发者工具会在整轮评测内复用同一个进程(不会每个 case 反复冷启动);仅explore与gen_trajectory节点会真正发起 DevTools 调用,其它节点仅依赖 LLM。
2. 出错排查
每次评测会在 data/runs/<runId>/cli_trace.jsonl 留下完整 CLI 调用现场(含 stdout / stderr / 耗时 / 错误信息)。
首选自查:
# 查看本次评测中所有失败的 CLI 调用
grep '"success":false' data/runs/<runId>/cli_trace.jsonl | jq .更多排错场景(端口未开、信任弹窗、超时、partial 升级等)见 `troubleshooting.md` 第 2 / 第 7 节。
Pipeline — 13 节点串行管线
1. 节点执行顺序
执行顺序严格遵循 NODE_ORDER:
| # | 节点 | 类型 | 职责 |
|---|---|---|---|
| 1 | start | per-skill | DevTools 连接、项目解析、源文件指纹采集 |
| 2 | component_check | per-skill | 检查原子组件深色模式适配(wxss + js 双条件,纯规则) |
| 3 | gen_api_deps | per-skill | 分析 mcp.json API 依赖关系 |
| 4 | explore | per-skill | LLM 驱动页面探索,产出 traces |
| 5 | entity_pool | per-skill | 从 traces 中收割原始实体并清洗、生成 intent_seeds |
| 6 | skill_review | per-skill | LLM 审查 skill 定义合理性 |
| 7 | gen_intent | per-case | 由 intent_seed 生成具体测试意图(K 次执行间复用) |
| 8 | gen_checklist | per-case | 基于 intent 生成评估 checklist(K 次执行间复用) |
| 9 | gen_trajectory | per-case + per-attempt | LLM 多轮对话产生工具调用轨迹(K 次独立采样,每次独占 DevTools) |
| 10 | eval | per-case + per-attempt | 用 checklist 对 attempt N 的 trajectory 打分 |
| 11 | attribution | per-case + per-attempt | attempt N 的失败归因(结合所有上游产物) |
| 12 | pass_k | per-case | 收集该 case 全部 K 个 attempt 的 eval 结果,输出 pass@k(K=1 也运行) |
| 13 | gen_report | aggregate | 聚合所有 skill × case 产物,输出 HTML 报告 |
流程概览:所有 skill 合并的 run 上跑一次前 6 个 per-skill 节点 → 再为每个 case 跑后 7 个 per-case 节点(其中gen_trajectory/eval/attribution跑 K 次)→ 最后gen_report聚合输出整体报告。
>
attempt 个数 K 由宿主通过 runOrchestrator({ passAtK }) 透传,默认 1。2. workdir 目录布局
<workdir>/
├── eval_report.html ← 最终 HTML 报告(gen_report 产物)
├── llm.json ← LLM 调用统计(gen_report 产物)
├── timing.json ← 节点耗时统计(gen_report 产物)
├── summary.json ← 评测整体摘要(gen_report 产物)
├── start.json / component_check.json / gen_api_deps.json / explore.json / entity_pool.json / skill_review.json ← run 级共享产物
└── cases/<idx>/
├── gen_intent.json / gen_checklist.json / pass_k.json ← per-case 节点产物
└── attempts/<n>/
└── gen_trajectory.json / eval.json / attribution.json ← per-attempt 节点产物(K=1 时 n=1)旧布局(<workdir>/skills/<skill>/...)在开启 multi-skill 后已废弃;老 workdir 续跑会报错,需重新冷启。3. 续跑机制
三种触发方式:
| 入口 | 行为 |
|---|---|
| 隐式跳过(默认) | 检测到产物文件存在且 schema 校验通过即跳过;输出 ♻️ <node> (已复用) |
| `--resume` | 扫描 run 内所有 case,定位首个未完成节点,从该处重启 |
| `--from <node>` | 强制从指定节点重跑(包含其下游),用于修改某节点逻辑后重新评测 |
跳过条件:产物文件存在 ∧ JSON 可解析 ∧ 字段 schema 通过。任一不满足即标记为未完成、需重跑。
Troubleshooting — 常见报错排查
当评测中出现异常时,先在本文档检索关键字;命中即按步骤排查,否则再读对应节点源码。
1. 检测到旧版 workdir 布局:<workdir>/skills/
含义:multi-skill 联合评测改造后,产物废弃了 per-skill 子目录,所有共享产物落在 workdir 根、per-case 产物落在 <workdir>/cases/<idx>/ 下。若检测到 <workdir>/skills/ 目录存在,表示该 workdir 是旧版本产物、不可续跑。
排查:
1. 检查 <workdir>/skills/ 是否存在 —— 若存在即为旧布局。 2. 解决方案:
- 推荐:新建空 workdir 重跑。
- 或手工合并 per-skill 子目录下产物到 workdir 根,并合并
cases/后再续跑(不推荐,指纹也不一致)。
3. 该机制防止老产物与新逻辑静默冲突造成 silent corruption。
2. DevTools 连接失败 / 连接微信开发者工具失败
典型表现:
start节点报错;进度卡在[1/N] ▶ start- 日志含
connect ECONNREFUSED或服务端口未开启
排查清单:
| 检查项 | 操作 |
|---|---|
| 是否安装新版开发者工具 | 新版安装后自动注册 wechatidecli 环境变量,终端执行 wechatidecli 可验证(macOS 用 which wechatidecli,Windows 用 where wechatidecli) |
开发者工具是否已安装且在 DEVTOOLS_ENV_APP_PATH 路径 | 若未安装新版,macOS 默认 /Applications/wechatwebdevtools.app;若安装在自定义路径,必须配置该环境变量 |
| 服务端口是否开启 | 开发者工具 → 设置 → 安全 → 勾选"服务端口" |
| 是否自动启动失败 | 手动打开开发者工具后,配置 DEVTOOLS_ENV_SKIP_AUTO_LAUNCH=1 跳过自动启动 |
| 项目路径是否绝对 | -p 参数必须是绝对路径,且目录中含 app.json 与 mcp.json |
| 是否信任了项目 | 首次连接时弹窗会要求"信任并打开",须人工确认 |
| 是否被防火墙拦截 | macOS 系统设置 → 网络 → 防火墙,确认未阻止 wechatwebdevtools |
3. LLM 鉴权失败 / 401 Unauthorized / Invalid API Key
排查:
1. 确认 .env 中三项都已填:WXA_SKILL_EVAL_LLM_BASE_URL、WXA_SKILL_EVAL_LLM_API_KEY、WXA_SKILL_EVAL_LLM_MODEL。 2. 用 curl 直接打目标 BaseURL 的 /v1/models,验证 key 在该网关下有效。 3. 公司内网网关常常要求 BaseURL 包含完整路径(如 https://gateway/v1),不要漏掉 /v1。 4. 若使用 OpenAI 官方,确认所选模型名(WXA_SKILL_EVAL_LLM_MODEL)账号有权限访问。 5. 端口/网关需要代理时,按目标 SDK 文档设置 HTTPS_PROXY,不要在源码里硬编码。
4. 节点输出 schema 校验失败 / [<node>] schema 校验失败
典型表现:续跑时打印 ⚠ 节点 X 输出无效,将被重跑;或依赖加载抛错。
排查:
1. 找到该 <node> 对应的产物 JSON 文件(路径见 `pipeline.md` 第 4 节)。 2. 手动检查产物的必填字段是否缺失或类型错误。 3. 删除该文件让节点重跑,或用 --from <node> 强制从该节点重启。
5. 节点跳过却找不到产物 / 续跑没复用
症状:上次明明跑过 explore,再次运行却没看到 ♻️ explore (已复用)。
排查:
1. 复用条件三关:产物文件存在 ∧ JSON 可解析 ∧ 字段完整。任意一关失败都不会复用。 2. 检查共享产物是否在 <workdir>/explore.json(run 级);per-case 产物是否在 <workdir>/cases/<idx>/<file>.json。 3. 若 schema 升级后老产物不兼容,可手工删除对应产物后重跑。
6. 端口 3200 被占用
行为:UI 模式默认端口 3200;若被占用会复用已有 server 实例(同一台机上运行第二个 run 时常见)。
手动指定端口:run --port 3201 或 serve --port 3201。
排查占用者(启动 server 失败时默认会按平台提示):
| 平台 | 查看占用 | 终止进程 |
|---|---|---|
| macOS / Linux | lsof -nP -iTCP:3200 -sTCP:LISTEN | kill -9 <pid> |
| Windows | `netstat -ano | findstr :3200` |
7. DevTools CLI 调用问题排查(首选 cli_trace.jsonl)
含义:gen_trajectory / explore 节点执行慢、超时、报错时,第一现场不是节点产物,而是 DevTools adapter 落盘的 CLI 调用 trace:
data/runs/<runId>/cli_trace.jsonl每行一条 JSON,记录一次 callTool / chat / 控制信令的完整调用现场(含 stdout / stderr / exitCode / durationMs)。
排查清单:
| 症状 | 排查命令 |
|---|---|
| 某次 chat 卡住超时 | jq 'select(.type=="chat" and .success==false)' .../cli_trace.jsonl 看 error / partial / peekSummary |
| 怀疑 CLI 内部超时 | `jq 'select(.killedByTimeout==true or (.error |
| 想看 tool 调用的耗时分布 | `jq -s 'group_by(.name) |
| chat partial 但 agent 实际完成 | jq 'select(.recoveredFromTimeout==true)' .../cli_trace.jsonl 确认是否被升级为 success |
| fatal 终止评测 | jq 'select(.fatal==true)' .../cli_trace.jsonl 看终止前最后一条记录 |
注意事项:
- 该文件完整保留 stdout/stderr 不截断;长会话单文件可能上百 MB,排查后可手动清理
cli_trace.jsonl只记 adapter 与 CLI 之间的调用,不替代progress.jsonl(节点级进度)和eval_report.html(评测结论)
8. Windows 平台常见问题
8.1 找不到 cli.bat / 该路径不是有效的微信开发者工具安装目录(wechatidecli 未注册时的兜底分支)
原因:系统未检测到 wechatidecli 环境变量命令,且 DEVTOOLS_ENV_APP_PATH 未配置或配置了错误路径,默认探测也失败。
排查与修复:
1. 推荐方案:升级到新版微信开发者工具(安装后自动注册 wechatidecli 环境变量),升级后无需手动配置路径。验证:在终端执行 where wechatidecli,有输出即为成功。 2. 若无法升级,确认微信开发者工具本地安装目录(常见位置):
C:\Program Files (x86)\Tencent\微信web开发者工具C:\Program Files\Tencent\微信web开发者工具
3. 在该目录下确认 cli.bat 文件存在。 4. 在 .env 或 shell 环境变量中设置:
DEVTOOLS_ENV_APP_PATH=C:\Program Files (x86)\Tencent\微信web开发者工具也可填 微信开发者工具.exe 文件路径(会自动取所在目录)。
8.2 PowerShell 选择目录失败 / 弹窗不弹出
现象:Web UI 中点击“选择目录”强迫退出或提示脚本被禁。
原因:企业域环境下 PowerShell 默认执行策略为 Restricted / AllSigned,拒绝运行未签名的内联脚本。
排查与修复:
1. 本工具调用 PowerShell 时已默认传入 -ExecutionPolicy Bypass,一般不受全局策略影响。 2. 仍遇拦截时,可手动运行验证:
powershell -NoProfile -ExecutionPolicy Bypass -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('ok')"若仍报 无法加载 类错误,请联系 IT 放开 PowerShell 脚本权限,或手动在 Web UI 表单中填入项目路径。 3. 中文路径乱码:本工具已在脚本首行设置 [Console]::OutputEncoding = UTF8;若本地 PowerShell 版本过低(< 5.1)可能仍会乱码,升级 PowerShell 后重试。
8.3 端口被占用(Windows 版)
netstat -ano | findstr :3200
taskkill /PID <pid> /F作为参考:netstat -ano 最后一列即为进程 PID;taskkill 需加 /F 强制终止。
.slide-down-enter-active[data-v-23b78fc3],.slide-down-leave-active[data-v-23b78fc3]{transition:transform .3s ease,opacity .3s ease,max-height .3s ease;overflow:hidden}.slide-down-enter-from[data-v-23b78fc3],.slide-down-leave-to[data-v-23b78fc3]{transform:translateY(-100%);opacity:0;max-height:0}.slide-down-enter-to[data-v-23b78fc3],.slide-down-leave-from[data-v-23b78fc3]{max-height:60px}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Montserrat,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--background: 210 20% 98%;--foreground: 222 47% 11%;--card: 0 0% 100%;--card-foreground: 222 47% 11%;--primary: 239 84% 67%;--primary-foreground: 0 0% 100%;--muted: 215 16% 47%;--border: 214 32% 91%;--ring: 239 84% 67%}.dark{--background: 222 47% 11%;--foreground: 210 40% 98%;--card: 217 33% 17%;--card-foreground: 210 40% 98%;--primary: 239 84% 67%;--primary-foreground: 0 0% 100%;--muted: 215 16% 47%;--border: 217 19% 27%;--ring: 239 84% 67%}*{border-color:hsl(var(--border))}body{font-family:Montserrat,system-ui,sans-serif}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.left-0{left:0}.right-0{right:0}.top-0{top:0}.top-6{top:1.5rem}.z-50{z-index:50}.z-\[100\]{z-index:100}.z-\[120\]{z-index:120}.mx-auto{margin-left:auto;margin-right:auto}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-2{margin-right:.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-8{height:2rem}.h-\[calc\(100vh-3\.5rem\)\]{height:calc(100vh - 3.5rem)}.h-full{height:100%}.h-px{height:1px}.max-h-40{max-height:10rem}.max-h-60{max-height:15rem}.max-h-\[85vh\]{max-height:85vh}.min-h-0{min-height:0px}.min-h-\[calc\(100vh-3\.5rem\)\]{min-height:calc(100vh - 3.5rem)}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-16{width:4rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-8{width:2rem}.w-\[min\(560px\,90vw\)\]{width:min(560px,90vw)}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-\[3rem\]{min-width:3rem}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-\[120px\]{max-width:120px}.max-w-\[280px\]{max-width:280px}.max-w-\[40\%\]{max-width:40%}.max-w-lg{max-width:32rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-0{border-width:0px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity, 1))}.border-amber-500\/30{border-color:#f59e0b4d}.border-danger\/30{border-color:#ef44444d}.border-primary{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.border-primary\/20{border-color:#6366f133}.border-primary\/30{border-color:#6366f14d}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-slate-200\/50{border-color:#e2e8f080}.border-slate-300{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.border-slate-600{--tw-border-opacity: 1;border-color:rgb(71 85 105 / var(--tw-border-opacity, 1))}.border-slate-700{--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity, 1))}.border-slate-700\/50{border-color:#33415580}.border-warning\/20{border-color:#f59e0b33}.border-t-transparent{border-top-color:transparent}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-500\/10{background-color:#f59e0b1a}.bg-amber-500\/20{background-color:#f59e0b33}.bg-amber-500\/5{background-color:#f59e0b0d}.bg-black\/40{background-color:#0006}.bg-black\/50{background-color:#00000080}.bg-danger\/10{background-color:#ef44441a}.bg-danger\/20{background-color:#ef444433}.bg-danger\/5{background-color:#ef44440d}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-primary{--tw-bg-opacity: 1;background-color:rgb(99 102 241 / var(--tw-bg-opacity, 1))}.bg-primary\/10{background-color:#6366f11a}.bg-primary\/20{background-color:#6366f133}.bg-primary\/30{background-color:#6366f14d}.bg-primary\/5{background-color:#6366f10d}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-slate-100\/50{background-color:#f1f5f980}.bg-slate-200{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.bg-slate-50{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.bg-slate-700{--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}.bg-slate-700\/60{background-color:#33415599}.bg-slate-800{--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.bg-success{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-success\/10{background-color:#22c55e1a}.bg-success\/20{background-color:#22c55e33}.bg-success\/5{background-color:#22c55e0d}.bg-success\/90{background-color:#22c55ee6}.bg-surface{--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.bg-warning\/10{background-color:#f59e0b1a}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/80{background-color:#fffc}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-danger\/80{--tw-gradient-from: rgb(239 68 68 / .8) var(--tw-gradient-from-position);--tw-gradient-to: rgb(239 68 68 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-primary{--tw-gradient-from: #6366F1 var(--tw-gradient-from-position);--tw-gradient-to: rgb(99 102 241 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-primary\/80{--tw-gradient-from: rgb(99 102 241 / .8) var(--tw-gradient-from-position);--tw-gradient-to: rgb(99 102 241 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-slate-400{--tw-gradient-from: #94a3b8 var(--tw-gradient-from-position);--tw-gradient-to: rgb(148 163 184 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-success{--tw-gradient-from: #22C55E var(--tw-gradient-from-position);--tw-gradient-to: rgb(34 197 94 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-success\/80{--tw-gradient-from: rgb(34 197 94 / .8) var(--tw-gradient-from-position);--tw-gradient-to: rgb(34 197 94 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-danger{--tw-gradient-to: #EF4444 var(--tw-gradient-to-position)}.to-emerald-600{--tw-gradient-to: #059669 var(--tw-gradient-to-position)}.to-primary{--tw-gradient-to: #6366F1 var(--tw-gradient-to-position)}.to-primary-dark{--tw-gradient-to: #4F46E5 var(--tw-gradient-to-position)}.to-slate-500{--tw-gradient-to: #64748b var(--tw-gradient-to-position)}.to-success{--tw-gradient-to: #22C55E var(--tw-gradient-to-position)}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-10{padding:2.5rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-\[5\%\]{padding-left:5%;padding-right:5%}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-3{padding-bottom:.75rem}.pb-5{padding-bottom:1.25rem}.pt-14{padding-top:3.5rem}.pt-2{padding-top:.5rem}.pt-4{padding-top:1rem}.pt-5{padding-top:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-5{line-height:1.25rem}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-wider{letter-spacing:.05em}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-amber-500{--tw-text-opacity: 1;color:rgb(245 158 11 / var(--tw-text-opacity, 1))}.text-amber-500\/80{color:#f59e0bcc}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-amber-800{--tw-text-opacity: 1;color:rgb(146 64 14 / var(--tw-text-opacity, 1))}.text-danger{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-danger\/80{color:#ef4444cc}.text-info{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-primary{--tw-text-opacity: 1;color:rgb(99 102 241 / var(--tw-text-opacity, 1))}.text-primary-light{--tw-text-opacity: 1;color:rgb(129 140 248 / var(--tw-text-opacity, 1))}.text-primary-light\/90{color:#818cf8e6}.text-slate-200{--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.text-slate-300{--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-slate-800{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.text-success{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-warning{--tw-text-opacity: 1;color:rgb(245 158 11 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.placeholder-slate-400::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(148 163 184 / var(--tw-placeholder-opacity, 1))}.placeholder-slate-400::placeholder{--tw-placeholder-opacity: 1;color:rgb(148 163 184 / var(--tw-placeholder-opacity, 1))}.accent-primary{accent-color:#6366F1}.opacity-30{opacity:.3}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-primary\/20{--tw-shadow-color: rgb(99 102 241 / .2);--tw-shadow: var(--tw-shadow-colored)}.shadow-primary\/25{--tw-shadow-color: rgb(99 102 241 / .25);--tw-shadow: var(--tw-shadow-colored)}.shadow-success\/25{--tw-shadow-color: rgb(34 197 94 / .25);--tw-shadow: var(--tw-shadow-colored)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur: blur(12px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}@keyframes enter{0%{opacity:var(--tw-enter-opacity, 1);transform:translate3d(var(--tw-enter-translate-x, 0),var(--tw-enter-translate-y, 0),0) scale3d(var(--tw-enter-scale, 1),var(--tw-enter-scale, 1),var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity, 1);transform:translate3d(var(--tw-exit-translate-x, 0),var(--tw-exit-translate-y, 0),0) scale3d(var(--tw-exit-scale, 1),var(--tw-exit-scale, 1),var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0))}}.duration-200{animation-duration:.2s}.duration-300{animation-duration:.3s}.duration-500{animation-duration:.5s}.ease-out{animation-timing-function:cubic-bezier(0,0,.2,1)}.running{animation-play-state:running}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px}.dark ::-webkit-scrollbar-thumb{background:#334155}::-webkit-scrollbar-thumb:hover{background:#94a3b8}.dark ::-webkit-scrollbar-thumb:hover{background:#475569}.log-panel{font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:13px;line-height:1.6}.first\:mt-0:first-child{margin-top:0}.hover\:scale-\[1\.02\]:hover{--tw-scale-x: 1.02;--tw-scale-y: 1.02;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-primary:hover{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.hover\:border-primary\/60:hover{border-color:#6366f199}.hover\:bg-danger\/20:hover{background-color:#ef444433}.hover\:bg-danger\/30:hover{background-color:#ef44444d}.hover\:bg-primary-dark:hover{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity, 1))}.hover\:bg-primary\/20:hover{background-color:#6366f133}.hover\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-200:hover{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-50:hover{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-700\/50:hover{background-color:#33415580}.hover\:bg-success:hover{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.hover\:bg-success\/90:hover{background-color:#22c55ee6}.hover\:text-danger:hover{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.hover\:text-primary:hover{--tw-text-opacity: 1;color:rgb(99 102 241 / var(--tw-text-opacity, 1))}.hover\:text-primary-light:hover{--tw-text-opacity: 1;color:rgb(129 140 248 / var(--tw-text-opacity, 1))}.hover\:text-slate-600:hover{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.hover\:text-slate-700:hover{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-80:hover{opacity:.8}.hover\:shadow-primary\/40:hover{--tw-shadow-color: rgb(99 102 241 / .4);--tw-shadow: var(--tw-shadow-colored)}.hover\:shadow-success\/40:hover{--tw-shadow-color: rgb(34 197 94 / .4);--tw-shadow: var(--tw-shadow-colored)}.focus\:border-primary:focus{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-primary\/50:focus{--tw-ring-color: rgb(99 102 241 / .5)}.active\:scale-\[0\.98\]:active{--tw-scale-x: .98;--tw-scale-y: .98;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:hover\:scale-100:hover:disabled{--tw-scale-x: 1;--tw-scale-y: 1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:text-primary{--tw-text-opacity: 1;color:rgb(99 102 241 / var(--tw-text-opacity, 1))}.dark\:border-amber-700\/40:is(.dark *){border-color:#b4530966}.dark\:border-slate-600:is(.dark *){--tw-border-opacity: 1;border-color:rgb(71 85 105 / var(--tw-border-opacity, 1))}.dark\:border-slate-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity, 1))}.dark\:border-slate-700\/30:is(.dark *){border-color:#3341554d}.dark\:border-slate-700\/50:is(.dark *){border-color:#33415580}.dark\:border-slate-700\/60:is(.dark *){border-color:#33415599}.dark\:bg-amber-900\/30:is(.dark *){background-color:#78350f4d}.dark\:bg-slate-700:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-700\/50:is(.dark *){background-color:#33415580}.dark\:bg-slate-800:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-800\/40:is(.dark *){background-color:#1e293b66}.dark\:bg-slate-800\/50:is(.dark *){background-color:#1e293b80}.dark\:bg-surface:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.dark\:bg-surface-dark:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.dark\:bg-surface-dark\/50:is(.dark *){background-color:#0f172a80}.dark\:bg-surface-dark\/80:is(.dark *){background-color:#0f172acc}.dark\:text-amber-200:is(.dark *){--tw-text-opacity: 1;color:rgb(253 230 138 / var(--tw-text-opacity, 1))}.dark\:text-amber-400:is(.dark *){--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.dark\:text-amber-400\/70:is(.dark *){color:#fbbf24b3}.dark\:text-slate-100:is(.dark *){--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity, 1))}.dark\:text-slate-200:is(.dark *){--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.dark\:text-slate-300:is(.dark *){--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.dark\:text-slate-400:is(.dark *){--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.dark\:text-slate-500:is(.dark *){--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.dark\:text-slate-600:is(.dark *){--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.dark\:placeholder-slate-500:is(.dark *)::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(100 116 139 / var(--tw-placeholder-opacity, 1))}.dark\:placeholder-slate-500:is(.dark *)::placeholder{--tw-placeholder-opacity: 1;color:rgb(100 116 139 / var(--tw-placeholder-opacity, 1))}.dark\:hover\:bg-slate-700:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-slate-800:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-slate-800\/60:hover:is(.dark *){background-color:#1e293b99}.dark\:hover\:bg-surface-dark\/30:hover:is(.dark *){background-color:#0f172a4d}.dark\:hover\:text-slate-200:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.dark\:hover\:text-slate-300:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}@media (min-width: 640px){.sm\:inline{display:inline}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 1280px){.xl\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WXA Skill Eval</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet" />
<script type="module" crossorigin src="/assets/index-B8aqPCZv.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Cmjnh484.css">
</head>
<body class="bg-gray-50 text-slate-800 dark:bg-surface-dark dark:text-slate-100 min-h-screen antialiased">
<div id="app"></div>
</body>
</html>