@round2ai/r2-cli 1.0.11 → 1.0.12-beta.1
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.
- package/README.md +43 -14
- package/dist/README.md +43 -14
- package/dist/pages/login.html +219 -57
- package/dist/pages/xianyu-auth.html +244 -67
- package/dist/r2-cli.js +2160 -45
- package/package.json +9 -6
- package/scripts/install-skills.js +28 -19
- package/skills/r2-auth/SKILL.md +31 -45
- package/skills/r2-goods/SKILL.md +104 -163
- package/skills/r2-goods/references/r2-goods-hangup.md +284 -0
- package/skills/r2-goods/references/r2-goods-listing.md +137 -0
- package/skills/r2-goods/references/r2-goods-query.md +63 -0
- package/skills/r2-shared/SKILL.md +117 -0
- package/dist/package.json +0 -61
- package/scripts/build.js +0 -176
- package/scripts/dev.js +0 -22
- package/skills/r2-cli/SKILL.md +0 -70
- /package/skills/{r2-cli → r2-shared}/_meta.json +0 -0
package/scripts/build.js
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* 构建脚本 - 使用 esbuild 打包
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import esbuild from "esbuild";
|
|
7
|
-
import fs from "node:fs/promises";
|
|
8
|
-
import path from "path";
|
|
9
|
-
import { fileURLToPath } from "url";
|
|
10
|
-
import * as dotenv from "dotenv";
|
|
11
|
-
|
|
12
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
-
const __dirname = path.dirname(__filename);
|
|
14
|
-
const rootDir = path.dirname(__dirname);
|
|
15
|
-
|
|
16
|
-
const nodeEnv = process.env.NODE_ENV || "development";
|
|
17
|
-
const isProd = nodeEnv === "production";
|
|
18
|
-
const envFile = isProd ? ".env.production" : ".env";
|
|
19
|
-
dotenv.config({ path: path.join(rootDir, envFile) });
|
|
20
|
-
const serverBaseUrl = process.env.SERVER_BASEURL || "https://api.qiuxietang.com";
|
|
21
|
-
|
|
22
|
-
// 入口点配置
|
|
23
|
-
const entryPoints = {
|
|
24
|
-
"r2-cli": "src/entrypoints/r2-cli.tsx",
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
// esbuild 配置
|
|
28
|
-
const esbuildConfig = {
|
|
29
|
-
bundle: true,
|
|
30
|
-
platform: "node",
|
|
31
|
-
format: "esm",
|
|
32
|
-
sourcemap: false,
|
|
33
|
-
minify: isProd,
|
|
34
|
-
external: [
|
|
35
|
-
"commander",
|
|
36
|
-
"chalk",
|
|
37
|
-
"figlet",
|
|
38
|
-
"@inquirer/prompts",
|
|
39
|
-
"@inquirer/core",
|
|
40
|
-
"@inquirer/input",
|
|
41
|
-
"@inquirer/select",
|
|
42
|
-
"@inquirer/confirm",
|
|
43
|
-
"@inquirer/checkbox",
|
|
44
|
-
"mute-stream",
|
|
45
|
-
"qrcode",
|
|
46
|
-
"ora",
|
|
47
|
-
"react",
|
|
48
|
-
"ink",
|
|
49
|
-
"react-dom",
|
|
50
|
-
"react-devtools-core",
|
|
51
|
-
"uuid",
|
|
52
|
-
],
|
|
53
|
-
banner: {
|
|
54
|
-
js: '"use strict";',
|
|
55
|
-
},
|
|
56
|
-
define: {
|
|
57
|
-
"process.env.NODE_ENV": JSON.stringify(nodeEnv),
|
|
58
|
-
"process.env.SERVER_BASEURL": JSON.stringify(serverBaseUrl),
|
|
59
|
-
},
|
|
60
|
-
treeShaking: true,
|
|
61
|
-
splitting: false,
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* 清理输出目录
|
|
66
|
-
*/
|
|
67
|
-
async function cleanDist() {
|
|
68
|
-
const distDir = path.join(rootDir, "dist");
|
|
69
|
-
try {
|
|
70
|
-
await fs.rm(distDir, { recursive: true, force: true });
|
|
71
|
-
} catch (e) {
|
|
72
|
-
if (e.code === "EBUSY" || e.code === "EPERM") {
|
|
73
|
-
const files = await fs.readdir(distDir);
|
|
74
|
-
for (const file of files) {
|
|
75
|
-
await fs.rm(path.join(distDir, file), { recursive: true, force: true });
|
|
76
|
-
}
|
|
77
|
-
} else {
|
|
78
|
-
throw e;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
await fs.mkdir(distDir, { recursive: true });
|
|
82
|
-
console.log("🧹 清理输出目录完成");
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* 构建单个入口点
|
|
87
|
-
*/
|
|
88
|
-
async function buildEntryPoint(name, entry) {
|
|
89
|
-
const outputDir = path.join(rootDir, "dist");
|
|
90
|
-
console.log(`🔨 构建 ${name} -> ${path.relative(rootDir, outputDir)}`);
|
|
91
|
-
|
|
92
|
-
const config = { ...esbuildConfig };
|
|
93
|
-
if (name === "r2-cli") {
|
|
94
|
-
config.banner = {
|
|
95
|
-
js: "#!/usr/bin/env node\n",
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
await esbuild.build({
|
|
101
|
-
...config,
|
|
102
|
-
entryPoints: [path.join(rootDir, entry)],
|
|
103
|
-
outdir: outputDir,
|
|
104
|
-
// 保持原始文件名,不加 outdir 的 hash 前缀
|
|
105
|
-
// outdir 会自动生成文件名,不需要 outfile
|
|
106
|
-
});
|
|
107
|
-
console.log(`✅ ${name} 构建成功`);
|
|
108
|
-
} catch (error) {
|
|
109
|
-
console.error(`❌ ${name} 构建失败:`, error.message);
|
|
110
|
-
throw error;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* 复制必要文件
|
|
116
|
-
*/
|
|
117
|
-
async function copyFiles() {
|
|
118
|
-
const filesToCopy = ["package.json", "README.md"];
|
|
119
|
-
|
|
120
|
-
for (const file of filesToCopy) {
|
|
121
|
-
const src = path.join(rootDir, file);
|
|
122
|
-
const dest = path.join(rootDir, "dist", file);
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
await fs.copyFile(src, dest);
|
|
126
|
-
console.log(`📄 已复制 ${file}`);
|
|
127
|
-
} catch {
|
|
128
|
-
// file doesn't exist, skip
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// 复制 QR 页面 HTML 文件到 dist/pages/
|
|
133
|
-
const pagesDir = path.join(rootDir, "dist", "pages");
|
|
134
|
-
await fs.mkdir(pagesDir, { recursive: true });
|
|
135
|
-
const htmlSrcDir = path.join(rootDir, "src", "qr-server", "pages");
|
|
136
|
-
const htmlFiles = await fs.readdir(htmlSrcDir);
|
|
137
|
-
for (const file of htmlFiles) {
|
|
138
|
-
if (file.endsWith(".html")) {
|
|
139
|
-
await fs.copyFile(path.join(htmlSrcDir, file), path.join(pagesDir, file));
|
|
140
|
-
console.log(`📄 已复制 pages/${file}`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* 构建项目
|
|
147
|
-
*/
|
|
148
|
-
async function build() {
|
|
149
|
-
console.log("🚀 开始构建 R2-CLI...\n");
|
|
150
|
-
|
|
151
|
-
try {
|
|
152
|
-
// 1. 清理输出目录
|
|
153
|
-
await cleanDist();
|
|
154
|
-
|
|
155
|
-
// 2. 构建所有入口点
|
|
156
|
-
console.log("🔨 开始构建入口点...\n");
|
|
157
|
-
for (const [name, entry] of Object.entries(entryPoints)) {
|
|
158
|
-
await buildEntryPoint(name, entry);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// 3. 复制必要文件
|
|
162
|
-
await copyFiles();
|
|
163
|
-
|
|
164
|
-
console.log("\n✅ 构建完成!");
|
|
165
|
-
console.log("\n📦 输出文件:");
|
|
166
|
-
Object.keys(entryPoints).forEach((name) => {
|
|
167
|
-
console.log(` • dist/${name}.js`);
|
|
168
|
-
});
|
|
169
|
-
} catch (error) {
|
|
170
|
-
console.error("❌ 构建失败:", error);
|
|
171
|
-
process.exit(1);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// 运行构建
|
|
176
|
-
build();
|
package/scripts/dev.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* 开发模式 - 直接运行源码
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { spawn } from 'child_process';
|
|
7
|
-
import path from 'path';
|
|
8
|
-
import { fileURLToPath } from 'url';
|
|
9
|
-
|
|
10
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
-
const __dirname = path.dirname(__filename);
|
|
12
|
-
const rootDir = path.dirname(__dirname);
|
|
13
|
-
|
|
14
|
-
const child = spawn('npx', ['tsx', 'src/entrypoints/r2-cli.tsx', ...process.argv.slice(2)], {
|
|
15
|
-
cwd: rootDir,
|
|
16
|
-
stdio: 'inherit',
|
|
17
|
-
shell: true,
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
child.on('exit', (code) => {
|
|
21
|
-
process.exit(code ?? 1);
|
|
22
|
-
});
|
package/skills/r2-cli/SKILL.md
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: r2-cli
|
|
3
|
-
description: R2-CLI 二手潮奢交易 CLI 工具。用于认证登录、商品上架/下架/改价、查看店铺/仓库/选品商品/上架列表。Agent 获取数据后展示给用户选择,完成 4 步上架流程。触发词:r2-cli、登录、上架、下架、改价、商品、goods、auth、shops、stocks、listing。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# R2-CLI Skill
|
|
7
|
-
|
|
8
|
-
二手潮奢交易命令行工具,由 Round2AI 团队维护。覆盖商品上架、认证登录等核心业务域。
|
|
9
|
-
|
|
10
|
-
## 安装
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
npm install -g @round2ai/r2-cli@latest
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## 命令前缀自动检测
|
|
17
|
-
|
|
18
|
-
首次使用时检测一次,后续所有命令使用检测到的前缀:
|
|
19
|
-
|
|
20
|
-
1. 项目目录有 `package.json`(name 含 r2-cli)→ `npm run dev --`
|
|
21
|
-
2. 存在 `dist/r2-cli.js` → `node dist/r2-cli.js`
|
|
22
|
-
3. `r2-cli --version` 成功 → `r2-cli`
|
|
23
|
-
|
|
24
|
-
> 部分平台 npm 会拦截 `--help` 等 flag,改用 `npx tsx src/entrypoints/r2-cli.tsx --help`。
|
|
25
|
-
|
|
26
|
-
## 前置条件
|
|
27
|
-
|
|
28
|
-
- 先登录:`r2-cli auth login`(支持第二回合 APP / 微信 / 支付宝扫码)
|
|
29
|
-
- 检查状态:`r2-cli auth status`
|
|
30
|
-
|
|
31
|
-
所有 `--json` 命令输出 `{ success: false, error: "..." }` 格式错误,检查 `success` 判断成败。
|
|
32
|
-
|
|
33
|
-
## 认证命令
|
|
34
|
-
|
|
35
|
-
| 命令 | 说明 |
|
|
36
|
-
|------|------|
|
|
37
|
-
| `r2-cli auth login` | 扫码登录(自动打开浏览器,人类使用) |
|
|
38
|
-
| `r2-cli auth login --json` | 扫码登录(自动打开浏览器 + JSON 输出,Agent 推荐) |
|
|
39
|
-
| `r2-cli auth login poll --token <>` | 手动轮询登录状态(备选方案,不推荐) |
|
|
40
|
-
| `r2-cli auth xianyu` | 闲鱼店铺授权(自动打开浏览器,人类使用) |
|
|
41
|
-
| `r2-cli auth xianyu --json` | 闲鱼店铺授权(自动打开浏览器 + JSON 输出,Agent 推荐) |
|
|
42
|
-
| `r2-cli auth xianyu poll --state <>` | 手动轮询授权状态(备选方案,不推荐) |
|
|
43
|
-
| `r2-cli auth status` | 查看登录状态 |
|
|
44
|
-
| `r2-cli auth logout` | 退出登录 |
|
|
45
|
-
|
|
46
|
-
> 认证登录的详细 Agent 操作流程见 **r2-auth** skill。
|
|
47
|
-
|
|
48
|
-
## 商品管理命令
|
|
49
|
-
|
|
50
|
-
| 命令 | 说明 |
|
|
51
|
-
|------|------|
|
|
52
|
-
| `r2-cli goods shops [--json]` | 查看所有已授权店铺(跨平台) |
|
|
53
|
-
| `r2-cli goods stocks [--json]` | 查看所有仓库 |
|
|
54
|
-
| `r2-cli goods list [--stock-id <id>] [--stock-goods-id <id>] [--json]` | 查看选品商品(两个过滤参数均为可选,支持 `--page` 和 `--size`) |
|
|
55
|
-
| `r2-cli goods listing [--json]` | 查询上架列表(支持 `--id` / `--shop-id` / `--stock-goods-id` / `--stock-id` / `--status` / `--platform` 过滤) |
|
|
56
|
-
| `r2-cli goods up` | 交互式上架(自动轮询上架结果) |
|
|
57
|
-
| `r2-cli goods up --stock-goods-id <id> --shop-id <id> --price <amount> --json` | Agent 直接上架(自动轮询上架结果) |
|
|
58
|
-
| `r2-cli goods down --id <id> [--json]` | 下架商品(也可用 `--stock-goods-id <id> --shop-id <id>`) |
|
|
59
|
-
| `r2-cli goods price --id <id> --price <amount> [--json]` | 修改上架价格(也可用 `--stock-goods-id <id> --shop-id <id>`) |
|
|
60
|
-
|
|
61
|
-
## Agent 上架 4 步流程
|
|
62
|
-
|
|
63
|
-
**核心原则:Agent 获取数据后展示给用户选择,不要让用户自己提供 ID。**
|
|
64
|
-
|
|
65
|
-
1. `r2-cli goods shops --json` → 展示店铺(`shopId`、`shopName`、`platform`)→ 用户选择
|
|
66
|
-
2. `r2-cli goods stocks --json` → 展示仓库(`stockId`、`stockName`)→ 用户选择
|
|
67
|
-
3. `r2-cli goods list --stock-id <id> --json` → 展示商品(`stockGoodsId`、`goodsName`、`brand`、`size`、`salePrice`)→ 用户选择(也可用 `--stock-goods-id <id>` 查询单个商品)
|
|
68
|
-
4. `r2-cli goods up --stock-goods-id <id> --shop-id <id> --price <amount> --json` → 提交上架(自动轮询结果)
|
|
69
|
-
|
|
70
|
-
> 完整流程、参数说明和注意事项见 **r2-goods** skill。
|
|
File without changes
|