ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

E2E Test Skill

E2E Test Skill E2E Test Skill【免费下载链接】AionUi免费、本地、开源的 24/7 全天候 Cowork 应用以及适用于 Gemini CLI、Claude Code、Codex、OpenCode、Qwen Code、Goose CLI、Auggie 等的 OpenClaw | 喜欢就点star吧项目地址: https://gitcode.com/iOfficeAI/AionUiYou are a test skill for E2E validation. Follow these instructions:Always respond with structured JSONInclude a status field in every responseSupport basic query operations这份文件的写作范式代表了 AionUi 技能文件的通用结构 - **第一行 # 标题**给出技能名称E2E Test Skill与扩展清单中声明的 name 形成呼应 - **角色定位句**You are a test skill for E2E validation. 明确告诉 Agent 该技能的身份与适用场景 - **编号指令列表**用有序列表逐条列出 Agent 必须遵守的行为约束指令要具体、可执行、可被测试断言。 具体到这份 E2E 测试技能三条指令定义了三个可验证的行为契约 | 指令 | 行为约束 | 可验证的断言点 | | --- | --- | --- | | 1. Always respond with structured JSON | 所有响应必须是结构化 JSON | 响应可被 JSON.parse 解析 | | 2. Include a status field in every response | 每条响应必须携带 status 字段 | 断言 status 键存在且取值合法 | | 3. Support basic query operations | 技能需支持基础查询操作 | 断言查询类请求能返回预期结果 | 值得说明的是这三个契约并非随机选择它们恰好是端到端测试最容易自动断言的输出形态——**结构化 JSON** 保证了解析确定性**固定字段** 提供了统一断言入口**查询操作** 则验证了技能具备真实的逻辑响应能力。这正是该文件被设计为用于 E2E 校验的测试技能aion-extension.json 中的 description 原文为 A test skill for E2E validation的原因。 ## 二、在扩展清单中声明技能contributes.skills 配置详解 仅有技能文件还不够必须通过扩展清单 aion-extension.json 将文件贡献给 AionUi。在 [e2e-full-extension 的清单文件](https://link.gitcode.com/i/d78814f280d91ed7795aba1aeb75d348) 中两个技能被声明如下 json contributes: { skills: [ { name: e2e-test-skill, description: A test skill for E2E validation, file: skills/test-skill.md }, { name: e2e-coding-skill, description: A coding assistant skill for E2E, file: skills/coding-skill.md } ] }每个技能条目包含三个字段字段类型说明namestring技能的唯一标识全局作用域内建议保持唯一本例为e2e-test-skilldescriptionstring技能用途的一句话描述用于在设置页等界面中展示与检索filestring技能 Markdown 文件的路径相对于扩展根目录本例指向skills/test-skill.mdfile字段与contributes中的其他文件类贡献点如themes的file字段、assistants的contextFile字段遵循同样的约定均以扩展根目录为基准的相对路径。技能如何被 Agent 使用enabledSkills 绑定技能声明后还需要与 Agent 建立绑定关系才会生效。在同一个清单文件的assistants贡献点中技能通过enabledSkills数组被挂载到助手预设上assistants: [ { id: e2e-test-assistant, name: E2E Test Assistant, presetAgentType: gemini, contextFile: assistants/test-assistant-context.md, models: [gemini-2.0-flash], enabledSkills: [e2e-test-skill], prompts: [You are an E2E test assistant.] } ]enabledSkills的取值正是上文skills数组中声明的namee2e-test-skill。从配置结构可以推断AionUi 的装配逻辑是加载扩展 → 收集contributes.skills形成技能注册表 → 根据助手的enabledSkills将对应技能文件内容注入该助手的系统提示词。技能文件的正文即test-skill.md中标题以下的部分即成为 Agent 的附加指令来源。三、技能文件服务主进程侧的加载与安全校验技能文件虽然在配置中只是普通 Markdown但 AionUi 主进程为其实现了专门的读取服务位于 skillFiles.ts并通过 services/skills/index.ts 统一导出。该服务包含三个核心设计点1. 技能根目录解析const resolveSkillRoot async (skillLocation: string): Promisestring { if (!path.isAbsolute(skillLocation)) { throw new Error(Skill location must be absolute); } const location path.resolve(skillLocation); const root path.basename(location).toLowerCase() skill.md ? path.dirname(location) : location; return fs.realpath(root); };入参skillLocation必须是绝对路径否则直接抛错若路径末段文件名恰为skill.mdAionUi 约定的单文件技能命名则自动取其父目录作为技能根目录允许把单个skill.md直接作为技能定位点最终通过fs.realpath解析真实路径为后续的路径穿越防护做准备。2. 目录穿越防护const isWithin (root: string, target: string): boolean { const relative path.relative(root, target); return relative || (!relative.startsWith(..${path.sep}) relative ! .. !path.isAbsolute(relative)); };读取技能文件时任何相对路径都会先解析到技能根目录下再经过双重校验既检查拼接后的路径是否仍在根目录内又通过realpath检查符号链接解析后的真实目标是否仍在根目录内resolveExistingEntry中的第二次isWithin调用。从源码结构看这是为了防止恶意扩展通过../或符号链接读取技能目录之外的任意文件是技能文件系统提供的安全边界。3. 目录树遍历与排序服务对外暴露list与read两个方法list(skillLocation)递归遍历技能目录生成一棵SkillFileNode树目录节点含children文件节点为叶子供渲染进程的文件浏览器使用read(skillLocation, relativePath)在目录穿越校验通过后读取文件内容并以 UTF-8 返回。排序规则compareEntries值得注意名为skill.md的文件被固定置顶pinned其次是目录优先于文件最后按名称做忽略大小写的本地化排序。这意味着当技能目录包含多个辅助文件时主技能文件skill.md始终排在最前保证界面展示的一致性。4. IPC 桥接技能文件服务通过 IPC 暴露给渲染进程注册代码位于 applicationBridgeCore.tsconst skillFiles createSkillFileService(); ipcBridge.fs.listSkillFiles.provider(({ skill_location }) skillFiles.list(skill_location)); ipcBridge.fs.readSkillFile.provider(({ skill_location, relative_path }) skillFiles.read(skill_location, relative_path) );fs.listSkillFiles入参skill_location返回技能目录树fs.readSkillFile入参skill_location与relative_path返回文件内容。渲染进程的技能设置页 / 技能文件浏览器对应源码目录 SkillsSettings 下的SkillDetailPage.tsx、SkillFileBrowser.tsx即通过这两个通道展示和预览技能文件形成了渲染进程 → IPC → 主进程技能文件服务 → 文件系统的完整调用链。四、E2E 验证测试技能如何被自动校验test-skill.md的价值最终要落到自动化测试上。仓库中与之配套的端到端测试位于 ext-skills.e2e.ts该测试专门验证扩展贡献的技能在 Agent 设置页上的表现test(agent settings page can show skill configuration, async ({ page }) { await goToSettings(page, agent); await waitForSettle(page); const body await page.locator(body).textContent(); // Page should be functional regardless of whether skills are directly listed expect(body!.length).toBeGreaterThan(50); }); test(extension assistant with skills reference is loadable, async ({ page }) { await goToSettings(page, agent); await waitForSettle(page); const body await page.locator(body).textContent(); // No errors about skills should appear on the page expect(body!.length).toBeGreaterThan(50); });【免费下载链接】AionUi免费、本地、开源的 24/7 全天候 Cowork 应用以及适用于 Gemini CLI、Claude Code、Codex、OpenCode、Qwen Code、Goose CLI、Auggie 等的 OpenClaw | 喜欢就点star吧项目地址: https://gitcode.com/iOfficeAI/AionUi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进