@round2ai/r2-cli 1.0.11 → 1.0.12-beta.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.
- package/README.md +24 -12
- package/dist/README.md +24 -12
- package/dist/r2-cli.js +36 -35
- package/package.json +7 -4
- package/scripts/install-skills.js +1 -20
- package/skills/r2-auth/SKILL.md +31 -45
- package/skills/r2-goods/SKILL.md +309 -98
- package/skills/r2-shared/SKILL.md +94 -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/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
R2-CLI — 二手潮奢交易命令行工具,由 [Round2AI](https://github.com/Round2AI) 团队维护 — 让人类和 AI Agent 都能在终端中完成商品上架等交易操作。
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
覆盖商品上架、挂售、认证登录等核心业务域,提供 12 个命令及 3 个 AI Agent [Skills](./skills/)。
|
|
9
9
|
|
|
10
10
|
[安装](#安装与快速开始) · [AI Agent 快速开始](#快速开始ai-agent) · [Agent Skills](#agent-skills) · [认证](#认证) · [命令](#命令参考) · [安全](#安全与风险提示)
|
|
11
11
|
|
|
@@ -22,6 +22,7 @@ R2-CLI — 二手潮奢交易命令行工具,由 [Round2AI](https://github.com
|
|
|
22
22
|
|------|------|
|
|
23
23
|
| 认证登录 | 扫码登录(第二回合 APP / 微信 / 支付宝)、闲鱼店铺授权、状态查询、登出(Agent 一步式流程) |
|
|
24
24
|
| 商品管理 | 商品上架(4 步流程:获取店铺 → 获取仓库 → 获取选品商品 → 提交上架 + 自动轮询上架结果)、店铺查看、仓库查看、选品商品查看、上架列表查询、下架、改价 |
|
|
25
|
+
| 闲鱼挂售 | 完整商品信息模式:类目查询 → 属性/品牌选择 → 图片上传 → 提交挂售 |
|
|
25
26
|
|
|
26
27
|
---
|
|
27
28
|
|
|
@@ -114,9 +115,9 @@ npx skills add Round2AI/r2-cli --all -y
|
|
|
114
115
|
|
|
115
116
|
| Skill | 说明 |
|
|
116
117
|
|-------|------|
|
|
118
|
+
| `r2-shared` | 共享基础:安装、统一错误格式、命令概览 |
|
|
117
119
|
| `r2-auth` | 认证登录:一步式扫码登录(生成二维码 + 自动轮询,支持第二回合 APP / 微信 / 支付宝)、闲鱼店铺授权、状态查询、登出 |
|
|
118
|
-
| `r2-
|
|
119
|
-
| `r2-goods` | 商品管理:4 步上架流程(获取数据 → 展示给用户 → 用户选择 → 提交上架 + 自动轮询结果)、下架、改价、店铺/仓库/商品/上架列表查看 |
|
|
120
|
+
| `r2-goods` | 商品管理:4 步上架流程、挂售流程(类目→属性→图片→提交)、下架、改价、店铺/仓库/商品/上架列表查看 |
|
|
120
121
|
|
|
121
122
|
---
|
|
122
123
|
|
|
@@ -139,7 +140,7 @@ Token 存储在 `~/.r2-cli/config.json`(原子写入防丢失),过期后
|
|
|
139
140
|
|
|
140
141
|
## 命令参考
|
|
141
142
|
|
|
142
|
-
###
|
|
143
|
+
### 商品查询
|
|
143
144
|
|
|
144
145
|
| 命令 | 说明 |
|
|
145
146
|
|------|------|
|
|
@@ -147,20 +148,31 @@ Token 存储在 `~/.r2-cli/config.json`(原子写入防丢失),过期后
|
|
|
147
148
|
| `r2-cli goods stocks [--json]` | 查看所有仓库 |
|
|
148
149
|
| `r2-cli goods list [--stock-id <id>] [--stock-goods-id <id>] [--json]` | 查看选品商品(可按仓库或商品 ID 过滤,支持 `--page` 和 `--size`) |
|
|
149
150
|
| `r2-cli goods listing [--json]` | 查询上架列表(支持 `--id` / `--shop-id` / `--stock-goods-id` / `--stock-id` / `--status` / `--platform` 过滤) |
|
|
151
|
+
|
|
152
|
+
### 商品上架/下架
|
|
153
|
+
|
|
154
|
+
| 命令 | 说明 |
|
|
155
|
+
|------|------|
|
|
150
156
|
| `r2-cli goods up` | 交互式上架(自动轮询上架结果) |
|
|
151
157
|
| `r2-cli goods up --stock-goods-id <id> --shop-id <id> --price <amount> --json` | Agent 直接上架(自动轮询上架结果) |
|
|
152
158
|
| `r2-cli goods down --id <id> [--json]` | 下架商品(也可用 `--stock-goods-id <id> --shop-id <id>`) |
|
|
153
159
|
| `r2-cli goods price --id <id> --price <amount> [--json]` | 修改上架价格(也可用 `--stock-goods-id <id> --shop-id <id>`) |
|
|
154
160
|
|
|
155
|
-
###
|
|
161
|
+
### 闲鱼挂售(完整商品信息模式)
|
|
162
|
+
|
|
163
|
+
挂售模式支持完整的商品信息:图片、类目、属性、品牌等。流程:查询类目/属性 → 上传图片 → 提交挂售。
|
|
164
|
+
|
|
165
|
+
| 命令 | 说明 |
|
|
166
|
+
|------|------|
|
|
167
|
+
| `r2-cli goods hang-up categories [--json]` | 获取闲鱼类目列表(大分类 → 小分类) |
|
|
168
|
+
| `r2-cli goods hang-up props --channel-cat-id <id> [--json]` | 获取指定类目下的属性列表(含可选值) |
|
|
169
|
+
| `r2-cli goods hang-up brands --channel-cat-id <id> --prop-id <id> --key <keyword> [--json]` | 品牌搜索 |
|
|
170
|
+
| `r2-cli goods hang-up upload-images --shop-id <id> --files <paths> --json` | 批量上传图片到闲鱼(挂售前必须先上传) |
|
|
171
|
+
| `r2-cli goods hang-up submit --shop-id <id> --title <> --price <> --category-id <> --channel-cat-id <> --image-ids <> --stuff-status <> --desc <> --out-item-no <> --json` | 提交挂售上架 |
|
|
172
|
+
|
|
173
|
+
**挂售必填参数**:`--shop-id`、`--title`、`--price`、`--category-id`(大分类 ID)、`--channel-cat-id`(小分类 ID)、`--image-ids`(图片 ID,逗号分隔)、`--stuff-status`(成色:100 全新 / -1 准新 / 99 99新 / 95 95新 / 90 9新)、`--desc`(商品描述)、`--out-item-no`(商家编码,同店铺唯一)
|
|
156
174
|
|
|
157
|
-
|
|
158
|
-
|------|------|------|
|
|
159
|
-
| `--stock-goods-id <id>` | 是 | 库存商品 ID(来自选品商品列表的 `stockGoodsId` 字段) |
|
|
160
|
-
| `--shop-id <id>` | 是 | 第三方店铺 ID(来自店铺列表的 `shopId` 字段,不是 `id`) |
|
|
161
|
-
| `--price <amount>` | 是 | 上架价格(正数) |
|
|
162
|
-
| `-p, --platform <platform>` | 否 | 平台,默认 xianyu |
|
|
163
|
-
| `--json` | 否 | JSON 输出(Agent 推荐) |
|
|
175
|
+
**挂售可选参数**:`--brand-name`、`--size`、`--goods-no`、`--original-price`、`--item-attrs`(属性列表 JSON)、`--trade-type`(默认 0 仅在线)、`--transport-fee`(默认 0 包邮)、`--yhb`(验货宝)、`--division-id`(默认 330100 杭州)
|
|
164
176
|
|
|
165
177
|
### 其他命令
|
|
166
178
|
|
package/dist/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
R2-CLI — 二手潮奢交易命令行工具,由 [Round2AI](https://github.com/Round2AI) 团队维护 — 让人类和 AI Agent 都能在终端中完成商品上架等交易操作。
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
覆盖商品上架、挂售、认证登录等核心业务域,提供 12 个命令及 3 个 AI Agent [Skills](./skills/)。
|
|
9
9
|
|
|
10
10
|
[安装](#安装与快速开始) · [AI Agent 快速开始](#快速开始ai-agent) · [Agent Skills](#agent-skills) · [认证](#认证) · [命令](#命令参考) · [安全](#安全与风险提示)
|
|
11
11
|
|
|
@@ -22,6 +22,7 @@ R2-CLI — 二手潮奢交易命令行工具,由 [Round2AI](https://github.com
|
|
|
22
22
|
|------|------|
|
|
23
23
|
| 认证登录 | 扫码登录(第二回合 APP / 微信 / 支付宝)、闲鱼店铺授权、状态查询、登出(Agent 一步式流程) |
|
|
24
24
|
| 商品管理 | 商品上架(4 步流程:获取店铺 → 获取仓库 → 获取选品商品 → 提交上架 + 自动轮询上架结果)、店铺查看、仓库查看、选品商品查看、上架列表查询、下架、改价 |
|
|
25
|
+
| 闲鱼挂售 | 完整商品信息模式:类目查询 → 属性/品牌选择 → 图片上传 → 提交挂售 |
|
|
25
26
|
|
|
26
27
|
---
|
|
27
28
|
|
|
@@ -114,9 +115,9 @@ npx skills add Round2AI/r2-cli --all -y
|
|
|
114
115
|
|
|
115
116
|
| Skill | 说明 |
|
|
116
117
|
|-------|------|
|
|
118
|
+
| `r2-shared` | 共享基础:安装、统一错误格式、命令概览 |
|
|
117
119
|
| `r2-auth` | 认证登录:一步式扫码登录(生成二维码 + 自动轮询,支持第二回合 APP / 微信 / 支付宝)、闲鱼店铺授权、状态查询、登出 |
|
|
118
|
-
| `r2-
|
|
119
|
-
| `r2-goods` | 商品管理:4 步上架流程(获取数据 → 展示给用户 → 用户选择 → 提交上架 + 自动轮询结果)、下架、改价、店铺/仓库/商品/上架列表查看 |
|
|
120
|
+
| `r2-goods` | 商品管理:4 步上架流程、挂售流程(类目→属性→图片→提交)、下架、改价、店铺/仓库/商品/上架列表查看 |
|
|
120
121
|
|
|
121
122
|
---
|
|
122
123
|
|
|
@@ -139,7 +140,7 @@ Token 存储在 `~/.r2-cli/config.json`(原子写入防丢失),过期后
|
|
|
139
140
|
|
|
140
141
|
## 命令参考
|
|
141
142
|
|
|
142
|
-
###
|
|
143
|
+
### 商品查询
|
|
143
144
|
|
|
144
145
|
| 命令 | 说明 |
|
|
145
146
|
|------|------|
|
|
@@ -147,20 +148,31 @@ Token 存储在 `~/.r2-cli/config.json`(原子写入防丢失),过期后
|
|
|
147
148
|
| `r2-cli goods stocks [--json]` | 查看所有仓库 |
|
|
148
149
|
| `r2-cli goods list [--stock-id <id>] [--stock-goods-id <id>] [--json]` | 查看选品商品(可按仓库或商品 ID 过滤,支持 `--page` 和 `--size`) |
|
|
149
150
|
| `r2-cli goods listing [--json]` | 查询上架列表(支持 `--id` / `--shop-id` / `--stock-goods-id` / `--stock-id` / `--status` / `--platform` 过滤) |
|
|
151
|
+
|
|
152
|
+
### 商品上架/下架
|
|
153
|
+
|
|
154
|
+
| 命令 | 说明 |
|
|
155
|
+
|------|------|
|
|
150
156
|
| `r2-cli goods up` | 交互式上架(自动轮询上架结果) |
|
|
151
157
|
| `r2-cli goods up --stock-goods-id <id> --shop-id <id> --price <amount> --json` | Agent 直接上架(自动轮询上架结果) |
|
|
152
158
|
| `r2-cli goods down --id <id> [--json]` | 下架商品(也可用 `--stock-goods-id <id> --shop-id <id>`) |
|
|
153
159
|
| `r2-cli goods price --id <id> --price <amount> [--json]` | 修改上架价格(也可用 `--stock-goods-id <id> --shop-id <id>`) |
|
|
154
160
|
|
|
155
|
-
###
|
|
161
|
+
### 闲鱼挂售(完整商品信息模式)
|
|
162
|
+
|
|
163
|
+
挂售模式支持完整的商品信息:图片、类目、属性、品牌等。流程:查询类目/属性 → 上传图片 → 提交挂售。
|
|
164
|
+
|
|
165
|
+
| 命令 | 说明 |
|
|
166
|
+
|------|------|
|
|
167
|
+
| `r2-cli goods hang-up categories [--json]` | 获取闲鱼类目列表(大分类 → 小分类) |
|
|
168
|
+
| `r2-cli goods hang-up props --channel-cat-id <id> [--json]` | 获取指定类目下的属性列表(含可选值) |
|
|
169
|
+
| `r2-cli goods hang-up brands --channel-cat-id <id> --prop-id <id> --key <keyword> [--json]` | 品牌搜索 |
|
|
170
|
+
| `r2-cli goods hang-up upload-images --shop-id <id> --files <paths> --json` | 批量上传图片到闲鱼(挂售前必须先上传) |
|
|
171
|
+
| `r2-cli goods hang-up submit --shop-id <id> --title <> --price <> --category-id <> --channel-cat-id <> --image-ids <> --stuff-status <> --desc <> --out-item-no <> --json` | 提交挂售上架 |
|
|
172
|
+
|
|
173
|
+
**挂售必填参数**:`--shop-id`、`--title`、`--price`、`--category-id`(大分类 ID)、`--channel-cat-id`(小分类 ID)、`--image-ids`(图片 ID,逗号分隔)、`--stuff-status`(成色:100 全新 / -1 准新 / 99 99新 / 95 95新 / 90 9新)、`--desc`(商品描述)、`--out-item-no`(商家编码,同店铺唯一)
|
|
156
174
|
|
|
157
|
-
|
|
158
|
-
|------|------|------|
|
|
159
|
-
| `--stock-goods-id <id>` | 是 | 库存商品 ID(来自选品商品列表的 `stockGoodsId` 字段) |
|
|
160
|
-
| `--shop-id <id>` | 是 | 第三方店铺 ID(来自店铺列表的 `shopId` 字段,不是 `id`) |
|
|
161
|
-
| `--price <amount>` | 是 | 上架价格(正数) |
|
|
162
|
-
| `-p, --platform <platform>` | 否 | 平台,默认 xianyu |
|
|
163
|
-
| `--json` | 否 | JSON 输出(Agent 推荐) |
|
|
175
|
+
**挂售可选参数**:`--brand-name`、`--size`、`--goods-no`、`--original-price`、`--item-attrs`(属性列表 JSON)、`--trade-type`(默认 0 仅在线)、`--transport-fee`(默认 0 包邮)、`--yhb`(验货宝)、`--division-id`(默认 330100 杭州)
|
|
164
176
|
|
|
165
177
|
### 其他命令
|
|
166
178
|
|
package/dist/r2-cli.js
CHANGED
|
@@ -1,47 +1,48 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
`;process.stdout.write(a)}finally{
|
|
3
|
+
var _e=Object.defineProperty;var tt=(e,t)=>()=>(e&&(t=e(e=0)),t);var et=(e,t)=>{for(var n in t)_e(e,n,{get:t[n],enumerable:!0})};var ee={};et(ee,{UserInfoCard:()=>co});import{Box as _,Text as E}from"ink";import{jsx as j,jsxs as M}from"react/jsx-runtime";function co({userInfo:e,lastLogin:t,daysSinceLogin:n}){let o=e.mobile?e.mobile.replace(/(\d{3})\d{4}(\d{4})/,"$1****$2"):"-";return M(_,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[j(E,{bold:!0,color:"cyan",children:"\u7528\u6237\u4FE1\u606F"}),M(_,{flexDirection:"row",marginTop:1,children:[j(_,{width:10,children:j(E,{color:"gray",children:"\u6635\u79F0"})}),j(E,{color:"yellow",children:e.nickname})]}),M(_,{flexDirection:"row",children:[j(_,{width:10,children:j(E,{color:"gray",children:"\u624B\u673A\u53F7"})}),j(E,{color:"yellow",children:o})]}),t&&M(_,{flexDirection:"column",marginTop:1,children:[M(E,{color:"gray",children:["\u6700\u540E\u767B\u5F55: ",t.toLocaleString()]}),n!==void 0&&M(E,{color:"gray",children:[" \u8DDD\u4ECA: ",n," \u5929"]})]})]})}var oe=tt(()=>{"use strict"});var at={};et(at,{renderComponent:()=>po,renderOnce:()=>ne});import lo from"react";import kt from"chalk";import{render as uo}from"ink";import{Writable as mo}from"node:stream";function ne(e){let t=kt.level;process.env.NO_COLOR||(kt.level=3);try{let n=[],o=new mo({write(c,u,d){n.push(Buffer.from(c)),d()}});o.isTTY=!0,o.columns=process.stdout.columns||80,o.rows=process.stdout.rows||24,uo(e,{stdout:o,patchConsole:!1}).unmount();let s=Buffer.concat(n).toString("utf8"),a=(s.split(/\x1B\[2J\x1B\[3J\x1B\[H/).at(-1)||s).replace(/\x1B\[\?[\d;]+[hl]/g,"").trimEnd()+`
|
|
4
|
+
`;process.stdout.write(a)}finally{kt.level=t}}function po(e,t){ne(lo.createElement(e,t))}var ct=tt(()=>{"use strict"});var Pe={};et(Pe,{ShopsTable:()=>Ro});import{Box as S,Text as A}from"ink";import{jsx as g,jsxs as z}from"react/jsx-runtime";function Ao(e){return e.map(t=>"shopName"in t?{id:t.shopId,name:t.shopName,platform:t.platform,expiresIn:t.expiresIn}:{id:t.id,name:t.name,platform:t.thirdUserId,expiresIn:t.expiresIn})}function vo({hasPlatform:e,fillWidth:t}){return z(S,{flexDirection:"row",paddingBottom:0,children:[e&&g(S,{width:qt,children:g(A,{bold:!0,color:"white",children:"\u5E73\u53F0"})}),g(S,{width:t,children:g(A,{bold:!0,color:"white",children:"\u5E97\u94FA\u540D"})}),g(S,{width:Bt,children:g(A,{bold:!0,color:"white",children:"ID"})}),g(S,{width:Gt,children:g(A,{bold:!0,color:"white",children:"\u72B6\u6001"})})]})}function ko({shop:e,hasPlatform:t,fillWidth:n}){let o=Ce[e.platform]??e.platform;return z(S,{flexDirection:"row",children:[t&&g(S,{width:qt,children:g(A,{color:"cyan",children:o})}),g(S,{width:n,children:g(A,{bold:!0,children:e.name})}),g(S,{width:Bt,children:g(A,{color:"gray",children:e.id})}),g(S,{width:Gt,children:g(A,{color:"green",children:"\u25CF \u6388\u6743\u4E2D"})})]})}function Ro({shops:e,platform:t}){let n=Ao(e),o=t==="all",r=t==="all"?"\u6240\u6709\u6388\u6743\u5E97\u94FA":`${Ce[t]??t}\u6388\u6743\u5E97\u94FA`,s=process.stdout.columns||80,i=4,a=Bt+Gt+(o?qt:0),c=Math.max(s-i-a,20),u=a+c;return z(S,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[z(S,{flexDirection:"row",children:[g(A,{bold:!0,color:"cyan",children:r}),z(A,{color:"gray",children:[" \xB7 ",n.length," \u5BB6"]})]}),z(S,{flexDirection:"column",marginTop:1,children:[g(vo,{hasPlatform:o,fillWidth:c}),g(A,{color:"gray",children:"\u2500".repeat(u)}),n.map(d=>g(ko,{shop:d,hasPlatform:o,fillWidth:c},d.id))]})]})}var Ce,qt,Bt,Gt,Te=tt(()=>{"use strict";Ce={xianyu:"\u95F2\u9C7C",douyin:"\u6296\u97F3"},qt=8,Bt=16,Gt=10});var ve={};et(ve,{StocksTable:()=>Uo});import{Box as h,Text as C}from"ink";import{jsx as m,jsxs as H}from"react/jsx-runtime";function Lo({fillWidth:e}){return H(h,{flexDirection:"row",paddingBottom:0,children:[m(h,{width:Jt,children:m(C,{bold:!0,color:"white",children:"ID"})}),m(h,{width:Xt,children:m(C,{bold:!0,color:"white",children:"\u7528\u6237ID"})}),m(h,{width:Qt,children:m(C,{bold:!0,color:"white",children:"\u4ED3\u5E93ID"})}),m(h,{width:e,children:m(C,{bold:!0,color:"white",children:"\u4ED3\u5E93\u540D\u79F0"})}),m(h,{width:_t,children:m(C,{bold:!0,color:"white",children:"\u521B\u5EFA\u65F6\u95F4"})})]})}function Oo({stock:e,fillWidth:t}){let n=new Date(e.gmtCreate).toLocaleString("zh-CN");return H(h,{flexDirection:"row",children:[m(h,{width:Jt,children:m(C,{color:"gray",children:e.id})}),m(h,{width:Xt,children:m(C,{color:"gray",children:e.userId})}),m(h,{width:Qt,children:m(C,{color:"gray",children:e.stockId})}),m(h,{width:t,children:m(C,{bold:!0,children:e.stockName})}),m(h,{width:_t,children:m(C,{color:"gray",children:n})})]})}function Uo({stocks:e}){let t=process.stdout.columns||80,n=4,o=Jt+Xt+Qt+_t,r=Math.max(t-n-o,20),s=o+r;return H(h,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[H(h,{flexDirection:"row",children:[m(C,{bold:!0,color:"cyan",children:"\u4ED3\u5E93\u5217\u8868"}),H(C,{color:"gray",children:[" \xB7 ",e.length," \u4E2A"]})]}),H(h,{flexDirection:"column",marginTop:1,children:[m(Lo,{fillWidth:r}),m(C,{color:"gray",children:"\u2500".repeat(s)}),e.map(i=>m(Oo,{stock:i,fillWidth:r},i.id))]})]})}var Jt,Xt,Qt,_t,ke=tt(()=>{"use strict";Jt=6,Xt=10,Qt=10,_t=22});import{Command as tn}from"commander";import{readFileSync as en}from"node:fs";import on from"node:path";import K from"chalk";import"commander";import{Command as le}from"commander";import f from"chalk";var G=class e extends Error{constructor(n,o,r){super(n);this.code=o;this.details=r;this.name="R2Error",Error.captureStackTrace&&Error.captureStackTrace(this,e)}code;details},T=class extends G{constructor(n,o,r){super(n,"API_ERROR",r);this.status=o;this.response=r;this.name="ApiError"}status;response},D=class extends G{constructor(n,o,r){super(n,"STORAGE_ERROR",{path:o,code:r});this.path=o;this.code=r;this.name="StorageError"}path;code},x=class extends G{constructor(t){super(t,"AUTH_ERROR"),this.name="AuthError"}},L=class extends G{constructor(n,o,r){super(n,"POLLING_ERROR",{attempts:o,timeout:r});this.attempts=o;this.timeout=r;this.name="PollingError"}attempts;timeout};async function Me(e,t,n){let o=new AbortController,r=()=>o.abort();n?.addEventListener("abort",r,{once:!0});let s=setTimeout(()=>o.abort(),t);try{return await e()}catch(i){throw o.signal.aborted&&!n?.aborted?new L("\u5355\u6B21\u8F6E\u8BE2\u8BF7\u6C42\u8D85\u65F6"):i}finally{clearTimeout(s),n?.removeEventListener("abort",r)}}async function J(e,t,n){let{interval:o,timeout:r,condition:s}=t,i=Date.now(),a=0;for(;Date.now()-i<r;){if(n?.aborted)throw new L("\u8F6E\u8BE2\u88AB\u4E2D\u6B62");a++;let c=r-(Date.now()-i),u=await Me(e,c,n);if(s(u,a))return u;await Fe(o,n)}throw new L(`\u8F6E\u8BE2\u8D85\u65F6 (\u5DF2\u7B49\u5F85 ${Date.now()-i}ms, \u5171 ${a} \u6B21)`)}function Fe(e,t){return new Promise((n,o)=>{if(t?.aborted){o(new L("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"));return}let r=()=>{clearTimeout(s),o(new L("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"))},s=setTimeout(()=>{t?.removeEventListener("abort",r),n()},e);t?.addEventListener("abort",r,{once:!0})})}import We from"node:fs";import{fileURLToPath as Ve}from"node:url";import{createRequire as Ke}from"node:module";import Wt from"node:path";import{exec as Ye}from"node:child_process";import ze from"node:http";var xt=class e{server=null;pages=new Map;port=0;idleTimer=null;static IDLE_TIMEOUT_MS=1e4;async start(){return this.server?this.port:new Promise((t,n)=>{this.server=ze.createServer((o,r)=>this.handleRequest(o,r)),this.server.listen(0,"127.0.0.1",()=>{let o=this.server.address();typeof o=="object"&&o?(this.port=o.port,t(this.port)):n(new Error("Failed to get server address"))}),this.server.on("error",n)})}registerPage(t,n,o,r){let s=this.pages.get(t);if(s){s.qrBuffer=o,s.status="waiting",s.config=r;let i=`data: ${JSON.stringify({status:"waiting"})}
|
|
5
5
|
|
|
6
|
-
`;for(let a of s.sseClients)a.write(i)}else this.pages.set(t,{html:
|
|
6
|
+
`;for(let a of s.sseClients)a.write(i)}else this.pages.set(t,{html:n,qrBuffer:o,status:"waiting",sseClients:[],config:r});this.resetIdleTimer()}unregisterPage(t){let n=this.pages.get(t);if(n){for(let o of n.sseClients)o.end();n.sseClients.length=0,this.pages.delete(t),this.pages.size===0&&this.close()}}setStatus(t,n){let o=this.pages.get(t);if(!o)return;o.status=n;let r=`data: ${JSON.stringify({status:n})}
|
|
7
7
|
|
|
8
|
-
`;for(let s of
|
|
8
|
+
`;for(let s of o.sseClients)s.write(r)}close(){if(this.server){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null);for(let t of this.pages.values()){for(let n of t.sseClients)n.end();t.sseClients.length=0}this.pages.clear(),this.server.close(),this.server=null,this.port=0,X=null}}resetIdleTimer(){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{[...this.pages.values()].some(n=>n.sseClients.length>0)||this.close()},e.IDLE_TIMEOUT_MS)}handleRequest(t,n){let o=t.url??"/";for(let[r,s]of this.pages){if(o===r){n.writeHead(302,{Location:r+"/"}),n.end();return}if(o===r+"/"){n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(s.html);return}if(o===r+"/qr.png"){n.writeHead(200,{"Content-Type":"image/png","Content-Length":s.qrBuffer.length}),n.end(s.qrBuffer);return}if(o===r+"/events"){n.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),n.write(`data: ${JSON.stringify({status:s.status})}
|
|
9
9
|
|
|
10
|
-
`),s.sseClients.push(
|
|
11
|
-
\u{1F50D} \u5DF2\u626B\u7801: ${
|
|
10
|
+
`),s.sseClients.push(n),t.on("close",()=>{let i=s.sseClients.indexOf(n);i>=0&&s.sseClients.splice(i,1)});return}if(o===r+"/config"){n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify(s.config??{}));return}}n.writeHead(404,{"Content-Type":"text/plain"}),n.end("Not Found")}},X=null,zt=!1;function ot(){X&&X.close()}function He(){zt||(zt=!0,process.on("exit",ot),process.on("SIGINT",ot),process.on("SIGTERM",ot),setInterval(()=>{process.stdin?.destroyed&&ot()},3e3).unref())}function Ht(){return X||(X=new xt,He()),X}var Ze=Wt.dirname(Ve(import.meta.url)),to="/login",eo="/login-xianyu",It=null;async function oo(e){return We.promises.readFile(Wt.join(Ze,"pages",e),"utf-8")}async function no(e){return It||(It=Ke(import.meta.url)),It("qrcode").toBuffer(e,{width:300,margin:2})}function R(e){let t=process.platform==="win32"?`start "" "${e}"`:process.platform==="darwin"?`open "${e}"`:`xdg-open "${e}"`;Ye(t)}async function Vt(e,t,n,o){let[r,s]=await Promise.all([oo(t),no(n)]),i=Ht(),a=await i.start();i.registerPage(e,r,s,o);let c=`http://127.0.0.1:${a}${e}/`;return{url:n,qrUrl:c,setStatus:u=>i.setStatus(e,u),closeServer:()=>i.unregisterPage(e)}}function St(e){return Vt(to,"login.html",e)}function Ct(e,t){return Vt(eo,"xianyu-auth.html",e,{authUrl:t})}import{promises as Q}from"node:fs";import Pt from"node:path";import ro from"node:os";var so=".r2-cli",nt=class{configPath;config;configLoaded=!1;dirEnsured=!1;constructor(){let t=ro.homedir(),n=Pt.join(t,so);this.configPath=Pt.join(n,"config.json"),this.config={credentials:null}}getConfigPath(){return this.configPath}async loadConfig(){if(this.configLoaded)return this.config;try{let t=await Q.readFile(this.configPath,"utf-8");return this.config=JSON.parse(t),this.configLoaded=!0,this.config}catch{return this.config={credentials:null},this.configLoaded=!0,this.config}}async ensureDir(){if(this.dirEnsured)return;let t=Pt.dirname(this.configPath);try{await Q.stat(t)}catch(n){if(n.code==="ENOENT")await Q.mkdir(t,{recursive:!0});else throw new D("Failed to create directory",t,n.code)}this.dirEnsured=!0}async saveConfig(t){this.config=t,await this.ensureDir();let n=JSON.stringify(t,null,2),o=this.configPath+".tmp";try{await Q.writeFile(o,n,"utf-8"),await Q.rename(o,this.configPath),this.configLoaded=!0}catch(r){throw await Q.unlink(o).catch(s=>{typeof process.env.DEBUG<"u"&&console.error("[config] cleanup tmp failed:",s)}),new D("Failed to save config",this.configPath,r.code)}}},Tt=null;function bt(){return Tt||(Tt=new nt),Tt}var vt=300*1e3,rt=class{store=bt();isTokenExpired(t){return t.expire?Date.now()>=t.expire-vt:!1}async saveCredentials(t,n){let o=Date.now(),r=n.expire?Number.parseInt(n.expire,10):0,s={token:t,userInfo:n,timestamp:o,...r>0&&{expire:o+r}},i=await this.store.loadConfig();i.credentials=s,await this.store.saveConfig(i)}async getCredentials(){let t=await this.store.loadConfig();return!t.credentials||this.isTokenExpired(t.credentials)?null:t.credentials}async clearCredentials(){let t=await this.store.loadConfig();t.credentials=null,await this.store.saveConfig(t)}async getToken(){return(await this.getCredentials())?.token??null}async getUserInfo(){return(await this.getCredentials())?.userInfo??null}async isLoggedIn(){return await this.getCredentials()!==null}},At=null;function Y(){return At||(At=new rt),At}var io="https://api.puresnake.com",st=class{config;authStorage=null;cachedToken=null;tokenExpiry=0;constructor(t={}){this.config={baseUrl:t.baseUrl??io,version:t.version??"v3",debug:t.debug??!1},this.authStorage=t.auth===!1?null:Y()}buildUrl(t){let n=t.startsWith("/")?t.slice(1):t;return`${this.config.baseUrl}/${this.config.version}/${n}`}async getAuthToken(){if(!this.authStorage)return;if(this.cachedToken&&Date.now()<this.tokenExpiry)return this.cachedToken;let t=await this.authStorage.getCredentials();if(!t)throw new x("\u8BF7\u5148\u8FD0\u884C r2-cli auth login \u767B\u5F55");return this.cachedToken=t.token,this.tokenExpiry=t.expire?t.expire-vt:Date.now()+1800*1e3,t.token}async requestFull(t,n){let o=this.buildUrl(t),{method:r,headers:s,body:i,timeout:a=3e4}=n,c=await this.getAuthToken(),u={...s,...c?{token:c}:{}},d=new AbortController,w=setTimeout(()=>d.abort(),a),q={method:r,headers:{"Content-Type":"application/json",...u},signal:d.signal};i!==void 0&&(q.body=JSON.stringify(i)),this.config.debug&&console.error(`[API ${r}]`,o,i);try{let l=await fetch(o,q);if(!l.ok){if(l.status===401)throw this.authStorage&&(this.cachedToken=null,await this.authStorage.clearCredentials().catch(B=>{console.error("[API] \u6E05\u9664\u51ED\u8BC1\u5931\u8D25:",B instanceof Error?B.message:String(B))})),new x("\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u8FD0\u884C r2-cli auth login \u91CD\u65B0\u767B\u5F55");let yt=await l.text();throw new T(yt||`${l.status} ${l.statusText}`,l.status)}let P=await l.json();if(this.config.debug&&console.error("[API Response]",P),!P.success||P.status!==0)throw new T(P.msg||"\u672A\u77E5\u9519\u8BEF",P.status,P);return P}catch(l){throw l instanceof DOMException&&l.name==="AbortError"?new T(`\u8BF7\u6C42\u8D85\u65F6 (${a}ms)`,408):l}finally{clearTimeout(w)}}async request(t,n){return(await this.requestFull(t,n)).data}async get(t,n,o){let r=n&&n.size>0?`${t}?${n.toString()}`:t;return this.request(r,{method:"GET",headers:o})}async post(t,n,o){return this.request(t,{method:"POST",body:n,headers:o})}async put(t,n,o){return this.request(t,{method:"PUT",body:n,headers:o})}async delete(t,n){return this.request(t,{method:"DELETE",headers:n})}async upload(t,n,o){let r=this.buildUrl(t),s=await this.getAuthToken(),i={...o,...s?{token:s}:{}},a=new AbortController,c=setTimeout(()=>a.abort(),6e4),u={method:"POST",headers:i,body:n,signal:a.signal};this.config.debug&&console.error("[API UPLOAD]",r);try{let d=await fetch(r,u);if(!d.ok){if(d.status===401)throw this.authStorage&&(this.cachedToken=null,await this.authStorage.clearCredentials().catch(()=>{})),new x("\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u8FD0\u884C r2-cli auth login \u91CD\u65B0\u767B\u5F55");let q=await d.text();throw new T(q||`${d.status} ${d.statusText}`,d.status)}let w=await d.json();if(this.config.debug&&console.error("[API Response]",w),!w.success||w.status!==0)throw new T(w.msg||"\u672A\u77E5\u9519\u8BEF",w.status,w);return w.data}catch(d){throw d instanceof DOMException&&d.name==="AbortError"?new T("\u4E0A\u4F20\u8D85\u65F6 (60000ms)",408):d}finally{clearTimeout(c)}}},it=new st,Kt=new st({auth:!1});var Yt=Kt;async function Zt(){return Yt.post("app/qrcode/generate")}async function te(e){let t=new URLSearchParams;t.append("qrToken",e);let n=`app/qrcode/status?${t.toString()}`,o=await Yt.requestFull(n,{method:"GET"});return o.token&&typeof o.data=="object"&&o.data!==null&&(o.data.token=o.token),o.data}async function re(e,t,n){let{UserInfoCard:o}=await Promise.resolve().then(()=>(oe(),ee)),{renderComponent:r}=await Promise.resolve().then(()=>(ct(),at)),s=t!=null?{userInfo:e,lastLogin:t,daysSinceLogin:n??0}:{userInfo:e};r(o,s)}var lt=class{storage;constructor(t){this.storage=t??Y()}async generateQR(){let t=await Zt(),n=`https://m.puresnake.com/r2/auth/login?qrToken=${t.qrContent}&from=wechat`,o=await St(n);return{qrData:t,...o}}async waitForLogin(t,n,o,r,s,i){let a=await J(()=>te(t),{interval:o,timeout:n,condition:c=>{switch(c.status){case"scanned":return i||(console.log(f.cyan(`
|
|
11
|
+
\u{1F50D} \u5DF2\u626B\u7801: ${c.userInfo?.nickname||"\u672A\u77E5\u7528\u6237"}`)),console.log(f.yellow("\u8BF7\u5728 APP \u4E0A\u786E\u8BA4\u767B\u5F55"))),s?.("scanning"),!1;case"confirmed":return i||console.log(f.green(`
|
|
12
12
|
\u2705 \u7528\u6237\u5DF2\u786E\u8BA4\u767B\u5F55`)),s?.("success"),!0;case"expired":return i||console.log(f.red(`
|
|
13
13
|
\u23F0 \u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F`)),s?.("expired"),!0;case"canceled":return i||console.log(f.red(`
|
|
14
|
-
\u{1F6AB} \u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55`)),s?.("expired"),!0;default:return!1}}},
|
|
15
|
-
\u{1F510} \u6B63\u5728\u542F\u52A8\u626B\u7801\u767B\u5F55...`));let{qrData:
|
|
16
|
-
`)),console.log(f.cyan(` \u94FE\u63A5: ${
|
|
17
|
-
`)),
|
|
18
|
-
`));let i=Number.parseInt(
|
|
14
|
+
\u{1F6AB} \u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55`)),s?.("expired"),!0;default:return!1}}},r??void 0);if(a.status==="confirmed"&&a.token&&a.userInfo)return await this.storage.saveCredentials(a.token,a.userInfo),{userInfo:a.userInfo,token:a.token};throw a.status==="expired"?new x("\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55"):a.status==="canceled"?new x("\u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55"):new x("\u767B\u5F55\u5931\u8D25: \u672A\u83B7\u53D6\u5230\u51ED\u8BC1")}async login(t){console.log(f.cyan(`
|
|
15
|
+
\u{1F510} \u6B63\u5728\u542F\u52A8\u626B\u7801\u767B\u5F55...`));let{qrData:n,qrUrl:o,setStatus:r,closeServer:s}=await this.generateQR();console.log(f.green(`\u2705 \u4E8C\u7EF4\u7801\u5DF2\u751F\u6210
|
|
16
|
+
`)),console.log(f.cyan(` \u94FE\u63A5: ${o}
|
|
17
|
+
`)),R(o),console.log(f.yellow(`\u23F3 \u7B49\u5F85\u626B\u7801...
|
|
18
|
+
`));let i=Number.parseInt(n.expireTime,10),a=Number.parseInt(n.pollInterval,10);try{let c=await this.waitForLogin(n.qrToken,i,a,t,r);return console.log(f.green(`
|
|
19
19
|
\u2705 \u767B\u5F55\u6210\u529F\uFF01
|
|
20
|
-
`)),
|
|
20
|
+
`)),re(c.userInfo),c}catch(c){throw console.log(f.red(`
|
|
21
21
|
\u274C \u767B\u5F55\u5931\u8D25
|
|
22
|
-
`)),
|
|
22
|
+
`)),c}finally{s()}}async logout(){console.log(f.cyan(`
|
|
23
23
|
\u{1F6AA} \u6B63\u5728\u9000\u51FA\u767B\u5F55...`)),await this.storage.clearCredentials(),console.log(f.green(`\u2705 \u5DF2\u9000\u51FA\u767B\u5F55
|
|
24
24
|
`))}async status(){if(!await this.storage.isLoggedIn()){console.log(f.yellow(`\u26A0\uFE0F \u5C1A\u672A\u767B\u5F55\u6216\u51ED\u8BC1\u5DF2\u8FC7\u671F
|
|
25
|
-
`));return}let
|
|
26
|
-
`)),await
|
|
27
|
-
\u2705 \u6388\u6743\u6210\u529F\uFF01\u5E97\u94FA: ${s.shopName} (${s.shopId})`)),
|
|
28
|
-
\u23F0 \u6388\u6743\u94FE\u63A5\u5DF2\u8FC7\u671F`)),
|
|
29
|
-
\u{1F517} \u6B63\u5728\u83B7\u53D6\u95F2\u9C7C\u6388\u6743\u5730\u5740...`));let{authData:t,qrUrl:
|
|
30
|
-
`)),console.log(
|
|
25
|
+
`));return}let n=await this.storage.getCredentials(),o=n.userInfo,r=new Date(n.timestamp),s=Math.floor((Date.now()-n.timestamp)/(1e3*60*60*24));console.log(f.green(`\u2705 \u5DF2\u767B\u5F55
|
|
26
|
+
`)),await re(o,r,s)}},Rt=null;function N(){return Rt||(Rt=new lt),Rt}import $ from"chalk";var se=it;async function ie(){return se.get("mms/xianyu/auth/url")}async function ae(e){let t=new URLSearchParams({state:e});return se.get("mms/xianyu/auth/status",t)}async function dt(){let e=await ie(),t=await Ct(e.url,e.url);return{authData:e,...t}}async function Z(e,t,n,o,r){return J(()=>ae(e),{interval:n,timeout:t,condition:s=>s.status==="success"?(console.log($.green(`
|
|
27
|
+
\u2705 \u6388\u6743\u6210\u529F\uFF01\u5E97\u94FA: ${s.shopName} (${s.shopId})`)),r?.("success"),!0):s.status==="expired"?(console.log($.red(`
|
|
28
|
+
\u23F0 \u6388\u6743\u94FE\u63A5\u5DF2\u8FC7\u671F`)),r?.("expired"),!0):!1},o)}async function Nt(e){console.log($.cyan(`
|
|
29
|
+
\u{1F517} \u6B63\u5728\u83B7\u53D6\u95F2\u9C7C\u6388\u6743\u5730\u5740...`));let{authData:t,qrUrl:n,setStatus:o,closeServer:r}=await dt();console.log($.green(`\u2705 \u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210
|
|
30
|
+
`)),console.log($.cyan(` \u94FE\u63A5: ${n}`)),console.log($.gray(` \u6216\u590D\u5236\u94FE\u63A5\u6253\u5F00: ${t.url}`)),R(n),console.log($.yellow(`
|
|
31
31
|
\u23F3 \u7B49\u5F85\u6388\u6743...
|
|
32
|
-
`));let s=t.expireTime?Number.parseInt(t.expireTime,10):3e5,i=t.pollInterval?Number.parseInt(t.pollInterval,10):1e3;try{let a=await
|
|
33
|
-
\u25B2 ${e.message}`)),console.error(
|
|
34
|
-
`));else if(e instanceof
|
|
35
|
-
`));else{let t=e instanceof Error?e.message:String(e);console.error(L.red(`\u25B2 ${t}`))}process.exit(1)}function vt(e){console.log(JSON.stringify({success:!1,error:e})),process.exit(1)}function it(e){return async(...t)=>{try{await e(...t)}catch(o){let r=o instanceof Error?o.message:String(o);vt(r)}}}var no=new Set(["accessToken","refreshExpireIn"]);function re(e){return e.map(t=>{let o={};for(let[r,n]of Object.entries(t))no.has(r)||(o[r]=n);return o})}function bt(){let e=new ne("login");e.description("\u626B\u7801\u767B\u5F55 Round2AI \u8D26\u6237").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");let t=new ne("poll").description("\u8F6E\u8BE2\u767B\u5F55\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--token <qrToken>","\u4E8C\u7EF4\u7801 token").option("--expire <ms>","\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09","300000").option("--interval <ms>","\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09","1000").action(it(async o=>{let n=await k().waitForLogin(o.token,Number.parseInt(o.expire,10),Number.parseInt(o.interval,10));console.log(JSON.stringify({success:!0,...n}))}));return e.addCommand(t),e.action(async o=>{try{if(o.json){let r=k(),{qrData:n,qrUrl:s,setStatus:i,closeServer:a}=await r.generateQR(),l=Number.parseInt(n.expireTime,10),d=Number.parseInt(n.pollInterval,10);console.log(JSON.stringify({qrToken:n.qrToken,expireTimeMs:l,pollIntervalMs:d,url:`https://m.puresnake.com/r2/auth/login?qrToken=${n.qrContent}&from=wechat`,qrUrl:s},null,2)),P(s);try{let g=await r.waitForLogin(n.qrToken,l,d,void 0,i,!0);console.log(JSON.stringify({success:!0,userInfo:g.userInfo}))}catch(g){let $=g instanceof Error?g.message:String(g);console.log(JSON.stringify({success:!1,error:$}))}finally{setTimeout(a,1e3)}}else await k().login()}catch(r){if(o.json){let n=r instanceof Error?r.message:String(r);console.log(JSON.stringify({success:!1,error:n})),process.exit(1)}m(r)}}),e}import{Command as so}from"commander";function At(){let e=new so("logout");return e.description("\u9000\u51FA\u767B\u5F55"),e.action(async()=>{try{await k().logout()}catch(t){m(t)}}),e}import{Command as io}from"commander";function Lt(){let e=new io("status");return e.description("\u67E5\u770B\u767B\u5F55\u72B6\u6001"),e.action(async()=>{try{await k().status()}catch(t){m(t)}}),e}import{Command as se}from"commander";function Rt(){let e=new se("xianyu");e.description("\u95F2\u9C7C\u5E97\u94FA\u6388\u6743").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");let t=new se("poll").description("\u8F6E\u8BE2\u95F2\u9C7C\u6388\u6743\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--state <state>","\u6388\u6743\u8F6E\u8BE2 token").option("--expire <ms>","\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09","300000").option("--interval <ms>","\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09","1000").action(it(async o=>{let r=await H(o.state,Number.parseInt(o.expire,10),Number.parseInt(o.interval,10));r.status==="success"?console.log(JSON.stringify({success:!0,shopId:r.shopId,shopName:r.shopName})):vt(`\u6388\u6743\u72B6\u6001: ${r.status}`)}));return e.addCommand(t),e.action(async o=>{try{if(o.json){let{authData:r,qrUrl:n,setStatus:s,closeServer:i}=await st(),a=r.expireTime?Number.parseInt(r.expireTime,10):3e5,l=r.pollInterval?Number.parseInt(r.pollInterval,10):1e3;console.log(JSON.stringify({state:r.state,expireTimeMs:a,pollIntervalMs:l,qrUrl:n},null,2)),P(n);try{let d=await H(r.state,a,l,void 0,s);d.status==="success"?console.log(JSON.stringify({success:!0,shopId:d.shopId,shopName:d.shopName})):(console.log(JSON.stringify({success:!1,error:`\u6388\u6743\u72B6\u6001: ${d.status}`})),process.exit(1))}catch(d){let g=d instanceof Error?d.message:String(d);console.log(JSON.stringify({success:!1,error:g})),process.exit(1)}finally{setTimeout(i,1e3)}}else await kt()}catch(r){if(o.json){let n=r instanceof Error?r.message:String(r);console.log(JSON.stringify({success:!1,error:n})),process.exit(1)}m(r)}}),e}import{Command as Lo}from"commander";import{Command as ao}from"commander";import I from"chalk";import{select as Ot,input as co,confirm as lo}from"@inquirer/prompts";var R=new A;function Nt(e){let t=new URLSearchParams;for(let[o,r]of Object.entries(e))r!=null&&r!==""&&t.append(o,String(r));return t}async function Et(e){return R.post("mms/goods/listing/up/xianyu",e)}async function ie(e){return R.get("mms/goods/listing/get",Nt({...e}))}async function ae(e){return R.post("mms/goods/listing/down/xianyu",e)}async function ce(e){return R.post("mms/goods/listing/update/xyPrice",e)}async function le(e){return R.get("mms/goods/listing/list",e?Nt({...e}):void 0)}async function at(){return await R.get("mms/user/shop/list")??[]}async function ct(){return await R.get("mms/user/stock/list")??[]}async function lt(e){let t=e?Nt({...e}):void 0;return R.get("mms/seller/goods/select/list",t)}var mo=2e3,uo=1e4;function po(e){let t=e.status?.toLowerCase()??"";return t===""||t==="init"||t==="pending"||t==="processing"}async function me(e,t,o,r){r||process.stdout.write(I.cyan("\u23F3 \u6B63\u5728\u67E5\u8BE2\u4E0A\u67B6\u8FDB\u5EA6..."));let n=await B(()=>ie({stockGoodsId:e,shopId:t,platform:o}),{interval:mo,timeout:uo,condition:s=>!po(s)});return r||process.stdout.write("\r"+" ".repeat(30)+"\r"),n}function ue(){let e=new ao("up");return e.description("\u4E0A\u67B6\u5546\u54C1\u5230\u95F2\u9C7C"),e.option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1ID\uFF08\u4ECE goods list \u83B7\u53D6\uFF09").option("--shop-id <id>","\u5E97\u94FAID\uFF08\u4ECE goods shops \u83B7\u53D6\uFF09").option("--price <amount>","\u4E0A\u67B6\u4EF7\u683C").option("-p, --platform <platform>","\u5E73\u53F0","xianyu").option("--json","\u8F93\u51FA JSON\uFF08Agent \u7528\uFF09").action(async t=>{try{if(t.stockGoodsId&&t.shopId&&t.price){let c=Number(t.stockGoodsId),S=t.shopId,dt=Number(t.price),j=t.platform,Ee=await Et({stockGoodsId:c,shopId:S,price:dt,platform:j}),pt=await me(c,S,j,t.json);if(t.json)console.log(JSON.stringify({success:!0,data:{submit:Ee,listing:pt}},null,2));else{let Oe=pt.status?.toLowerCase()!=="failed";console.log(Oe?I.green("\u2713 \u4E0A\u67B6\u6210\u529F"):I.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify(pt,null,2))}return}let o=await at();if(o.length===0){console.log(I.yellow("\u6CA1\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF0C\u8BF7\u5148\u8FD0\u884C r2-cli auth xianyu \u6388\u6743"));return}let r=await Ot({message:"\u9009\u62E9\u5E97\u94FA",choices:o.map(c=>({name:`${c.shopName} (${c.platform})`,value:c.shopId}))}),n=await ct();if(n.length===0){console.log(I.yellow("\u6CA1\u6709\u53EF\u7528\u7684\u4ED3\u5E93"));return}let s=await Ot({message:"\u9009\u62E9\u4ED3\u5E93",choices:n.map(c=>({name:c.stockName,value:c.stockId}))}),i=await lt({stockId:s,size:100});if(!i.items?.length){console.log(I.yellow("\u8BE5\u4ED3\u5E93\u6CA1\u6709\u53EF\u9009\u7684\u5546\u54C1"));return}let a=await Ot({message:"\u9009\u62E9\u5546\u54C1",choices:i.items.map(c=>({name:`${c.goodsName} ${c.size?`| ${c.size}`:""} | \xA5${c.salePrice}`,value:c.stockGoodsId}))}),l=await co({message:"\u8F93\u5165\u4E0A\u67B6\u4EF7\u683C",default:i.items.find(c=>c.stockGoodsId===a)?.salePrice?.toString()??"",validate:c=>Number(c)>0?!0:"\u4EF7\u683C\u5FC5\u987B\u4E3A\u6B63\u6570"});if(!await lo({message:`\u786E\u8BA4\u4E0A\u67B6\uFF1F\u4EF7\u683C \xA5${l}`,default:!0})){console.log(I.gray("\u5DF2\u53D6\u6D88"));return}let g=Number(a);await Et({stockGoodsId:g,shopId:r,price:Number(l),platform:"xianyu"}),console.log(I.green("\u2713 \u4E0A\u67B6\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u67E5\u8BE2\u8FDB\u5EA6..."));let $=await me(g,r,"xianyu"),K=$.status?.toLowerCase()!=="failed";console.log(K?I.green("\u2713 \u4E0A\u67B6\u6210\u529F"):I.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify($,null,2))}catch(o){m(o)}}),e}import{Command as wo}from"commander";import fe from"chalk";function he(){let e=new wo("shops");return e.description("\u67E5\u770B\u6240\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF08\u8DE8\u5E73\u53F0\uFF09"),e.option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(async t=>{try{let o=await at();if(t.json){console.log(JSON.stringify(re(o),null,2));return}if(!o.length){console.log(fe.yellow("\u672A\u627E\u5230\u5DF2\u6388\u6743\u7684\u5E97\u94FA")),console.log(fe.gray(" \u63D0\u793A: \u8BF7\u5148\u5728\u7B2C\u4E8C\u56DE\u5408 APP \u4E2D\u6388\u6743\u5E97\u94FA"));return}let{ShopsTable:r}=await Promise.resolve().then(()=>(ge(),pe)),{renderComponent:n}=await Promise.resolve().then(()=>(rt(),ot));n(r,{shops:o,platform:"all"})}catch(o){m(o)}}),e}import{Command as Io}from"commander";import To from"chalk";function xe(){let e=new Io("stocks");return e.description("\u67E5\u770B\u6240\u6709\u4ED3\u5E93"),e.option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(async t=>{try{let o=await ct();if(t.json){console.log(JSON.stringify(o,null,2));return}if(!o.length){console.log(To.yellow("\u672A\u627E\u5230\u4ED3\u5E93\u4FE1\u606F"));return}let{StocksTable:r}=await Promise.resolve().then(()=>(we(),ye)),{renderComponent:n}=await Promise.resolve().then(()=>(rt(),ot));n(r,{stocks:o})}catch(o){m(o)}}),e}import{Command as Po}from"commander";import F from"chalk";function Se(){let e=new Po("list");return e.description("\u67E5\u770B\u4ED3\u5E93\u4E2D\u7684\u9009\u54C1\u5546\u54C1"),e.option("--stock-id <id>","\u4ED3\u5E93 ID\uFF08\u4ECE goods stocks \u83B7\u53D6\uFF09").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--page <n>","\u9875\u7801","1").option("--size <n>","\u6BCF\u9875\u6570\u91CF","20").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(async t=>{try{let r=await lt({stockId:t.stockId||void 0,stockGoodsId:t.stockGoodsId||void 0,page:Number(t.page)||1,size:Number(t.size)||20})??{items:[],total:0};if(t.json){r.items?.length?console.log(JSON.stringify(r,null,2)):console.log(JSON.stringify({...r,hint:"\u9009\u54C1\u5546\u54C1\u4E3A\u7A7A\uFF0C\u8BF7\u5148\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E\u540E\u518D\u8BD5"},null,2));return}if(!r.items?.length){console.log(F.yellow("\u6682\u65E0\u9009\u54C1\u5546\u54C1\uFF0C\u8BF7\u5148\u7ED1\u5B9A\u4ED3\u5E93\u6216\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E"));return}console.log(F.cyan(`
|
|
36
|
-
\u9009\u54C1\u5546\u54C1\uFF08\u5171 ${
|
|
37
|
-
`));for(let
|
|
38
|
-
`));for(let
|
|
39
|
-
\
|
|
40
|
-
|
|
41
|
-
\
|
|
42
|
-
\
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
`))}function
|
|
47
|
-
\
|
|
32
|
+
`));let s=t.expireTime?Number.parseInt(t.expireTime,10):3e5,i=t.pollInterval?Number.parseInt(t.pollInterval,10):1e3;try{let a=await Z(t.state,s,i,e,o);if(a.status==="success")return a;throw new x("\u95F2\u9C7C\u6388\u6743\u5931\u8D25: "+(a.status==="expired"?"\u94FE\u63A5\u5DF2\u8FC7\u671F":"\u672A\u77E5\u72B6\u6001"))}finally{r()}}import O from"chalk";function b(e){if(e instanceof x)console.error(O.red(`
|
|
33
|
+
\u25B2 ${e.message}`)),console.error(O.gray(`\u2192 \u8BF7\u5148\u8FD0\u884C: r2-cli auth login
|
|
34
|
+
`));else if(e instanceof T)console.error(O.red(`\u25B2 \u64CD\u4F5C\u5931\u8D25: ${e.message}`)),e.status&&console.error(O.gray(` \u72B6\u6001\u7801: ${e.status}`));else if(e instanceof D)console.error(O.red(`\u25B2 \u914D\u7F6E\u6587\u4EF6\u5F02\u5E38: ${e.message}`)),e.path&&console.error(O.gray(` \u8DEF\u5F84: ${e.path}`)),console.error(O.gray(`\u2192 \u8BF7\u5C1D\u8BD5\u91CD\u65B0\u767B\u5F55: r2-cli auth login
|
|
35
|
+
`));else{let t=e instanceof Error?e.message:String(e);console.error(O.red(`\u25B2 ${t}`))}process.exit(1)}function Lt(e){console.log(JSON.stringify({success:!1,error:e})),process.exit(1)}function p(e){return async t=>{try{await e(t)}catch(n){if(t.json){let o=n instanceof Error?n.message:String(n);console.log(JSON.stringify({success:!1,error:o})),process.exit(1)}b(n)}}}function ut(e){return async(...t)=>{try{await e(...t)}catch(n){let o=n instanceof Error?n.message:String(n);Lt(o)}}}var fo=new Set(["accessToken","refreshExpireIn"]);function ce(e){return e.map(t=>{let n={};for(let[o,r]of Object.entries(t))fo.has(o)||(n[o]=r);return n})}function Ot(){let e=new le("login");e.description("\u626B\u7801\u767B\u5F55 Round2AI \u8D26\u6237").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");let t=new le("poll").description("\u8F6E\u8BE2\u767B\u5F55\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--token <qrToken>","\u4E8C\u7EF4\u7801 token").option("--expire <ms>","\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09","300000").option("--interval <ms>","\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09","1000").action(ut(async n=>{let r=await N().waitForLogin(n.token,Number.parseInt(n.expire,10),Number.parseInt(n.interval,10));console.log(JSON.stringify({success:!0,...r}))}));return e.addCommand(t),e.action(async n=>{try{if(n.json){let o=N(),{qrData:r,qrUrl:s,setStatus:i,closeServer:a}=await o.generateQR(),c=Number.parseInt(r.expireTime,10),u=Number.parseInt(r.pollInterval,10);console.log(JSON.stringify({qrToken:r.qrToken,expireTimeMs:c,pollIntervalMs:u,url:`https://m.puresnake.com/r2/auth/login?qrToken=${r.qrContent}&from=wechat`,qrUrl:s},null,2)),R(s);try{let d=await o.waitForLogin(r.qrToken,c,u,void 0,i,!0);console.log(JSON.stringify({success:!0,userInfo:d.userInfo}))}catch(d){let w=d instanceof Error?d.message:String(d);console.log(JSON.stringify({success:!1,error:w}))}finally{setTimeout(a,1e3)}}else await N().login()}catch(o){if(n.json){let r=o instanceof Error?o.message:String(o);console.log(JSON.stringify({success:!1,error:r})),process.exit(1)}b(o)}}),e}import{Command as ho}from"commander";function Ut(){let e=new ho("logout");return e.description("\u9000\u51FA\u767B\u5F55"),e.action(async()=>{try{await N().logout()}catch(t){b(t)}}),e}import{Command as yo}from"commander";function Dt(){let e=new yo("status");return e.description("\u67E5\u770B\u767B\u5F55\u72B6\u6001"),e.action(async()=>{try{await N().status()}catch(t){b(t)}}),e}import{Command as de}from"commander";function Et(){let e=new de("xianyu");e.description("\u95F2\u9C7C\u5E97\u94FA\u6388\u6743").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");let t=new de("poll").description("\u8F6E\u8BE2\u95F2\u9C7C\u6388\u6743\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--state <state>","\u6388\u6743\u8F6E\u8BE2 token").option("--expire <ms>","\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09","300000").option("--interval <ms>","\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09","1000").action(ut(async n=>{let o=await Z(n.state,Number.parseInt(n.expire,10),Number.parseInt(n.interval,10));o.status==="success"?console.log(JSON.stringify({success:!0,shopId:o.shopId,shopName:o.shopName})):Lt(`\u6388\u6743\u72B6\u6001: ${o.status}`)}));return e.addCommand(t),e.action(async n=>{try{if(n.json){let{authData:o,qrUrl:r,setStatus:s,closeServer:i}=await dt(),a=o.expireTime?Number.parseInt(o.expireTime,10):3e5,c=o.pollInterval?Number.parseInt(o.pollInterval,10):1e3;console.log(JSON.stringify({state:o.state,expireTimeMs:a,pollIntervalMs:c,qrUrl:r},null,2)),R(r);try{let u=await Z(o.state,a,c,void 0,s);u.status==="success"?console.log(JSON.stringify({success:!0,shopId:u.shopId,shopName:u.shopName})):(console.log(JSON.stringify({success:!1,error:`\u6388\u6743\u72B6\u6001: ${u.status}`})),process.exit(1))}catch(u){let d=u instanceof Error?u.message:String(u);console.log(JSON.stringify({success:!1,error:d})),process.exit(1)}finally{setTimeout(i,1e3)}}else await Nt()}catch(o){if(n.json){let r=o instanceof Error?o.message:String(o);console.log(JSON.stringify({success:!1,error:r})),process.exit(1)}b(o)}}),e}import{Command as Xo}from"commander";import{Command as Io}from"commander";import v from"chalk";import{select as $t,input as So,confirm as Co}from"@inquirer/prompts";import{readFileSync as wo}from"node:fs";import{basename as xo}from"node:path";var I=it;function F(e){let t=new URLSearchParams;for(let[n,o]of Object.entries(e))o!=null&&o!==""&&t.append(n,String(o));return t}async function jt(e){return I.post("mms/goods/listing/up/xianyu",e)}async function ue(e){return I.get("mms/goods/listing/get",F({...e}))}async function me(e){return I.post("mms/goods/listing/down/xianyu",e)}async function pe(e){return I.post("mms/goods/listing/update/xyPrice",e)}async function ge(e){return I.get("mms/goods/listing/list",e?F({...e}):void 0)}async function mt(){return await I.get("mms/user/shop/list")??[]}async function pt(){return await I.get("mms/user/stock/list")??[]}async function gt(e){let t=e?F({...e}):void 0;return I.get("mms/seller/goods/select/list",t)}async function fe(e,t){let n=[];for(let o of t){let r=wo(o),s=xo(o),i=new FormData;i.append("file",new Blob([r]),s);let a=await I.upload(`platform/xy/media/upload?shopId=${encodeURIComponent(e)}`,i);n.push(a)}return n}async function he(e){return I.post("mms/goods/listing/hang/up/xianyu",e)}async function ye(e=16){return await I.get("platform/xy/cat",F({spBizType:e}))??[]}async function we(e){return await I.get("platform/xy/props",F({channelCatId:e}))??[]}async function xe(e,t,n){return await I.get("platform/xy/props/value",F({channelCatId:e,propId:t,key:n}))??[]}var Po=2e3,To=1e4;function bo(e){let t=e.status?.toLowerCase()??"";return t===""||t==="init"||t==="pending"||t==="processing"}async function Ie(e,t,n,o){o||process.stdout.write(v.cyan("\u23F3 \u6B63\u5728\u67E5\u8BE2\u4E0A\u67B6\u8FDB\u5EA6..."));let r=await J(()=>ue({stockGoodsId:e,shopId:t,platform:n}),{interval:Po,timeout:To,condition:s=>!bo(s)});return o||process.stdout.write("\r"+" ".repeat(30)+"\r"),r}function Se(){let e=new Io("up");return e.description("\u4E0A\u67B6\u5546\u54C1\u5230\u95F2\u9C7C"),e.option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1ID\uFF08\u4ECE goods list \u83B7\u53D6\uFF09").option("--shop-id <id>","\u5E97\u94FAID\uFF08\u4ECE goods shops \u83B7\u53D6\uFF09").option("--price <amount>","\u4E0A\u67B6\u4EF7\u683C").option("-p, --platform <platform>","\u5E73\u53F0","xianyu").option("--json","\u8F93\u51FA JSON\uFF08Agent \u7528\uFF09").action(p(async t=>{if(t.json&&!(t.stockGoodsId&&t.shopId&&t.price)&&(console.log(JSON.stringify({success:!1,error:"Agent \u6A21\u5F0F\u9700\u8981 --stock-goods-id, --shop-id, --price"})),process.exit(1)),t.stockGoodsId&&t.shopId&&t.price){let l=Number(t.stockGoodsId),P=t.shopId,yt=Number(t.price),B=t.platform,Xe=await jt({stockGoodsId:l,shopId:P,price:yt,platform:B}),wt=await Ie(l,P,B,t.json);if(t.json)console.log(JSON.stringify({success:!0,data:{submit:Xe,listing:wt}},null,2));else{let Qe=wt.status?.toLowerCase()!=="failed";console.log(Qe?v.green("\u2713 \u4E0A\u67B6\u6210\u529F"):v.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify(wt,null,2))}return}let n=await mt();if(n.length===0){console.log(v.yellow("\u6CA1\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF0C\u8BF7\u5148\u8FD0\u884C r2-cli auth xianyu \u6388\u6743"));return}let o=await $t({message:"\u9009\u62E9\u5E97\u94FA",choices:n.map(l=>({name:`${l.shopName} (${l.platform})`,value:l.shopId}))}),r=await pt();if(r.length===0){console.log(v.yellow("\u6CA1\u6709\u53EF\u7528\u7684\u4ED3\u5E93"));return}let s=await $t({message:"\u9009\u62E9\u4ED3\u5E93",choices:r.map(l=>({name:l.stockName,value:l.stockId}))}),i=await gt({stockId:s,size:100});if(!i.items?.length){console.log(v.yellow("\u8BE5\u4ED3\u5E93\u6CA1\u6709\u53EF\u9009\u7684\u5546\u54C1"));return}let a=await $t({message:"\u9009\u62E9\u5546\u54C1",choices:i.items.map(l=>({name:`${l.goodsName} ${l.size?`| ${l.size}`:""} | \xA5${l.salePrice}`,value:l.stockGoodsId}))}),c=await So({message:"\u8F93\u5165\u4E0A\u67B6\u4EF7\u683C",default:i.items.find(l=>l.stockGoodsId===a)?.salePrice?.toString()??"",validate:l=>Number(l)>0?!0:"\u4EF7\u683C\u5FC5\u987B\u4E3A\u6B63\u6570"});if(!await Co({message:`\u786E\u8BA4\u4E0A\u67B6\uFF1F\u4EF7\u683C \xA5${c}`,default:!0})){console.log(v.gray("\u5DF2\u53D6\u6D88"));return}let d=Number(a);await jt({stockGoodsId:d,shopId:o,price:Number(c),platform:"xianyu"}),console.log(v.green("\u2713 \u4E0A\u67B6\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u67E5\u8BE2\u8FDB\u5EA6..."));let w=await Ie(d,o,"xianyu"),q=w.status?.toLowerCase()!=="failed";console.log(q?v.green("\u2713 \u4E0A\u67B6\u6210\u529F"):v.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify(w,null,2))})),e}import{Command as No}from"commander";import be from"chalk";function Ae(){let e=new No("shops");return e.description("\u67E5\u770B\u6240\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF08\u8DE8\u5E73\u53F0\uFF09"),e.option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(p(async t=>{let n=await mt();if(t.json){console.log(JSON.stringify(ce(n),null,2));return}if(!n.length){console.log(be.yellow("\u672A\u627E\u5230\u5DF2\u6388\u6743\u7684\u5E97\u94FA")),console.log(be.gray(" \u63D0\u793A: \u8BF7\u5148\u5728\u7B2C\u4E8C\u56DE\u5408 APP \u4E2D\u6388\u6743\u5E97\u94FA"));return}let{ShopsTable:o}=await Promise.resolve().then(()=>(Te(),Pe)),{renderComponent:r}=await Promise.resolve().then(()=>(ct(),at));r(o,{shops:n,platform:"all"})})),e}import{Command as Do}from"commander";import Eo from"chalk";function Re(){let e=new Do("stocks");return e.description("\u67E5\u770B\u6240\u6709\u4ED3\u5E93"),e.option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(p(async t=>{let n=await pt();if(t.json){console.log(JSON.stringify(n,null,2));return}if(!n.length){console.log(Eo.yellow("\u672A\u627E\u5230\u4ED3\u5E93\u4FE1\u606F"));return}let{StocksTable:o}=await Promise.resolve().then(()=>(ke(),ve)),{renderComponent:r}=await Promise.resolve().then(()=>(ct(),at));r(o,{stocks:n})})),e}import{Command as jo}from"commander";import W from"chalk";function Ne(){let e=new jo("list");return e.description("\u67E5\u770B\u4ED3\u5E93\u4E2D\u7684\u9009\u54C1\u5546\u54C1"),e.option("--stock-id <id>","\u4ED3\u5E93 ID\uFF08\u4ECE goods stocks \u83B7\u53D6\uFF09").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--page <n>","\u9875\u7801","1").option("--size <n>","\u6BCF\u9875\u6570\u91CF","20").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(p(async t=>{let o=await gt({stockId:t.stockId||void 0,stockGoodsId:t.stockGoodsId||void 0,page:Number(t.page)||1,size:Number(t.size)||20})??{items:[],total:0};if(t.json){o.items?.length?console.log(JSON.stringify(o,null,2)):console.log(JSON.stringify({...o,hint:"\u9009\u54C1\u5546\u54C1\u4E3A\u7A7A\uFF0C\u8BF7\u5148\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E\u540E\u518D\u8BD5"},null,2));return}if(!o.items?.length){console.log(W.yellow("\u6682\u65E0\u9009\u54C1\u5546\u54C1\uFF0C\u8BF7\u5148\u7ED1\u5B9A\u4ED3\u5E93\u6216\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E"));return}console.log(W.cyan(`
|
|
36
|
+
\u9009\u54C1\u5546\u54C1\uFF08\u5171 ${o.total} \u4EF6\uFF0C\u7B2C ${o.page} \u9875\uFF09
|
|
37
|
+
`));for(let r of o.items)console.log(` ${W.bold(r.goodsName)} ${r.size?W.gray(`| ${r.size}`):""}`),console.log(` \u54C1\u724C: ${r.brand} \u5EFA\u8BAE\u552E\u4EF7: \xA5${r.salePrice} stockGoodsId: ${W.green(r.stockGoodsId)}`),console.log(W.gray(` \u5206\u7C7B: ${r.cate1Name} > ${r.cate2Name} > ${r.cate3Name}`)),console.log()})),e}import{Command as $o}from"commander";import Le from"chalk";var qo={init:"\u5F85\u4E0A\u67B6",up:"\u5DF2\u4E0A\u67B6",down:"\u5DF2\u4E0B\u67B6",fail:"\u5931\u8D25"};function Oe(){let e=new $o("listing");return e.description("\u67E5\u8BE2\u4E0A\u67B6\u5546\u54C1\u5217\u8868"),e.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--stock-id <id>","\u4ED3\u5E93 ID").option("-s, --status <status>","\u72B6\u6001\u8FC7\u6EE4\uFF08init/up/down/fail\uFF09").option("-p, --platform <platform>","\u5E73\u53F0","xianyu").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(p(async t=>{let o=await ge({id:t.id,stockGoodsId:t.stockGoodsId?Number(t.stockGoodsId):void 0,shopId:t.shopId,stockId:t.stockId,status:t.status,platform:t.platform})??{list:[],total:0};if(t.json){o.list?.length?console.log(JSON.stringify(o,null,2)):console.log(JSON.stringify({...o,hint:"\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"},null,2));return}if(!o.list?.length){console.log(Le.yellow("\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"));return}console.log(Le.green(`\u2705 \u5171 ${o.total} \u6761\u8BB0\u5F55
|
|
38
|
+
`));for(let r of o.list){let s=qo[r.status]??r.status;console.log(` ID: ${r.id} | \u72B6\u6001: ${s} | \u4EF7\u683C: ${r.price} | stockGoodsId: ${r.stockGoodsId}`)}})),e}import{Command as Bo}from"commander";import Mt from"chalk";function Ue(){let e=new Bo("down");return e.description("\u4E0B\u67B6\u95F2\u9C7C\u5546\u54C1"),e.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(p(async t=>{if(!t.id&&!(t.stockGoodsId&&t.shopId)){t.json&&(console.log(JSON.stringify({success:!1,error:"\u8BF7\u6307\u5B9A\u4E0B\u67B6\u6761\u4EF6\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"})),process.exit(1)),console.log(Mt.yellow("\u8BF7\u6307\u5B9A\u4E0B\u67B6\u6761\u4EF6\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));return}let n={};t.id&&(n.id=t.id),t.stockGoodsId&&(n.stockGoodsId=Number(t.stockGoodsId)),t.shopId&&(n.shopId=t.shopId),t.json||console.log(Mt.cyan("\u{1F4E6} \u6B63\u5728\u4E0B\u67B6\u5546\u54C1..."));let o=await me(n);t.json?console.log(JSON.stringify({success:!0,data:o},null,2)):(console.log(Mt.green("\u2705 \u4E0B\u67B6\u6210\u529F")),console.log(JSON.stringify(o,null,2)))})),e}import{Command as Go}from"commander";import ft from"chalk";function De(){let e=new Go("price");return e.description("\u4FEE\u6539\u95F2\u9C7C\u4E0A\u67B6\u5546\u54C1\u4EF7\u683C"),e.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--price <amount>","\u65B0\u4EF7\u683C\uFF08\u5FC5\u586B\uFF09").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(p(async t=>{if(!t.price){t.json&&(console.log(JSON.stringify({success:!1,error:"--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570"})),process.exit(1)),console.log(ft.yellow("--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570"));return}if(!t.id&&!(t.stockGoodsId&&t.shopId)){t.json&&(console.log(JSON.stringify({success:!1,error:"\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"})),process.exit(1)),console.log(ft.yellow("\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));return}let n={price:Number(t.price)};t.id&&(n.id=t.id),t.stockGoodsId&&(n.stockGoodsId=Number(t.stockGoodsId)),t.shopId&&(n.shopId=t.shopId),t.json||console.log(ft.cyan(`\u{1F4B0} \u6B63\u5728\u4FEE\u6539\u4EF7\u683C\u4E3A ${t.price}...`));let o=await pe(n);t.json?console.log(JSON.stringify({success:!0,data:o},null,2)):(console.log(ft.green("\u2705 \u4EF7\u683C\u4FEE\u6539\u6210\u529F")),console.log(JSON.stringify(o,null,2)))})),e}import{Command as V}from"commander";import y from"chalk";var Jo={100:"\u5168\u65B0",[-1]:"\u51C6\u65B0",99:"99\u65B0",95:"95\u65B0",90:"9\u65B0"};function Ee(){let e=new V("hang-up");return e.description("\u95F2\u9C7C\u6302\u552E\u4E0A\u67B6\uFF08\u5B8C\u6574\u5546\u54C1\u4FE1\u606F\u6A21\u5F0F\uFF09"),e.addCommand(new V("categories").description("\u83B7\u53D6\u95F2\u9C7C\u7C7B\u76EE\u5217\u8868\uFF08\u5927\u5206\u7C7B \u2192 \u5C0F\u5206\u7C7B\uFF09").option("--sp-biz-type <n>","\u4E1A\u52A1\u5206\u7C7B\uFF0C16=\u5962\u54C1","16").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(p(async t=>{let n=await ye(Number(t.spBizType));if(t.json){console.log(JSON.stringify(n,null,2));return}let o=new Map;for(let r of n){let s=String(r.catId);o.has(s)||o.set(s,{catName:r.catName,children:[]}),o.get(s).children.push({channel:r.channel,channelCatId:r.channelCatId})}for(let[,r]of o){console.log(y.bold(r.catName));for(let s of r.children)console.log(` ${s.channel} (channelCatId: ${y.green(s.channelCatId)})`)}}))),e.addCommand(new V("props").description("\u83B7\u53D6\u6307\u5B9A\u7C7B\u76EE\u4E0B\u7684\u5C5E\u6027\u5217\u8868\uFF08\u542B\u53EF\u9009\u503C\uFF09").requiredOption("--channel-cat-id <id>","\u5C0F\u5206\u7C7B ID\uFF08\u4ECE categories \u83B7\u53D6\uFF09").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(p(async t=>{let n=await we(t.channelCatId);if(t.json){console.log(JSON.stringify(n,null,2));return}for(let o of n)if(console.log(y.bold(`
|
|
39
|
+
${o.propName} (propId: ${o.propId})`)),o.propsValues?.length)for(let r of o.propsValues)console.log(` ${r.valueName} (valueId: ${r.valueId})`);else console.log(y.gray(" \uFF08\u4F7F\u7528 brands \u5B50\u547D\u4EE4\u641C\u7D22\uFF09"))}))),e.addCommand(new V("brands").description("\u641C\u7D22\u95F2\u9C7C\u54C1\u724C\uFF08\u6309\u5173\u952E\u5B57\u8FC7\u6EE4\uFF09").requiredOption("--channel-cat-id <id>","\u5C0F\u5206\u7C7B ID").requiredOption("--prop-id <id>","\u5C5E\u6027 ID\uFF08\u54C1\u724C\u5C5E\u6027\u7684 propId\uFF09").requiredOption("--key <keyword>","\u641C\u7D22\u5173\u952E\u5B57").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(p(async t=>{let n=await xe(t.channelCatId,t.propId,t.key);if(t.json){console.log(JSON.stringify(n,null,2));return}if(!n.length){console.log(y.yellow("\u672A\u627E\u5230\u5339\u914D\u7684\u54C1\u724C"));return}for(let o of n)console.log(` ${o.valueName} (valueId: ${o.valueId})`)}))),e.addCommand(new V("upload-images").description("\u6279\u91CF\u4E0A\u4F20\u56FE\u7247\u5230\u95F2\u9C7C\uFF08\u6302\u552E\u524D\u5FC5\u987B\u5148\u4E0A\u4F20\u56FE\u7247\uFF09").requiredOption("--shop-id <id>","\u5E97\u94FA ID").requiredOption("--files <paths>","\u56FE\u7247\u6587\u4EF6\u8DEF\u5F84\uFF0C\u9017\u53F7\u5206\u9694").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(p(async t=>{let n=t.files.split(",").map(r=>r.trim()).filter(Boolean);if(n.length===0){t.json&&(console.log(JSON.stringify({success:!1,error:"\u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u5F20\u56FE\u7247"})),process.exit(1)),console.log(y.yellow("\u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u5F20\u56FE\u7247"));return}t.json||console.log(y.cyan(`\u6B63\u5728\u4E0A\u4F20 ${n.length} \u5F20\u56FE\u7247...`));let o=await fe(t.shopId,n);if(t.json)console.log(JSON.stringify({success:!0,images:o},null,2));else{console.log(y.green(`\u4E0A\u4F20\u6210\u529F\uFF0C\u5171 ${o.length} \u5F20`));for(let r of o)console.log(` \u56FE\u7247ID: ${r.value}`)}}))),e.addCommand(new V("submit").description("\u63D0\u4EA4\u6302\u552E\u4E0A\u67B6").requiredOption("--shop-id <id>","\u5E97\u94FA ID\uFF08\u5373\u95F2\u9C7C\u7528\u6237\u540D account\uFF09").requiredOption("--title <title>","\u5546\u54C1\u6807\u9898").requiredOption("--price <amount>","\u552E\u4EF7").requiredOption("--category-id <id>","\u5927\u5206\u7C7B ID\uFF08\u4ECE categories \u83B7\u53D6\uFF09").requiredOption("--channel-cat-id <id>","\u5C0F\u5206\u7C7B ID\uFF08\u4ECE categories \u83B7\u53D6\uFF09").requiredOption("--image-ids <ids>","\u56FE\u7247 ID \u5217\u8868\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u5148\u901A\u8FC7 upload-images \u83B7\u53D6\uFF09").requiredOption("--stuff-status <n>","\u6210\u8272\uFF1A100 \u5168\u65B0 / -1 \u51C6\u65B0 / 99 99\u65B0 / 95 95\u65B0 / 90 9\u65B0").option("--item-attrs <json>",'\u5546\u54C1\u5C5E\u6027\u5217\u8868 JSON\uFF0C\u683C\u5F0F: [{"propId":"x","valueId":"y","valueName":"z"}]').option("--brand-name <name>","\u54C1\u724C\u540D\u79F0").option("--desc <desc>","\u5546\u54C1\u63CF\u8FF0").option("--size <size>","\u5C3A\u7801").option("--goods-no <no>","\u8D27\u53F7").option("--original-price <amount>","\u539F\u4EF7").option("--trade-type <n>","\u4EA4\u6613\u65B9\u5F0F\uFF1A0 \u4EC5\u5728\u7EBF / 1 \u4EC5\u7EBF\u4E0B / 2 \u7EBF\u4E0A\u6216\u7EBF\u4E0B","0").option("--transport-fee <amount>","\u8FD0\u8D39\uFF08\u9ED8\u8BA4 0 \u5305\u90AE\uFF09","0").option("--yhb","\u662F\u5426\u5F00\u542F\u9A8C\u8D27\u5B9D").requiredOption("--out-item-no <no>","\u5546\u5BB6\u7F16\u7801\uFF08\u540C\u5E97\u94FA\u552F\u4E00\uFF0C\u7528\u6237\u81EA\u5B9A\u4E49\uFF09").option("--division-id <id>","\u884C\u653F\u533A\u5212 ID\uFF08\u5E02\u7EA7 ID\uFF0C\u9ED8\u8BA4\u676D\u5DDE 330100\uFF09","330100").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(p(async t=>{let n=t.imageIds.split(",").map(s=>s.trim()),o={account:t.shopId,title:t.title,reservePrice:Number(t.price),categoryId:Number(t.categoryId),channelCatId:t.channelCatId,imageIdList:n,stuffStatus:Number(t.stuffStatus),itemBizType:2,spBizType:"16",tradeType:Number(t.tradeType)||0,transportFee:Number(t.transportFee)||0,yhb:t.yhb??!1,...t.brandName&&{brandName:t.brandName},...t.desc&&{desc:t.desc},...t.size&&{size:t.size},...t.goodsNo&&{goodsNo:t.goodsNo},...t.originalPrice&&{originalPrice:Number(t.originalPrice)},outItemNo:t.outItemNo,divisionId:Number(t.divisionId)||330100,apiAfterSalesDo:{supportFd10msPolicy:!1,supportFd24hsPolicy:!0,supportNfrPolicy:!0,supportSdrPolicy:!0,supportVnrPolicy:!1,supportGpaPolicy:!1,supportFd48hsPolicy:!1},...t.itemAttrs&&{itemAttrList:JSON.parse(t.itemAttrs)}};t.json||(console.log(y.cyan("\u6B63\u5728\u63D0\u4EA4\u6302\u552E...")),console.log(y.gray(` \u6807\u9898: ${o.title}`)),console.log(y.gray(` \u552E\u4EF7: \xA5${o.reservePrice}`)),console.log(y.gray(` \u6210\u8272: ${Jo[o.stuffStatus]??o.stuffStatus}`)),console.log(y.gray(` \u56FE\u7247: ${n.length} \u5F20`)),o.itemAttrList?.length&&console.log(y.gray(` \u5C5E\u6027: ${o.itemAttrList.length} \u9879`)));let r=await he(o);t.json?console.log(JSON.stringify({success:!0,data:r},null,2)):(console.log(y.green("\u6302\u552E\u63D0\u4EA4\u6210\u529F")),console.log(JSON.stringify(r,null,2)))}))),e}function je(){let e=new Xo("goods");return e.description("\u5546\u54C1\u7BA1\u7406"),e.addCommand(Ae()),e.addCommand(Re()),e.addCommand(Ne()),e.addCommand(Oe()),e.addCommand(Ue()),e.addCommand(De()),e.addCommand(Se()),e.addCommand(Ee()),e}import{Command as Qo}from"commander";import k from"chalk";import{promises as _o}from"node:fs";import Mo from"node:path";import Fo from"node:os";import{spawn as zo}from"node:child_process";var ht="@round2ai/r2-cli";function $e(){let e=new Qo("uninstall");return e.description("\u5378\u8F7D R2-CLI \u5E76\u6E05\u9664\u6240\u6709\u914D\u7F6E"),e.action(async()=>{try{console.log(k.yellow(`
|
|
40
|
+
\u26A0\uFE0F \u5373\u5C06\u6267\u884C\u4EE5\u4E0B\u64CD\u4F5C\uFF1A`)),console.log(k.gray(" 1. \u5220\u9664\u914D\u7F6E\u76EE\u5F55 ~/.r2-cli/")),console.log(k.gray(` 2. \u5168\u5C40\u5378\u8F7D ${ht}
|
|
41
|
+
`));let{confirm:t}=await import("@inquirer/prompts");if(!await t({message:"\u786E\u8BA4\u5378\u8F7D\uFF1F",default:!1})){console.log(k.gray("\u5DF2\u53D6\u6D88\u5378\u8F7D"));return}let o=Mo.join(Fo.homedir(),".r2-cli");try{await _o.rm(o,{recursive:!0,force:!0}),console.log(k.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u6E05\u9664"))}catch{console.log(k.yellow("\u26A0\uFE0F \u914D\u7F6E\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u65E0\u6CD5\u5220\u9664\uFF08\u53EF\u5FFD\u7565\uFF09"))}console.log(k.cyan(`\u6B63\u5728\u5378\u8F7D ${ht}...`)),zo("npm",["uninstall","-g",ht],{stdio:"inherit",shell:!0}).on("exit",s=>{s===0?console.log(k.green(`
|
|
42
|
+
\u2705 ${ht} \u5DF2\u5378\u8F7D`)):(console.log(k.yellow(`
|
|
43
|
+
\u26A0\uFE0F npm \u5378\u8F7D\u5931\u8D25 (exit code: ${s})`)),console.log(k.gray(" \u5982\u901A\u8FC7 yarn/pnpm \u5B89\u88C5\uFF0C\u8BF7\u624B\u52A8\u5378\u8F7D"))),process.exit(s??1)})}catch(t){b(t)}}),e}function qe(e){let t=e.command("auth").description("\u6388\u6743\u7BA1\u7406");t.addCommand(Ot()),t.addCommand(Ut()),t.addCommand(Dt()),t.addCommand(Et()),e.addCommand(je()),e.addCommand($e())}import Be from"chalk";var Ft="@round2ai/r2-cli",Ho=[`https://registry.npmmirror.com/${encodeURIComponent(Ft)}/latest`,`https://registry.npmjs.org/${encodeURIComponent(Ft)}/latest`],Wo=5e3;async function Vo(e){let t=new AbortController,n=setTimeout(()=>t.abort(),Wo);try{let o=await fetch(e,{signal:t.signal});return o.ok?(await o.json()).version??null:null}catch{return null}finally{clearTimeout(n)}}async function Ko(){let e=await Promise.allSettled(Ho.map(Vo));for(let t of e)if(t.status==="fulfilled"&&t.value)return t.value;return null}function Yo(e,t){let n=e.split(".").map(Number),o=t.split(".").map(Number);for(let r=0;r<3;r++)if((n[r]??0)!==(o[r]??0))return(n[r]??0)>(o[r]??0);return!1}async function Ge(e){let t=await Ko();t&&Yo(t,e)&&Zo(e,t)}function Zo(e,t){console.error(Be.yellow(`
|
|
44
|
+
Update available: ${e} \u2192 ${t}`)+Be.gray(`
|
|
45
|
+
Run: npm update -g ${Ft}
|
|
46
|
+
`))}async function nn(){let{default:e}=await import("figlet");console.log(K.cyan.bold(e.textSync("R2-CLI",{font:"Standard",horizontalLayout:"full"}))),console.log(K.gray(` \u5411 AI \u5F00\u653E\u4E8C\u624B\u6F6E\u5962\u4EA4\u6613\u5168\u94FE\u8DEF\u80FD\u529B
|
|
47
|
+
`))}function rn(){let e=new tn;e.name("r2-cli").description("R2-CLI\uFF0C\u5411 AI \u5F00\u653E\u4E8C\u624B\u6F6E\u5962\u4EA4\u6613\u5168\u94FE\u8DEF\u80FD\u529B");let t="0.0.0";for(let o of["../package.json","../../package.json"])try{t=JSON.parse(en(on.join(import.meta.dirname,o),"utf-8")).version;break}catch{}t==="0.0.0"&&console.error(K.yellow("Warning: unable to read version from package.json")),e.version(t,"-v, --version");let n=Ge(t);return e.configureOutput({writeErr:o=>{console.error(K.red(o.replace("error:","").trim()))}}),e.action(async()=>{await nn(),e.help()}),qe(e),{program:e,updateCheckPromise:n}}function Je(){console.log(K.gray(`
|
|
48
|
+
\u64CD\u4F5C\u5DF2\u53D6\u6D88`)),process.exit(130)}process.on("SIGINT",Je);process.on("SIGTERM",Je);var{program:sn,updateCheckPromise:an}=rn();sn.parse(process.argv);an.catch(e=>{console.error(K.gray(`[update-check] ${e instanceof Error?e.message:String(e)}`))});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@round2ai/r2-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12-beta.0",
|
|
4
4
|
"description": "R2-CLI,向 AI 开放二手潮奢交易全链路能力",
|
|
5
5
|
"main": "dist/r2-cli.js",
|
|
6
6
|
"type": "module",
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
"postinstall": "node scripts/install-skills.js",
|
|
12
12
|
"build": "cross-env NODE_ENV=development node scripts/build.js",
|
|
13
13
|
"build:prod": "cross-env NODE_ENV=production node scripts/build.js",
|
|
14
|
-
"dev": "node scripts/dev.js"
|
|
14
|
+
"dev": "node scripts/dev.js",
|
|
15
|
+
"test": "vitest run",
|
|
16
|
+
"test:watch": "vitest"
|
|
15
17
|
},
|
|
16
18
|
"keywords": [
|
|
17
19
|
"round2ai",
|
|
@@ -25,7 +27,7 @@
|
|
|
25
27
|
],
|
|
26
28
|
"files": [
|
|
27
29
|
"dist",
|
|
28
|
-
"scripts",
|
|
30
|
+
"scripts/install-skills.js",
|
|
29
31
|
"skills",
|
|
30
32
|
"package.json",
|
|
31
33
|
"README.md"
|
|
@@ -56,6 +58,7 @@
|
|
|
56
58
|
"cross-env": "^10.1.0",
|
|
57
59
|
"dotenv": "^17.4.2",
|
|
58
60
|
"esbuild": "^0.28.0",
|
|
59
|
-
"typescript": "^6.0.2"
|
|
61
|
+
"typescript": "^6.0.2",
|
|
62
|
+
"vitest": "^4.1.5"
|
|
60
63
|
}
|
|
61
64
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* postinstall: 将 skills/ 复制到 ~/.agents/skills/
|
|
2
|
+
* postinstall: 将 skills/ 复制到 ~/.agents/skills/
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import fs from "node:fs";
|
|
@@ -10,7 +10,6 @@ import { fileURLToPath } from "node:url";
|
|
|
10
10
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
11
|
const pkgSkillsDir = path.join(__dirname, "..", "skills");
|
|
12
12
|
const agentsDir = path.join(os.homedir(), ".agents", "skills");
|
|
13
|
-
const claudeDir = path.join(os.homedir(), ".claude", "skills");
|
|
14
13
|
|
|
15
14
|
if (!fs.existsSync(pkgSkillsDir)) process.exit(0);
|
|
16
15
|
|
|
@@ -18,13 +17,11 @@ fs.mkdirSync(agentsDir, { recursive: true });
|
|
|
18
17
|
|
|
19
18
|
for (const name of fs.readdirSync(pkgSkillsDir)) {
|
|
20
19
|
const rawSrc = path.join(pkgSkillsDir, name);
|
|
21
|
-
// npm 包内是真实目录,本地开发可能是 symlink → 解析真实路径
|
|
22
20
|
let src;
|
|
23
21
|
try { src = fs.realpathSync(rawSrc); } catch { continue; }
|
|
24
22
|
if (!fs.statSync(src).isDirectory()) continue;
|
|
25
23
|
|
|
26
24
|
const dest = path.join(agentsDir, name);
|
|
27
|
-
// 清空目标目录中的旧残留文件
|
|
28
25
|
if (fs.existsSync(dest)) {
|
|
29
26
|
for (const old of fs.readdirSync(dest)) {
|
|
30
27
|
fs.unlinkSync(path.join(dest, old));
|
|
@@ -35,20 +32,4 @@ for (const name of fs.readdirSync(pkgSkillsDir)) {
|
|
|
35
32
|
for (const file of fs.readdirSync(src)) {
|
|
36
33
|
fs.copyFileSync(path.join(src, file), path.join(dest, file));
|
|
37
34
|
}
|
|
38
|
-
|
|
39
|
-
// 确保 ~/.claude/skills/<name> 指向 ~/.agents/skills/<name>
|
|
40
|
-
const link = path.join(claudeDir, name);
|
|
41
|
-
if (!fs.existsSync(link)) {
|
|
42
|
-
fs.mkdirSync(claudeDir, { recursive: true });
|
|
43
|
-
const target = dest;
|
|
44
|
-
try {
|
|
45
|
-
fs.symlinkSync(target, link, "junction");
|
|
46
|
-
} catch {
|
|
47
|
-
// Windows 权限不足时 fallback:直接复制
|
|
48
|
-
fs.mkdirSync(link, { recursive: true });
|
|
49
|
-
for (const file of fs.readdirSync(dest)) {
|
|
50
|
-
fs.copyFileSync(path.join(dest, file), path.join(link, file));
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
35
|
}
|