@skillbuilder/minitool-cli 0.0.0-beta-20261027053041051 → 0.0.0-stage
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 +2 -184
- package/package.json +4 -46
- package/bin/redminitool.js +0 -176
- package/lib/bootstrap.js +0 -69
- package/lib/commands/auth/identity.js +0 -98
- package/lib/commands/auth/index.js +0 -20
- package/lib/commands/auth/login.js +0 -148
- package/lib/commands/auth/logout.js +0 -52
- package/lib/commands/auth/storage.js +0 -105
- package/lib/commands/dev/dev.test.js +0 -108
- package/lib/commands/dev.js +0 -119
- package/lib/commands/index.js +0 -19
- package/lib/commands/minitool/cli.test.js +0 -222
- package/lib/commands/minitool/commands.test.js +0 -119
- package/lib/commands/minitool/common.js +0 -103
- package/lib/commands/minitool/config.js +0 -51
- package/lib/commands/minitool/edit.js +0 -55
- package/lib/commands/minitool/history.js +0 -56
- package/lib/commands/minitool/index.js +0 -24
- package/lib/commands/minitool/list.js +0 -65
- package/lib/commands/minitool/preview.js +0 -115
- package/lib/commands/minitool/status.js +0 -55
- package/lib/commands/minitool/submit.js +0 -58
- package/lib/commands/minitool/upload.js +0 -80
- package/lib/core/base.js +0 -133
- package/lib/decorators/auth.js +0 -26
- package/lib/decorators/captureError.js +0 -32
- package/lib/decorators/constants.js +0 -11
- package/lib/decorators/decorators.test.js +0 -94
- package/lib/decorators/index.js +0 -21
- package/lib/decorators/injectParams.js +0 -30
- package/lib/decorators/json-output.js +0 -18
- package/lib/decorators/params/common.js +0 -21
- package/lib/decorators/params/index.js +0 -24
- package/lib/index.js +0 -18
- package/lib/main.js +0 -26
- package/lib/mcp.js +0 -197
- package/lib/output.js +0 -7
- package/lib/ui.js +0 -39
- package/lib/utils/agent-check.js +0 -157
- package/lib/utils/templates.js +0 -75
- package/types/bootstrap.d.ts +0 -14
- package/types/commands/auth/identity.d.ts +0 -9
- package/types/commands/auth/index.d.ts +0 -4
- package/types/commands/auth/login.d.ts +0 -13
- package/types/commands/auth/logout.d.ts +0 -7
- package/types/commands/auth/storage.d.ts +0 -14
- package/types/commands/dev/dev.test.d.ts +0 -1
- package/types/commands/dev.d.ts +0 -8
- package/types/commands/index.d.ts +0 -3
- package/types/commands/minitool/cli.test.d.ts +0 -1
- package/types/commands/minitool/commands.test.d.ts +0 -1
- package/types/commands/minitool/common.d.ts +0 -12
- package/types/commands/minitool/config.d.ts +0 -5
- package/types/commands/minitool/edit.d.ts +0 -20
- package/types/commands/minitool/history.d.ts +0 -5
- package/types/commands/minitool/index.d.ts +0 -8
- package/types/commands/minitool/list.d.ts +0 -5
- package/types/commands/minitool/preview.d.ts +0 -23
- package/types/commands/minitool/status.d.ts +0 -5
- package/types/commands/minitool/submit.d.ts +0 -25
- package/types/commands/minitool/upload.d.ts +0 -20
- package/types/core/base.d.ts +0 -37
- package/types/decorators/auth.d.ts +0 -1
- package/types/decorators/captureError.d.ts +0 -1
- package/types/decorators/constants.d.ts +0 -7
- package/types/decorators/decorators.test.d.ts +0 -1
- package/types/decorators/index.d.ts +0 -5
- package/types/decorators/injectParams.d.ts +0 -1
- package/types/decorators/json-output.d.ts +0 -2
- package/types/decorators/params/common.d.ts +0 -10
- package/types/decorators/params/index.d.ts +0 -5
- package/types/index.d.ts +0 -2
- package/types/main.d.ts +0 -5
- package/types/mcp.d.ts +0 -9
- package/types/output.d.ts +0 -4
- package/types/ui.d.ts +0 -4
- package/types/utils/agent-check.d.ts +0 -16
- package/types/utils/templates.d.ts +0 -17
package/README.md
CHANGED
|
@@ -1,185 +1,3 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Temporary Holding Version
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
CLI 和 MCP 共用 `minitool-core` 的 DI 业务服务;平台接口与扫码协议参考 `skill-cli` 的 `feat-pipline-auth` 分支重新实现。
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## 命令总览
|
|
8
|
-
|
|
9
|
-
业务命令可直接从顶层使用,例如 `redminitool list`;原有 `redminitool minitool list` 等分组入口继续兼容,参数与 Core 服务完全共用。
|
|
10
|
-
|
|
11
|
-
| 命令 | 用途 | 关键选项 |
|
|
12
|
-
| --- | --- | --- |
|
|
13
|
-
| `login` | 扫码登录或取消等待 | `--env beta`、`--cancel` |
|
|
14
|
-
| `whoami` | 查看当前创作者身份 | `--env beta` |
|
|
15
|
-
| `logout` | 清理当前环境登录态 | `--env beta` |
|
|
16
|
-
| `dev` | 启动本地调试工作台 | `--dir ./dist`、`--no-open` |
|
|
17
|
-
| `config` | 查询类目与权限编码 | `--source` |
|
|
18
|
-
| `list` | 分页查询小工具 | `--source`、`--page-num`、`--page-size` |
|
|
19
|
-
| `status` | 查询当前版本与审核状态 | `--source`、`--app-id` |
|
|
20
|
-
| `history` | 查询历史版本 | `--source`、`--app-id` |
|
|
21
|
-
| `upload` | 上传代码包或图片 | `--file`、`--type pkg\|image` |
|
|
22
|
-
| `preview` | 创建手机预览 | `--source`、`--file`、`--qr-out` |
|
|
23
|
-
| `submit` | 提交新工具或新版本审核 | `--source`、`--file` |
|
|
24
|
-
| `edit` | 更新完整基础资料 | `--source`、`--file` |
|
|
25
|
-
|
|
26
|
-
用 `redminitool <命令> --help` 查看全部参数。上传、预览、提审、编辑支持 `--dry-run`;实际执行通过交互确认或 `--yes`。
|
|
27
|
-
`--json` 可放在命令前后,也支持 `redminitool minitool --json list ...`。业务错误和参数解析错误均返回非零退出码;JSON 模式的 stdout 只输出一个结果对象。
|
|
28
|
-
|
|
29
|
-
```shell
|
|
30
|
-
redminitool --env beta --json config --source <平台分配的来源>
|
|
31
|
-
redminitool list --env beta --source <平台分配的来源> --json
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## 登录与环境
|
|
35
|
-
|
|
36
|
-
```shell
|
|
37
|
-
redminitool login
|
|
38
|
-
redminitool whoami
|
|
39
|
-
redminitool auth status
|
|
40
|
-
redminitool login --cancel
|
|
41
|
-
redminitool logout
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
默认使用小红书 App 扫码,流程为设备码 → S256 PKCE → 授权状态轮询 → Token 交换。
|
|
45
|
-
终端显示二维码和手机浏览器备用链接;`login --json` 将授权提示与临时 PNG 的 `qrCodePath` 以 `AUTH_PROMPT:<json>` 写入 stderr,stdout 仅输出最终结果。登录结束后清理临时二维码。
|
|
46
|
-
Ctrl+C / SIGTERM 或另一终端 `login --cancel` 可取消等待。网络中断后再次 login 会恢复仍有效的设备码。
|
|
47
|
-
若 Token 响应未携带身份字段,登录仍成功,whoami 会明确提示身份暂不可用。
|
|
48
|
-
Token 临近过期时自动续期;续期明确失效后,显式 login 可重新扫码。不会把设备码、verifier 或 Token 放入命令参数、日志、MCP 输出。
|
|
49
|
-
|
|
50
|
-
所有命令接受 `--env prod|beta`,默认 prod;也可设置 `REDMINITOOL_ENV`,MCP 同样支持该环境选项。
|
|
51
|
-
prod 使用 `~/.redminitool/`,beta 使用 `~/.redminitool/beta/`,存储模式和 Keyring 条目互相隔离。
|
|
52
|
-
`REDMINITOOL_HOME` 可替换 home 目录(其下仍创建 `.redminitool`)。不会读取旧 `skill-cli` 凭据文件。
|
|
53
|
-
域名统一由 `@skillbuilder/endpoints` 维护。beta 网关与参考分支一致;来源由平台分配,并与登录环境对应。
|
|
54
|
-
|
|
55
|
-
默认使用权限为 `0600` 的 `auth.json`,目录权限为 `0700`,原子写入并拒绝符号链接、多硬链和异常 owner。
|
|
56
|
-
凭据也可显式转入系统 Keyring:
|
|
57
|
-
|
|
58
|
-
```shell
|
|
59
|
-
redminitool auth storage --set keyring
|
|
60
|
-
redminitool auth storage --check
|
|
61
|
-
redminitool auth storage --set file
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Keyring 访问失败不会自动降级。`config.json` 只存版本与存储模式;设备码等待状态单独存入受限的 `pending-auth.json`,完成或取消后清理。
|
|
65
|
-
`logout` 清理当前环境的凭据和等待状态。原有 Secret 登录保留为 `login --method secret`,仅支持 prod 交互输入,密钥不落盘。
|
|
66
|
-
第三方小工具接口使用扫码 OAuth 凭据,原有 Secret 会话不保证具有第三方接口权限。
|
|
67
|
-
|
|
68
|
-
## 查询与上传
|
|
69
|
-
|
|
70
|
-
除上传外,平台接口必须提供已分配的来源:`--source <来源>`,或设置 `REDMINITOOL_SOURCE`。
|
|
71
|
-
|
|
72
|
-
```shell
|
|
73
|
-
redminitool config --source <来源>
|
|
74
|
-
redminitool list --source <来源> --page-num 1 --page-size 20
|
|
75
|
-
redminitool status --source <来源> --app-id <id>
|
|
76
|
-
redminitool history --source <来源> --app-id <id>
|
|
77
|
-
redminitool upload --file ./app.zip --type pkg --dry-run --json
|
|
78
|
-
redminitool upload --file ./app.zip --type pkg --yes --json
|
|
79
|
-
redminitool upload --file ./icon.png --type image --yes --json
|
|
80
|
-
redminitool upload --file ./cover.png --type image --yes --json
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
上传返回 `fileId`、`md5`、`sha256`、`size`、`type`;上传本身不创建草稿小工具。
|
|
84
|
-
ZIP 根目录需含 `index.html`,单文件不超过 10 MiB,解压不超过 30 MiB。
|
|
85
|
-
图片支持 PNG、JPEG、GIF、WebP,服务端策略可能有进一步限制。
|
|
86
|
-
|
|
87
|
-
## 手机预览、提审与编辑
|
|
88
|
-
|
|
89
|
-
保存 `preview.json`(不要在参数文件中填写 source):
|
|
90
|
-
|
|
91
|
-
```json
|
|
92
|
-
{
|
|
93
|
-
"pkgFileId": "上传代码包返回的fileId",
|
|
94
|
-
"md5": "00000000000000000000000000000000",
|
|
95
|
-
"appName": "我的工具",
|
|
96
|
-
"version": "1.0.0"
|
|
97
|
-
}
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
替换为实际 fileId 和 md5 后运行:
|
|
101
|
-
|
|
102
|
-
```shell
|
|
103
|
-
redminitool preview --source <来源> --file ./preview.json --dry-run
|
|
104
|
-
redminitool preview --source <来源> --file ./preview.json --yes --qr-out ./preview.png
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
预览必填 `pkgFileId` / `md5`,可选 `appName` / `iconFileId` / `version`,不支持按已有 appId 刷新预览。
|
|
108
|
-
返回 `previewUrl`,终端展示二维码;`--qr-out` 另存 PNG 且不覆盖已有文件。
|
|
109
|
-
远端成功、本地写图失败时返回 `qrError`,可直接使用已有链接,不必重复创建预览。
|
|
110
|
-
|
|
111
|
-
保存 `submit.json`,填写实际上传文件标识和 `config` 返回的类目/权限编码:
|
|
112
|
-
|
|
113
|
-
```json
|
|
114
|
-
{
|
|
115
|
-
"appName": "我的工具",
|
|
116
|
-
"slogan": "一句话简介",
|
|
117
|
-
"iconFileId": "icon-file-id",
|
|
118
|
-
"coverFileId": "cover-file-id",
|
|
119
|
-
"version": "1.0.0",
|
|
120
|
-
"pkgFileId": "pkg-file-id",
|
|
121
|
-
"md5": "00000000000000000000000000000000",
|
|
122
|
-
"categories": ["平台类目编码"],
|
|
123
|
-
"authorizations": []
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
```shell
|
|
128
|
-
redminitool submit --source <来源> --file ./submit.json --dry-run --json
|
|
129
|
-
redminitool submit --source <来源> --file ./submit.json --yes --json
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
新建不传 `appId`;更新版本添加已有 `appId`。版本须为 `x.y.z`,类目仅允许一个,权限可以为空。
|
|
133
|
-
core 在提交前查询当前配置并校验编码。提交成功表示已送审,后续用 status/history 查询结果。
|
|
134
|
-
编辑基础信息使用 `edit.json`。例如只改简介时,也需要传入现有名称和图标:
|
|
135
|
-
|
|
136
|
-
```json
|
|
137
|
-
{
|
|
138
|
-
"appId": "已有ID",
|
|
139
|
-
"appName": "现有名称",
|
|
140
|
-
"slogan": "更新后的简介",
|
|
141
|
-
"iconFileId": "现有图标的fileId"
|
|
142
|
-
}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
```shell
|
|
146
|
-
redminitool edit --source <来源> --file ./edit.json --dry-run
|
|
147
|
-
redminitool edit --source <来源> --file ./edit.json --yes
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
edit 必须同时传入 `appName`、`slogan`、`iconFileId` 三项非空白字符串,`coverFileId` 可选。
|
|
151
|
-
平台不支持仅传一个字段的局部更新;未修改项使用可信的现有值,图标 URL 不能代替 fileId。
|
|
152
|
-
缺项、null、空串或纯空白会在 core 本地拦截,CLI dry-run 和 MCP 沿用同一校验。更新代码包通过 submit 新版本完成。
|
|
153
|
-
|
|
154
|
-
所有命令统一支持 `--json`:成功为 `{ "ok": true, "data": ... }`,失败为 `{ "ok": false, "error": { "code", "message" } }`。
|
|
155
|
-
写操作沿用交互确认,非交互执行需 `--yes`;`--dry-run` 仅校验本地内容,不需要登录、不请求远端。
|
|
156
|
-
本地检查通过不代表线上权限或审核通过。写接口不自动重试,`OUTCOME_UNKNOWN` 时先查询状态、列表和历史,再决定是否重试。
|
|
157
|
-
|
|
158
|
-
## 本地调试与 MCP
|
|
159
|
-
|
|
160
|
-
```shell
|
|
161
|
-
redminitool dev --dir ./dist
|
|
162
|
-
redminitool dev --dir ./dist --no-open
|
|
163
|
-
redminitool mcp
|
|
164
|
-
redminitool mcp --env beta
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
`dev` 通过 `@skillbuilder/miniapp-simulator/workbench/server` 启动本地模拟器工作台服务,提供产物加载、截图、交互、DOM / Canvas 和日志能力。
|
|
168
|
-
`--dir` 默认当前目录;优先使用 `index.html`,否则使用根目录唯一的 HTML 文件。需要构建的项目传入 `--dir ./dist`。
|
|
169
|
-
服务固定监听 `127.0.0.1` 并自动分配端口。文件直接通过清单加载,HTML / JS / CSS 更新后自动重载;退出时关闭服务、文件监听和 SSE 连接。
|
|
170
|
-
默认连接模拟器包统一配置的正式 Runtime 服务;`--env` 只选择业务与认证环境。设备和场景在工作台切换。
|
|
171
|
-
参数与模拟器公开接入协议保持一致,不提供 `--port`、`--entry`、`--width`、`--height` 或远端上下文参数。
|
|
172
|
-
使用 `--json` 时,启动成功后 stderr 输出一行 `DEV_READY:{"rootDir":"...","workbenchUrl":"..."}`;正常停止后 stdout 输出最终 `{ "ok": true, "data": ... }`。
|
|
173
|
-
|
|
174
|
-
MCP 提供 `auth_status`、`creator_whoami`、`minitool_config/list/status/history/preview/submit/edit` 和 `e2e_*`。
|
|
175
|
-
设置 `REDMINITOOL_MCP_UPLOAD_ROOT` 后才注册 `minitool_upload`,只允许授权目录中的 ZIP / 图片;所有写工具要求 `confirm=true`。
|
|
176
|
-
MCP 的业务参数使用与 core 相同的真实字段,凭据不作为 MCP 参数。扫码登录在 CLI 中完成。
|
|
177
|
-
stdout 为 JSON-RPC 专用通道,诊断写 stderr。CLI APM 默认关闭,仅设置 `REDMINITOOL_APM_ENDPOINT` 后上报脱敏事件。
|
|
178
|
-
|
|
179
|
-
命令测试通过 Commander 解析入口连接 DI Core 和本地 HTTP 平台,覆盖扫码登录、查询、上传、预览、提审、编辑、退出及无确认拒绝写入;二进制入口另行验证帮助、JSON 参数错误、分组兼容和离线 dry-run。
|
|
180
|
-
2026-10-26 已使用同一真实 beta 账号对比参考 CLI,验证身份、配置、列表、状态、历史、上传和预览;提审、编辑的完整写入流程目前在本地测试平台验证。
|
|
181
|
-
|
|
182
|
-
```shell
|
|
183
|
-
pnpm --filter @skillbuilder/minitool-core test
|
|
184
|
-
pnpm --filter @skillbuilder/minitool-cli test
|
|
185
|
-
```
|
|
3
|
+
This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
|
package/package.json
CHANGED
|
@@ -1,48 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skillbuilder/minitool-cli",
|
|
3
|
-
"version": "0.0.0-
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
},
|
|
8
|
-
"main": "lib/index.js",
|
|
9
|
-
"types": "types/index.d.ts",
|
|
10
|
-
"bin": {
|
|
11
|
-
"redminitool": "./bin/redminitool.js",
|
|
12
|
-
"red-minitool": "./bin/redminitool.js",
|
|
13
|
-
"xhs-minitool": "./bin/redminitool.js",
|
|
14
|
-
"minitool": "./bin/redminitool.js"
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"bin",
|
|
18
|
-
"lib",
|
|
19
|
-
"README.md",
|
|
20
|
-
"types"
|
|
21
|
-
],
|
|
22
|
-
"dependencies": {
|
|
23
|
-
"@modelcontextprotocol/sdk": "1.25.3",
|
|
24
|
-
"chalk": "^2.4.2",
|
|
25
|
-
"cli-table3": "^0.5.1",
|
|
26
|
-
"commander": "7",
|
|
27
|
-
"didyoumean": "^1.2.2",
|
|
28
|
-
"inquirer": "^6.5.2",
|
|
29
|
-
"jszip": "^3.10.1",
|
|
30
|
-
"log-symbols": "^3.0.0",
|
|
31
|
-
"open": "^7.4.2",
|
|
32
|
-
"ora": "^4.0.2",
|
|
33
|
-
"semver": "^7.3.7",
|
|
34
|
-
"update-notifier": "^4.0.0",
|
|
35
|
-
"yargs-parser": "^21.0.1",
|
|
36
|
-
"zod": "4.3.5",
|
|
37
|
-
"qrcode": "^1.5.4",
|
|
38
|
-
"@skillbuilder/endpoints": "0.0.0-beta-20261027053041051",
|
|
39
|
-
"@skillbuilder/minitool-cli-auth": "0.0.0-beta-20261027053041051",
|
|
40
|
-
"@skillbuilder/minitool-cli-config": "0.0.0-beta-20261027053041051",
|
|
41
|
-
"@skillbuilder/minitool-core": "0.0.0-beta-20261027053041051",
|
|
42
|
-
"@skillbuilder/miniapp-simulator": "0.0.0-beta-20261027053041051",
|
|
43
|
-
"@skillbuilder/minitool-e2e": "0.0.0-beta-20261027053041051"
|
|
44
|
-
},
|
|
45
|
-
"keywords": [],
|
|
46
|
-
"author": "",
|
|
47
|
-
"license": "ISC"
|
|
48
|
-
}
|
|
3
|
+
"version": "0.0.0-stage",
|
|
4
|
+
"stub": true,
|
|
5
|
+
"description": "Temporary package placeholder for staged publishing"
|
|
6
|
+
}
|
package/bin/redminitool.js
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const yargsParser = require("yargs-parser");
|
|
3
|
-
const chalk = require("chalk");
|
|
4
|
-
const { program } = require("commander");
|
|
5
|
-
const logSymbols = require("log-symbols");
|
|
6
|
-
const didYouMean = require("didyoumean");
|
|
7
|
-
const updateNotifier = require("update-notifier");
|
|
8
|
-
const semver = require("semver");
|
|
9
|
-
const pkg = require("../package.json");
|
|
10
|
-
|
|
11
|
-
function reportError(error, json) {
|
|
12
|
-
const rawCode = error && typeof error.code === "string" ? error.code : "COMMAND_FAILED";
|
|
13
|
-
const code = rawCode.startsWith("commander.") ? "INVALID_ARGS" : rawCode;
|
|
14
|
-
const message = error instanceof Error ? error.message : "命令执行失败";
|
|
15
|
-
if (json) process.stdout.write(`${JSON.stringify({ ok: false, error: { code, message } }, null, 2)}\n`);
|
|
16
|
-
else process.stderr.write(`${logSymbols.error} ${message}\n`);
|
|
17
|
-
process.exitCode = 1;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async function main() {
|
|
21
|
-
const processArgv = process.argv;
|
|
22
|
-
const isBeta = pkg.version.indexOf("-") > -1;
|
|
23
|
-
process.CLI_VERSION = pkg.version;
|
|
24
|
-
|
|
25
|
-
const currentMajorVersion = +semver.major(process.version);
|
|
26
|
-
|
|
27
|
-
// 定义最小版本和推荐版本
|
|
28
|
-
const NODE_MIN_VERSION = 20;
|
|
29
|
-
|
|
30
|
-
// 检查当前版本是否满足最小版本要求
|
|
31
|
-
if (NODE_MIN_VERSION > currentMajorVersion) {
|
|
32
|
-
console.error(
|
|
33
|
-
chalk.bold.red(`当前 Node.js 版本为 v${currentMajorVersion}。请升级到至少 v${NODE_MIN_VERSION} 版本。`),
|
|
34
|
-
);
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const yargsParsedResult = yargsParser(process.argv.slice(2), { boolean: ["json"] });
|
|
39
|
-
|
|
40
|
-
// MCP 模式下 stdout 是 JSON-RPC 专用通道,必须在加载常规 CLI 命令和日志之前分流。
|
|
41
|
-
if (yargsParsedResult._[0] === "mcp") {
|
|
42
|
-
if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
43
|
-
process.stdout.write("Usage: redminitool mcp\n\nStart the MiniTool MCP server over stdio.\n");
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
const { runMcpCommand } = require("../lib/mcp");
|
|
47
|
-
await runMcpCommand({ environment: yargsParsedResult.env });
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// 检查是否是版本请求,如果是则自定义输出
|
|
52
|
-
if (process.argv.includes("-V") || process.argv.includes("--version")) {
|
|
53
|
-
const version = pkg.version;
|
|
54
|
-
const isBeta = version.indexOf("-") > -1;
|
|
55
|
-
const versionColor = isBeta ? chalk.yellow : chalk.green;
|
|
56
|
-
|
|
57
|
-
console.log();
|
|
58
|
-
console.log(chalk.cyan.bold(" ╭─────────────────────────────────╮"));
|
|
59
|
-
console.log(
|
|
60
|
-
chalk.cyan.bold(" │"),
|
|
61
|
-
chalk.white.bold(" redminitool"),
|
|
62
|
-
chalk.gray("v"),
|
|
63
|
-
versionColor.bold(version),
|
|
64
|
-
isBeta ? chalk.yellow(" (beta)") : "",
|
|
65
|
-
chalk.cyan.bold(" │"),
|
|
66
|
-
);
|
|
67
|
-
console.log(chalk.cyan.bold(" │"), chalk.gray(" 小红书小工具 CLI"), chalk.cyan.bold(" │"));
|
|
68
|
-
console.log(chalk.cyan.bold(" ╰─────────────────────────────────╯"));
|
|
69
|
-
console.log();
|
|
70
|
-
process.exit(0);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const { registerCommands, createCliServices, flushCliApm } = require("../lib");
|
|
74
|
-
const services = createCliServices({ environment: yargsParsedResult.env });
|
|
75
|
-
|
|
76
|
-
// 设置 options 选项(必须在添加任何选项之前调用)
|
|
77
|
-
program.storeOptionsAsProperties(false);
|
|
78
|
-
|
|
79
|
-
// 配置 commander 帮助格式,对齐 nrm 格式
|
|
80
|
-
program
|
|
81
|
-
.name("redminitool")
|
|
82
|
-
.description("小红书小工具 CLI,面向创作者、三方 AI 工具和自动化流程")
|
|
83
|
-
.usage("[options] [command]")
|
|
84
|
-
.option("--env <environment>", "服务环境:prod(默认)或 beta")
|
|
85
|
-
.option("--json", "以稳定 JSON 协议输出,供 AI 与自动化调用")
|
|
86
|
-
.version(pkg.version, "-V, --version", "output the version number");
|
|
87
|
-
|
|
88
|
-
program.exitOverride();
|
|
89
|
-
// 参数解析错误也走统一输出,避免 --json 时混入 Commander 的终端提示。
|
|
90
|
-
program.configureOutput({ writeErr: () => {} });
|
|
91
|
-
// Commander 7 在创建子命令时复制退出处理器,须先配置再注册。
|
|
92
|
-
await registerCommands(services);
|
|
93
|
-
program.command("mcp").description("通过 stdio 启动小工具 MCP server");
|
|
94
|
-
|
|
95
|
-
// 配置帮助输出格式
|
|
96
|
-
program.configureHelp({
|
|
97
|
-
sortSubcommands: true,
|
|
98
|
-
subcommandTerm: (cmd) => cmd.name(),
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// 处理无效命令
|
|
102
|
-
program.action(() => {
|
|
103
|
-
const args = program.args;
|
|
104
|
-
if (!Array.isArray(args) || !args.length) {
|
|
105
|
-
program.outputHelp();
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
const cmd = args.join(" ");
|
|
109
|
-
didYouMean.threshold = 0.5;
|
|
110
|
-
didYouMean.caseSensitive = false;
|
|
111
|
-
const suggest = didYouMean(cmd, [
|
|
112
|
-
"login",
|
|
113
|
-
"logout",
|
|
114
|
-
"dev",
|
|
115
|
-
"auth status",
|
|
116
|
-
"auth storage",
|
|
117
|
-
"whoami",
|
|
118
|
-
"config",
|
|
119
|
-
"list",
|
|
120
|
-
"status",
|
|
121
|
-
"history",
|
|
122
|
-
"upload",
|
|
123
|
-
"preview",
|
|
124
|
-
"submit",
|
|
125
|
-
"edit",
|
|
126
|
-
"minitool list",
|
|
127
|
-
"minitool config",
|
|
128
|
-
"minitool history",
|
|
129
|
-
"minitool edit",
|
|
130
|
-
"minitool upload",
|
|
131
|
-
"minitool preview",
|
|
132
|
-
"minitool submit",
|
|
133
|
-
"minitool status",
|
|
134
|
-
]);
|
|
135
|
-
const hint = suggest ? `;您是不是想使用 redminitool ${suggest}` : ";使用 redminitool -h 查看所有命令";
|
|
136
|
-
throw Object.assign(new Error(`${cmd} 不是有效的命令${hint}`), { code: "INVALID_ARGS" });
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
await program.parseAsync(processArgv);
|
|
141
|
-
} catch (e) {
|
|
142
|
-
if (e.code === "commander.helpDisplayed" || e.code === "commander.help" || e.code === "commander.version") return;
|
|
143
|
-
reportError(e, yargsParsedResult.json === true);
|
|
144
|
-
} finally {
|
|
145
|
-
try {
|
|
146
|
-
await services.dispose();
|
|
147
|
-
} finally {
|
|
148
|
-
await flushCliApm();
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// 检查更新
|
|
153
|
-
if (process.env.CI === "1" || yargsParsedResult.json === true) return;
|
|
154
|
-
const ONE_DAY = 86400000;
|
|
155
|
-
// Beta 版 1 个小时检查一次,稳定版 1 天检查一次
|
|
156
|
-
const CheckInterval = isBeta ? 3600000 : ONE_DAY;
|
|
157
|
-
|
|
158
|
-
const notifier = updateNotifier({
|
|
159
|
-
pkg,
|
|
160
|
-
distTag: isBeta ? "beta" : "latest",
|
|
161
|
-
// 检查更新间隔 1 天
|
|
162
|
-
updateCheckInterval: CheckInterval,
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
notifier.notify({
|
|
166
|
-
isGlobal: true,
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (require.main === module) {
|
|
171
|
-
main().catch((error) => {
|
|
172
|
-
reportError(error, yargsParser(process.argv.slice(2), { boolean: ["json"] }).json === true);
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
exports.main = main;
|
package/lib/bootstrap.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.createCliServices = createCliServices;
|
|
37
|
-
const os = __importStar(require("os"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
const endpoints_1 = require("@skillbuilder/endpoints");
|
|
40
|
-
const minitool_cli_auth_1 = require("@skillbuilder/minitool-cli-auth");
|
|
41
|
-
const minitool_cli_config_1 = require("@skillbuilder/minitool-cli-config");
|
|
42
|
-
const minitool_core_1 = require("@skillbuilder/minitool-core");
|
|
43
|
-
function createCliServices(options = {}) {
|
|
44
|
-
var _a, _b, _c, _d, _e;
|
|
45
|
-
const environment = (_b = (_a = options.environment) !== null && _a !== void 0 ? _a : process.env.REDMINITOOL_ENV) !== null && _b !== void 0 ? _b : "prod";
|
|
46
|
-
if (environment !== "prod" && environment !== "beta")
|
|
47
|
-
throw new Error("--env 仅支持 prod 或 beta");
|
|
48
|
-
const homeDir = path.resolve((_d = (_c = options.homeDir) !== null && _c !== void 0 ? _c : process.env.REDMINITOOL_HOME) !== null && _d !== void 0 ? _d : os.homedir());
|
|
49
|
-
const files = new minitool_cli_config_1.ConfigFiles(homeDir, environment);
|
|
50
|
-
const credentials = new minitool_cli_auth_1.ManagedCredentialStore(files);
|
|
51
|
-
const secret = new minitool_cli_auth_1.SecretAuthService(credentials, new minitool_cli_auth_1.HttpSecretAuthApi(new URL("/api/eros/mp/red/cloud/cli_auth", (0, endpoints_1.getMiniappBaseUrl)()).toString(), options.request), credentials);
|
|
52
|
-
const apiBaseUrl = (_e = options.apiBaseUrl) !== null && _e !== void 0 ? _e : endpoints_1.MINITOOL_API_BASE_URLS[environment];
|
|
53
|
-
const auth = new minitool_cli_auth_1.DeviceAuthService(credentials, new minitool_cli_auth_1.HttpDeviceAuthApi(apiBaseUrl, options.request), credentials, files, environment === "prod" ? secret : undefined);
|
|
54
|
-
const core = (0, minitool_core_1.createMinitoolCore)({
|
|
55
|
-
accessTokens: auth,
|
|
56
|
-
api: { apiBaseUrl, request: options.request },
|
|
57
|
-
});
|
|
58
|
-
return Object.freeze({
|
|
59
|
-
upload: core.upload,
|
|
60
|
-
miniTools: core.miniTools,
|
|
61
|
-
auth,
|
|
62
|
-
credentialStorage: credentials,
|
|
63
|
-
environment,
|
|
64
|
-
get isDisposed() {
|
|
65
|
-
return core.isDisposed;
|
|
66
|
-
},
|
|
67
|
-
dispose: () => core.dispose(),
|
|
68
|
-
});
|
|
69
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
9
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
10
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
11
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
12
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
13
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
14
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
15
|
-
});
|
|
16
|
-
};
|
|
17
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
|
-
};
|
|
20
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.WhoAmICommand = exports.AuthStatusCommand = void 0;
|
|
22
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
23
|
-
const base_1 = require("../../core/base");
|
|
24
|
-
const decorators_1 = require("../../decorators");
|
|
25
|
-
const ui_1 = require("../../ui");
|
|
26
|
-
let AuthStatusCommand = class AuthStatusCommand extends base_1.Command {
|
|
27
|
-
execute(ctx) {
|
|
28
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
-
var _a, _b;
|
|
30
|
-
const state = yield this.services.auth.getAuthState();
|
|
31
|
-
if (this.isJson(ctx))
|
|
32
|
-
return state;
|
|
33
|
-
if (state.status === "unavailable") {
|
|
34
|
-
(0, ui_1.printHeading)("账号状态", "无法读取登录态");
|
|
35
|
-
(0, ui_1.printDetails)([["状态", state.reason]]);
|
|
36
|
-
(0, ui_1.printHint)("运行 redminitool auth storage --check 检查凭据存储");
|
|
37
|
-
return state;
|
|
38
|
-
}
|
|
39
|
-
if (state.status === "anonymous") {
|
|
40
|
-
(0, ui_1.printHeading)("账号状态", state.reason === "expired" ? "登录态已过期" : "尚未登录");
|
|
41
|
-
(0, ui_1.printDetails)([["状态", state.reason]]);
|
|
42
|
-
(0, ui_1.printHint)("运行 redminitool login 重新登录");
|
|
43
|
-
return state;
|
|
44
|
-
}
|
|
45
|
-
(0, ui_1.printHeading)("账号状态", "已登录小红书小工具");
|
|
46
|
-
(0, ui_1.printDetails)([
|
|
47
|
-
["创作者", (_b = (_a = state.identitySnapshot) === null || _a === void 0 ? void 0 : _a.displayName) !== null && _b !== void 0 ? _b : "待服务端确认"],
|
|
48
|
-
["认证方式", state.method],
|
|
49
|
-
["凭据存储", state.source === "os_keychain" ? "系统 Keychain" : "本地受限文件"],
|
|
50
|
-
["有效期至", state.expiresAt ? new Date(state.expiresAt).toLocaleString("zh-CN") : undefined],
|
|
51
|
-
]);
|
|
52
|
-
if (!state.identitySnapshot) {
|
|
53
|
-
console.log(chalk_1.default.yellow(" ⚠ 认证响应未返回创作者身份;需接入服务端安全身份接口。"));
|
|
54
|
-
}
|
|
55
|
-
return state;
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
get options() {
|
|
59
|
-
return {
|
|
60
|
-
cmd: "auth",
|
|
61
|
-
childCmd: { cmd: "status", desc: "查看脱敏后的认证状态" },
|
|
62
|
-
desc: "查看脱敏后的认证状态",
|
|
63
|
-
options: [],
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
exports.AuthStatusCommand = AuthStatusCommand;
|
|
68
|
-
exports.AuthStatusCommand = AuthStatusCommand = __decorate([
|
|
69
|
-
(0, base_1.ICommand)()
|
|
70
|
-
], AuthStatusCommand);
|
|
71
|
-
let WhoAmICommand = class WhoAmICommand extends base_1.Command {
|
|
72
|
-
execute(ctx) {
|
|
73
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
-
const identity = yield this.services.auth.whoAmI();
|
|
75
|
-
if (this.isJson(ctx))
|
|
76
|
-
return identity;
|
|
77
|
-
(0, ui_1.printHeading)("创作者身份", "当前账号");
|
|
78
|
-
(0, ui_1.printDetails)([
|
|
79
|
-
["昵称", identity.displayName],
|
|
80
|
-
["Creator ID", identity.creatorId],
|
|
81
|
-
["简介", identity.description],
|
|
82
|
-
]);
|
|
83
|
-
return identity;
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
get options() {
|
|
87
|
-
return {
|
|
88
|
-
cmd: "whoami",
|
|
89
|
-
desc: "获取当前登录的创作者身份",
|
|
90
|
-
options: [],
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
exports.WhoAmICommand = WhoAmICommand;
|
|
95
|
-
exports.WhoAmICommand = WhoAmICommand = __decorate([
|
|
96
|
-
(0, base_1.ICommand)(),
|
|
97
|
-
(0, decorators_1.AuthGuard)()
|
|
98
|
-
], WhoAmICommand);
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./login"), exports);
|
|
18
|
-
__exportStar(require("./logout"), exports);
|
|
19
|
-
__exportStar(require("./identity"), exports);
|
|
20
|
-
__exportStar(require("./storage"), exports);
|