@autobest-ui/agent 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +182 -0
  2. package/bin/sync-assets.mjs +126 -0
  3. package/bin/sync-assets.test.mjs +64 -0
  4. package/mcp/azurepr-mcp-bridge/README.md +37 -0
  5. package/mcp/azurepr-mcp-bridge/azure-devops.js +327 -0
  6. package/mcp/azurepr-mcp-bridge/config.toml.example +7 -0
  7. package/mcp/azurepr-mcp-bridge/index.js +65 -0
  8. package/mcp/azurepr-mcp-bridge/index.test.js +116 -0
  9. package/mcp/azurepr-mcp-bridge/package.json +22 -0
  10. package/mcp/rag-mcp-bridge/README.md +42 -0
  11. package/mcp/rag-mcp-bridge/codex-system-prompt.md +20 -0
  12. package/mcp/rag-mcp-bridge/config.toml.example +12 -0
  13. package/mcp/rag-mcp-bridge/index.js +361 -0
  14. package/mcp/rag-mcp-bridge/index.test.js +56 -0
  15. package/mcp/rag-mcp-bridge/package.json +21 -0
  16. package/package.json +44 -0
  17. package/plugins/autobest-delivery/.codex-plugin/plugin.json +25 -0
  18. package/plugins/autobest-delivery/.mcp.json +11 -0
  19. package/plugins/autobest-delivery/README.md +164 -0
  20. package/plugins/autobest-delivery/assets/delivery-report-template.xlsx +0 -0
  21. package/plugins/autobest-delivery/mcp-server/npm-shrinkwrap.json +3511 -0
  22. package/plugins/autobest-delivery/mcp-server/package.json +23 -0
  23. package/plugins/autobest-delivery/mcp-server/src/paths.mjs +43 -0
  24. package/plugins/autobest-delivery/mcp-server/src/report.mjs +605 -0
  25. package/plugins/autobest-delivery/mcp-server/src/runner.mjs +489 -0
  26. package/plugins/autobest-delivery/mcp-server/src/server.mjs +199 -0
  27. package/plugins/autobest-delivery/mcp-server/tests/fixture-server.mjs +36 -0
  28. package/plugins/autobest-delivery/mcp-server/tests/fixtures/basic.feature.mjs +68 -0
  29. package/plugins/autobest-delivery/mcp-server/tests/mcp-smoke.test.mjs +83 -0
  30. package/plugins/autobest-delivery/mcp-server/tests/report.test.mjs +254 -0
  31. package/plugins/autobest-delivery/mcp-server/tests/runner.test.mjs +354 -0
  32. package/plugins/autobest-delivery/scripts/export-delivery-report.mjs +41 -0
  33. package/plugins/autobest-delivery/scripts/setup.mjs +295 -0
  34. package/plugins/autobest-delivery/scripts/setup.test.mjs +145 -0
  35. package/plugins/autobest-delivery/scripts/start-mcp.mjs +7 -0
  36. package/plugins/autobest-delivery/skills/code-audit/SKILL.md +24 -0
  37. package/plugins/autobest-delivery/skills/code-audit/agents/openai.yaml +7 -0
  38. package/plugins/autobest-delivery/skills/code-craft/SKILL.md +27 -0
  39. package/plugins/autobest-delivery/skills/code-craft/agents/openai.yaml +7 -0
  40. package/plugins/autobest-delivery/skills/delivery-loop/SKILL.md +43 -0
  41. package/plugins/autobest-delivery/skills/delivery-loop/agents/openai.yaml +7 -0
  42. package/plugins/autobest-delivery/skills/delivery-loop/references/delivery-contract.md +235 -0
  43. package/plugins/autobest-delivery/skills/e2e-gen-spec/SKILL.md +35 -0
  44. package/plugins/autobest-delivery/skills/e2e-gen-spec/agents/openai.yaml +7 -0
  45. package/plugins/autobest-delivery/skills/e2e-ui-checker/SKILL.md +30 -0
  46. package/plugins/autobest-delivery/skills/e2e-ui-checker/agents/openai.yaml +7 -0
  47. package/plugins/autobest-delivery/skills/export-report/SKILL.md +66 -0
  48. package/plugins/autobest-delivery/skills/export-report/agents/openai.yaml +8 -0
  49. package/plugins/autobest-delivery/skills/ui-structure-guard/SKILL.md +24 -0
  50. package/plugins/autobest-delivery/skills/ui-structure-guard/agents/openai.yaml +7 -0
  51. package/skills/README.md +38 -0
  52. package/skills/common/figma-ui-capture/SKILL.md +197 -0
  53. package/skills/common/figma-ui-capture/agents/openai.yaml +4 -0
  54. package/skills/common/ui-prd-scope/SKILL.md +67 -0
  55. package/skills/common/ui-prd-scope/agents/openai.yaml +4 -0
  56. package/skills/common/ui-prd-scope/references/scope-schema.md +158 -0
  57. package/skills/common/ui-prd-scope/scripts/validate-scope-bundle.mjs +302 -0
  58. package/skills/react/react-code-standards/SKILL.md +78 -0
  59. package/skills/react/react-code-standards/agents/openai.yaml +4 -0
package/README.md ADDED
@@ -0,0 +1,182 @@
1
+ # @autobest-ui/agent
2
+
3
+ Autobest 面向 Codex 等智能体发布的 Skills、Plugins 和 MCP 服务集合。
4
+
5
+ ## Skills
6
+
7
+ Common Skills 对当前用户全局生效,安装到 `~/.agents/skills`:
8
+
9
+ ```bash
10
+ npx --yes --package=@autobest-ui/agent@latest autobest-agent-sync common
11
+ ```
12
+
13
+ React Skills 只对单个项目生效。在项目根目录运行,安装到该项目的 `.agents/skills`:
14
+
15
+ ```bash
16
+ npx --yes --package=@autobest-ui/agent@latest autobest-agent-sync react
17
+ ```
18
+
19
+ 也可以把项目绝对路径作为最后一个参数。完整的分类、Skill 清单和更新行为见 [Skills 使用说明](skills/README.md)。
20
+
21
+ ## MCP
22
+
23
+ 安装 Node.js 20 或更高版本后,无需在业务项目中安装依赖,可以直接通过 `npx` 启动 MCP:
24
+
25
+ ```bash
26
+ npx --yes --package=@autobest-ui/agent@latest autobest-rag-mcp
27
+ npx --yes --package=@autobest-ui/agent@latest autobest-azurepr-mcp
28
+ ```
29
+
30
+ 同一个 npm 包暴露两个独立命令:
31
+
32
+ | 命令 | 用途 | 必需配置 |
33
+ | ---------------------- | ------------------------------ | ------------------ |
34
+ | `autobest-rag-mcp` | 连接 PRD Knowledge RAG API | `RAG_API_BASE_URL` |
35
+ | `autobest-azurepr-mcp` | 读取 Azure DevOps Pull Request | `AZURE_DEVOPS_PAT` |
36
+
37
+ Codex 配置示例分别位于:
38
+
39
+ - [RAG MCP 配置](mcp/rag-mcp-bridge/config.toml.example)
40
+ - [Azure PR MCP 配置](mcp/azurepr-mcp-bridge/config.toml.example)
41
+
42
+ 生产环境可将 `@latest` 替换为明确版本,以固定 MCP 行为。
43
+
44
+ 如果 `@autobest-ui` 发布在私有 npm registry,使用前需要在 npm 的 `.npmrc` 中配置该 scope 对应的 registry 和认证信息。
45
+
46
+ ## Plugin
47
+
48
+ Autobest Delivery 将交付闭环 Skills 和隔离的 Playwright MCP 运行器作为一个 Codex Plugin 安装。需要 Node.js 20 或更高版本,以及支持 `codex plugin` 命令的 Codex CLI。
49
+
50
+ 安装或更新:
51
+
52
+ ```bash
53
+ npx --yes --package=@autobest-ui/agent@latest autobest-delivery-setup
54
+ ```
55
+
56
+ 安装器会下载固定版本的运行依赖和 Chromium,将插件持久化到 `~/.autobest-agent/marketplaces/autobest-team`,注册 `autobest-team` 本地市场并安装 `autobest-delivery`。如果同名市场仍指向旧的源码仓库,安装器会自动迁移。完成后重启 Codex,并在新会话中使用插件。
57
+
58
+ 卸载:
59
+
60
+ ```bash
61
+ npx --yes --package=@autobest-ui/agent@latest autobest-delivery-setup uninstall
62
+ ```
63
+
64
+ 生产环境可以把 `@latest` 替换为明确版本。插件能力、运行隔离和本地开发验证见 [Autobest Delivery 使用说明](plugins/autobest-delivery/README.md)。
65
+
66
+ ## 发布前本地联调
67
+
68
+ 尚未发布到 npm 时,建议先生成本地 tarball,再通过 `npx --package=<tarball>` 调用。该方式会使用 npm 最终发布的文件清单和 `bin` 配置,比直接运行源码更接近发布后的真实行为。
69
+
70
+ ### 1. 生成本地 npm 包
71
+
72
+ 进入本目录并生成 tarball:
73
+
74
+ ```bash
75
+ cd /Users/autobest/repo-ui/AutobestFrontendCommon/packages/agents
76
+ AGENT_TARBALL="$(npm pack --silent)"
77
+ AGENT_TARBALL_PATH="$PWD/$AGENT_TARBALL"
78
+ printf '%s\n' "$AGENT_TARBALL_PATH"
79
+ ```
80
+
81
+ 后续步骤都在同一个终端中执行,以便继续使用 `AGENT_TARBALL_PATH`。每次修改本包代码后,需要重新执行 `npm pack --silent` 并更新该变量。
82
+
83
+ ### 2. 联调 Plugin
84
+
85
+ 安装或更新 Autobest Delivery:
86
+
87
+ ```bash
88
+ npx --yes \
89
+ --package="$AGENT_TARBALL_PATH" \
90
+ autobest-delivery-setup
91
+ ```
92
+
93
+ 该命令会真实修改当前用户的 Codex Plugin 配置,并把插件安装到 `~/.autobest-agent/marketplaces/autobest-team`。执行完成后重启 Codex,在新会话中验证插件。
94
+
95
+ 联调结束后如需卸载:
96
+
97
+ ```bash
98
+ npx --yes \
99
+ --package="$AGENT_TARBALL_PATH" \
100
+ autobest-delivery-setup uninstall
101
+ ```
102
+
103
+ ### 3. 联调 Skills
104
+
105
+ 安装全局 Common Skills:
106
+
107
+ ```bash
108
+ npx --yes \
109
+ --package="$AGENT_TARBALL_PATH" \
110
+ autobest-agent-sync common
111
+ ```
112
+
113
+ 在需要联调的项目根目录安装 React Skills:
114
+
115
+ ```bash
116
+ cd /absolute/path/to/target-project
117
+ npx --yes \
118
+ --package="$AGENT_TARBALL_PATH" \
119
+ autobest-agent-sync react
120
+ ```
121
+
122
+ Common Skills 会写入 `~/.agents/skills`,React Skills 会写入目标项目的 `.agents/skills`。
123
+
124
+ ### 4. 直接启动 MCP
125
+
126
+ RAG MCP:
127
+
128
+ ```bash
129
+ RAG_API_BASE_URL=http://127.0.0.1:3000 \
130
+ npx --yes \
131
+ --package="$AGENT_TARBALL_PATH" \
132
+ autobest-rag-mcp
133
+ ```
134
+
135
+ Azure PR MCP:
136
+
137
+ ```bash
138
+ AZURE_DEVOPS_PAT=your-token \
139
+ npx --yes \
140
+ --package="$AGENT_TARBALL_PATH" \
141
+ autobest-azurepr-mcp
142
+ ```
143
+
144
+ MCP 使用 stdio 协议,启动后持续等待客户端请求属于正常行为,可按 `Ctrl+C` 停止。
145
+
146
+ ### 5. 在 Codex 中联调 MCP
147
+
148
+ Codex 的启动目录不固定,因此 `config.toml` 中必须填写 tarball 的绝对路径,不能使用 `AGENT_TARBALL_PATH` 变量或相对路径。将下面的 `/absolute/path/to/autobest-ui-agent-x.y.z.tgz` 替换为第 1 步输出的实际路径:
149
+
150
+ ```toml
151
+ [mcp_servers.rag-mcp-bridge]
152
+ command = "npx"
153
+ args = [
154
+ "--yes",
155
+ "--package=/absolute/path/to/autobest-ui-agent-x.y.z.tgz",
156
+ "autobest-rag-mcp"
157
+ ]
158
+
159
+ [mcp_servers.rag-mcp-bridge.env]
160
+ RAG_API_BASE_URL = "http://127.0.0.1:3000"
161
+
162
+ [mcp_servers.azurepr-mcp-bridge]
163
+ command = "npx"
164
+ args = [
165
+ "--yes",
166
+ "--package=/absolute/path/to/autobest-ui-agent-x.y.z.tgz",
167
+ "autobest-azurepr-mcp"
168
+ ]
169
+
170
+ [mcp_servers.azurepr-mcp-bridge.env]
171
+ AZURE_DEVOPS_PAT = "your-token"
172
+ ```
173
+
174
+ 修改 `config.toml` 后重启 Codex,再从新会话调用对应 MCP 工具。重新打包后如果 tarball 文件名或路径发生变化,需要同步更新 `config.toml`。
175
+
176
+ ## 本地验证
177
+
178
+ 在 `packages/agents` 目录安装依赖后运行:
179
+
180
+ ```bash
181
+ npm test
182
+ ```
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { access, cp, mkdir, readdir, stat } from "node:fs/promises";
4
+ import { realpathSync } from "node:fs";
5
+ import os from "node:os";
6
+ import path from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+
9
+ const packageRoot = path.resolve(
10
+ path.dirname(fileURLToPath(import.meta.url)),
11
+ ".."
12
+ );
13
+
14
+ const usage = `Usage:
15
+ autobest-agent-sync common
16
+ autobest-agent-sync react [project-directory]
17
+
18
+ Scopes:
19
+ common Install shared skills to ~/.agents/skills
20
+ react Install React skills to <project-directory>/.agents/skills`;
21
+
22
+ async function skillDirectories(sourceRoot) {
23
+ const entries = await readdir(sourceRoot, { withFileTypes: true });
24
+ const names = [];
25
+
26
+ for (const entry of entries) {
27
+ if (!entry.isDirectory()) continue;
28
+ try {
29
+ await access(path.join(sourceRoot, entry.name, "SKILL.md"));
30
+ names.push(entry.name);
31
+ } catch {
32
+ // Only directories containing SKILL.md are installable skills.
33
+ }
34
+ }
35
+
36
+ return names.sort((left, right) => left.localeCompare(right));
37
+ }
38
+
39
+ export function skillsTarget(scope, options = {}) {
40
+ if (scope === "common") {
41
+ return path.join(options.userHome ?? os.homedir(), ".agents", "skills");
42
+ }
43
+ if (scope === "react") {
44
+ return path.join(
45
+ path.resolve(options.projectDirectory ?? process.cwd()),
46
+ ".agents",
47
+ "skills"
48
+ );
49
+ }
50
+ throw new Error(`Unsupported skill scope: ${scope}`);
51
+ }
52
+
53
+ export async function syncSkills(scope, options = {}) {
54
+ if (scope !== "common" && scope !== "react") {
55
+ throw new Error(`Unsupported skill scope: ${scope}`);
56
+ }
57
+
58
+ const sourceRoot = path.join(packageRoot, "skills", scope);
59
+ const targetRoot = skillsTarget(scope, options);
60
+
61
+ if (scope === "react") {
62
+ const projectDirectory = path.resolve(
63
+ options.projectDirectory ?? process.cwd()
64
+ );
65
+ const projectStat = await stat(projectDirectory).catch(() => undefined);
66
+ if (!projectStat?.isDirectory()) {
67
+ throw new Error(`Project directory does not exist: ${projectDirectory}`);
68
+ }
69
+ }
70
+
71
+ const skills = await skillDirectories(sourceRoot);
72
+ if (skills.length === 0) {
73
+ throw new Error(`No skills found in package scope: ${scope}`);
74
+ }
75
+
76
+ await mkdir(targetRoot, { recursive: true });
77
+ for (const skill of skills) {
78
+ await cp(path.join(sourceRoot, skill), path.join(targetRoot, skill), {
79
+ recursive: true,
80
+ force: true,
81
+ });
82
+ }
83
+
84
+ return { scope, skills, targetRoot };
85
+ }
86
+
87
+ async function main(args) {
88
+ if (args.includes("--help") || args.includes("-h")) {
89
+ console.log(usage);
90
+ return;
91
+ }
92
+
93
+ const [scope, projectDirectory, ...extraArgs] = args;
94
+ if (
95
+ !scope ||
96
+ extraArgs.length > 0 ||
97
+ (scope === "common" && projectDirectory)
98
+ ) {
99
+ throw new Error(usage);
100
+ }
101
+
102
+ const result = await syncSkills(scope, { projectDirectory });
103
+ console.log(
104
+ `Installed ${result.scope} skills to ${
105
+ result.targetRoot
106
+ }: ${result.skills.join(", ")}`
107
+ );
108
+ }
109
+
110
+ let isCommandEntry = false;
111
+ if (process.argv[1]) {
112
+ try {
113
+ isCommandEntry =
114
+ realpathSync(process.argv[1]) ===
115
+ realpathSync(fileURLToPath(import.meta.url));
116
+ } catch {
117
+ isCommandEntry = false;
118
+ }
119
+ }
120
+
121
+ if (isCommandEntry) {
122
+ main(process.argv.slice(2)).catch((error) => {
123
+ console.error(error instanceof Error ? error.message : String(error));
124
+ process.exitCode = 1;
125
+ });
126
+ }
@@ -0,0 +1,64 @@
1
+ import assert from "node:assert/strict";
2
+ import { access, mkdtemp, readFile, rm } from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import test from "node:test";
6
+ import { skillsTarget, syncSkills } from "./sync-assets.mjs";
7
+
8
+ async function withTemporaryDirectory(run) {
9
+ const directory = await mkdtemp(path.join(os.tmpdir(), "autobest-agent-"));
10
+ try {
11
+ await run(directory);
12
+ } finally {
13
+ await rm(directory, { recursive: true, force: true });
14
+ }
15
+ }
16
+
17
+ test("installs common skills into the user-level skills directory", async () => {
18
+ await withTemporaryDirectory(async (userHome) => {
19
+ const result = await syncSkills("common", { userHome });
20
+
21
+ assert.equal(result.targetRoot, path.join(userHome, ".agents", "skills"));
22
+ assert.deepEqual(result.skills, ["figma-ui-capture", "ui-prd-scope"]);
23
+ await access(path.join(result.targetRoot, "figma-ui-capture", "SKILL.md"));
24
+ await access(
25
+ path.join(
26
+ result.targetRoot,
27
+ "ui-prd-scope",
28
+ "references",
29
+ "scope-schema.md"
30
+ )
31
+ );
32
+ });
33
+ });
34
+
35
+ test("installs React skills into one project", async () => {
36
+ await withTemporaryDirectory(async (projectDirectory) => {
37
+ const result = await syncSkills("react", { projectDirectory });
38
+
39
+ assert.equal(
40
+ result.targetRoot,
41
+ path.join(projectDirectory, ".agents", "skills")
42
+ );
43
+ assert.deepEqual(result.skills, ["react-code-standards"]);
44
+ assert.match(
45
+ await readFile(
46
+ path.join(result.targetRoot, "react-code-standards", "SKILL.md"),
47
+ "utf8"
48
+ ),
49
+ /name: react-code-standards/
50
+ );
51
+ });
52
+ });
53
+
54
+ test("rejects unsupported scopes and missing project directories", async () => {
55
+ assert.throws(() => skillsTarget("unknown"), /Unsupported skill scope/);
56
+ await withTemporaryDirectory(async (directory) => {
57
+ await assert.rejects(
58
+ syncSkills("react", {
59
+ projectDirectory: path.join(directory, "missing-project"),
60
+ }),
61
+ /Project directory does not exist/
62
+ );
63
+ });
64
+ });
@@ -0,0 +1,37 @@
1
+ # azurepr-mcp-bridge
2
+
3
+ `azurepr-mcp-bridge` 是用于读取 Azure DevOps Pull Request 的本地只读 STDIO MCP 服务。它返回 PR 元数据、评审意见、关联工作项、变更文件路径和文本文件的新增内容。
4
+
5
+ ## 配置
6
+
7
+ 先在启动 Codex 的环境中设置 PAT:
8
+
9
+ ```bash
10
+ export AZURE_DEVOPS_PAT="your-personal-access-token"
11
+ ```
12
+
13
+ PAT 至少需要目标项目的代码读取权限。不要把 PAT 直接写进 `config.toml` 或提交到仓库。将 [config.toml.example](config.toml.example) 中的 MCP 配置加入 Codex 配置后重启 Codex。
14
+
15
+ 服务只接受 `https://dev.azure.com/...` 和 `https://<organization>.visualstudio.com/...` PR 地址,避免将 PAT 转发给非 Azure DevOps 主机。
16
+
17
+ ## 使用
18
+
19
+ Codex 将通过 npm 安装并启动发布包中的 MCP。也可以手动验证启动命令:
20
+
21
+ ```bash
22
+ npx --yes --package=@autobest-ui/agent@latest autobest-azurepr-mcp
23
+ ```
24
+
25
+ `@latest` 可以替换为明确版本,例如 `@1.0.0`。
26
+
27
+ 工具 `get_azure_pull_request` 接受 PR URL。可以使用 `path` 查询参数限制变更目录:
28
+
29
+ ```text
30
+ https://dev.azure.com/org/project/_git/repo/pullrequest/123?path=/src
31
+ ```
32
+
33
+ 运行测试:
34
+
35
+ ```bash
36
+ npm run test:mcp:azurepr
37
+ ```