wkgeo-cli 0.2.0 → 0.2.2
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 +171 -36
- package/SKILL.md +173 -29
- package/lib/args.mjs +5 -0
- package/lib/cli.mjs +5 -0
- package/lib/cms.mjs +317 -0
- package/lib/commands/auth.mjs +129 -93
- package/lib/commands/billing.mjs +641 -421
- package/lib/commands/cms.mjs +1265 -0
- package/lib/commands/import.mjs +164 -0
- package/lib/commands/index.mjs +83 -4
- package/lib/config.mjs +82 -22
- package/lib/device.mjs +22 -5
- package/lib/index.mjs +5 -0
- package/lib/local-import.mjs +185 -0
- package/lib/login.mjs +97 -85
- package/lib/oauth-urls.mjs +163 -0
- package/lib/runtime.mjs +81 -0
- package/lib/site-state.mjs +137 -0
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -23,6 +23,10 @@ version: 0.2.0
|
|
|
23
23
|
* 用户说"**帮我下单**"/"买加量包"/"扩容空间"/"买流量" → `products list` → `orders create`
|
|
24
24
|
* 用户说"**用钱包付**"/"余额支付"/"帮我付钱" → `orders create`(余额够会**当场付清**)+ `wallet` 复核
|
|
25
25
|
* 用户说"**充值**"/"充 100 块" → `wallet recharge`(下单后**自动打开我们网站的收银台页面**,用户在那里扫码支付)
|
|
26
|
+
* 用户说"**充值**"但**没说金额**、或说"**我自己选金额**"/"给我个充值链接" → `wallet recharge-link`
|
|
27
|
+
(生成**独立充值页**链接:`https://pay.wkgeo.com/recharge/?ticket=…`,用户在网页上自己选金额
|
|
28
|
+
—— ¥10 / ¥20 快捷,或自定义,**最低 ¥9.90、不设上限** —— 然后扫码支付;**不需要登录会员中心**。
|
|
29
|
+
默认**不**弹浏览器:把 `data.pay_url` 原样交给用户即可。⛔ 不要用它代替用户付款。)
|
|
26
30
|
* 用户说"**查余额**"/"我的钱包"/"账单流水" → `wallet` / `wallet txns`
|
|
27
31
|
* 用户说"**我的订单**"/"订单状态" → `orders list` / `orders get` / `orders check`
|
|
28
32
|
* 用户说"**我授权过哪些应用**"/"取消某个应用的授权" → `apps list` / `apps revoke`
|
|
@@ -103,7 +107,7 @@ npx -y wkgeo-cli@latest skill > SKILL.md # 直接落一份到本地,离线
|
|
|
103
107
|
|
|
104
108
|
| 命令 | 作用 | 关键参数 |
|
|
105
109
|
| --- | --- | --- |
|
|
106
|
-
| `login` | 授权一次(令牌存本地 30
|
|
110
|
+
| `login` | 授权一次(令牌存本地 30 天;**默认浏览器回调**,设备码仅兜底) | `--device`、`--no-wait`、`--device-continue`、`--no-auto-device`、`--callback-first-wait <秒>`(可选,默认关闭)、`--no-browser`、`--open-browser`、`--scope`、`--timeout <秒>` |
|
|
107
111
|
| `whoami` | 当前是谁(账号标识) | `--verbose` |
|
|
108
112
|
| `logout` | 退出(删本地凭据 + 服务端吊销) | `--local-only` |
|
|
109
113
|
| `config` | 生效配置 / 登录状态 | — |
|
|
@@ -113,6 +117,7 @@ npx -y wkgeo-cli@latest skill > SKILL.md # 直接落一份到本地,离线
|
|
|
113
117
|
| `wallet` | 余额 + 最近流水 | `--limit` `--entitlements` |
|
|
114
118
|
| `wallet txns` | 钱包流水 | `--limit` |
|
|
115
119
|
| `wallet recharge` | 充值下单,**并打开我们网站的收银台页面**扫码支付(**不扣款**) | `--amount-cents`(分,必填)、`--no-browser`、`--open-browser`、`--dry-run` |
|
|
120
|
+
| `wallet recharge-link` | 生成**独立充值页**链接(用户在网页上**自己选金额**并扫码支付;**不扣款**、不建单) | `--open-browser`(默认**不**弹)、`--no-browser` |
|
|
116
121
|
| `products list` | 能买什么 | — |
|
|
117
122
|
| `orders create` | 下单(余额够**当场付清**) | `--product <代码>` `--units <份数>`(或 `--quota <键>` `--amount <数量>`)`--allow-wechat` |
|
|
118
123
|
| `orders check` | 查支付结果 + 最新余额 | `<订单ID>` |
|
|
@@ -121,8 +126,21 @@ npx -y wkgeo-cli@latest skill > SKILL.md # 直接落一份到本地,离线
|
|
|
121
126
|
| `orders list` | 我的订单 | `--limit` `--offset` `--status` |
|
|
122
127
|
| `apps list` | 我授权过的应用 | — |
|
|
123
128
|
| `apps revoke` | 一键吊销某应用授权(令牌立即失效) | `<client_id>` |
|
|
129
|
+
| `site use` | **选中要操作的站点**(存本地,之后的 CMS 命令默认用它;不带参数 = 看当前) | `<站点ID或域名>`、`--clear` |
|
|
130
|
+
| `categories list/get/create/update/delete` | 栏目:列表 / 详情 / 新建 / 改 / 删 | 见 §7.5 |
|
|
131
|
+
| `categories bind-template` | 给栏目绑定模板 html(`--clear` 解绑) | `<栏目>` `<模板文件>`、`--clear` |
|
|
132
|
+
| `contents list/get/create/update/delete` | 内容:列表 / 详情 / 新建 / 改 / 删 | 见 §7.5 |
|
|
133
|
+
| `assets list` / `assets upload` | 素材:列表 / 上传(签名 → 直传 OSS → 登记) | `assets upload <文件>`、`--name` |
|
|
134
|
+
| `templates list/get/save` | 模板:清单 / 看源码(直出)/ 保存 | `templates get <文件>`、`templates save <文件> --file <本地>` |
|
|
135
|
+
| `publish` | **看发布状态**(前台按需渲染:`published` 即上线,没有额外发布步骤) | — |
|
|
136
|
+
| `import` | 老站导入(**默认 dry-run**;走本机运维脚本,**需运维权限**) | `--url`(必填)、`--apply`、`--site` |
|
|
124
137
|
| `skill` | **打印给 AI 端的操作手册**(本文件原文,随包分发) | `--json`(默认纯文本原文;不受"非终端自动 JSON"影响) |
|
|
125
138
|
|
|
139
|
+
> CMS 命令(`categories` / `contents` / `assets` / `templates` / `publish`)都要先确定站点:
|
|
140
|
+
> `--site <站点ID>` > 环境变量 `WKONGAI_SITE` > 本地 `wkgeo site use`
|
|
141
|
+
> > **都没有时不带站点头**(服务端用你唯一的成员站;多站会报 `cms_site_required` 让你指定)。
|
|
142
|
+
> ⚠️ `--site` **只认 uuid**;域名先 `wkgeo site use <域名>` 解析。
|
|
143
|
+
|
|
126
144
|
### 示例:成功
|
|
127
145
|
|
|
128
146
|
```bash
|
|
@@ -173,6 +191,13 @@ $ npx -y wkgeo-cli@latest orders create --product storage_gb --units 10
|
|
|
173
191
|
|
|
174
192
|
## 5. 授权流程(**必须让用户动手的那一步**)
|
|
175
193
|
|
|
194
|
+
> ★ **2026-10-18 域名统一到路径**:授权站 canonical 从 `https://oauth.wkgeo.com/` 改成
|
|
195
|
+
> **`https://wkgeo.com/oauth/`**(同意页 `/oauth/authorize/`、设备码页 `/oauth/device/`)。
|
|
196
|
+
> 老子域**继续可用**(老板要求并存);CLI 以 `WKONGAI_OAUTH_WEB_BASE` 为 canonical,
|
|
197
|
+
> 服务端 metadata 只提供路径 —— 所以**服务端还没部署新地址时,CLI 打印的也是新地址**。
|
|
198
|
+
> 回滚一条环境变量即可:`WKONGAI_OAUTH_WEB_BASE=https://oauth.wkgeo.com`(不用改代码)。
|
|
199
|
+
> ⚠️ 给用户看的地址**原样转述**,别自己把 `wkgeo.com/oauth` 改回 `oauth.wkgeo.com` 去"纠错"。
|
|
200
|
+
|
|
176
201
|
### 5.1 本地回调模式(默认)
|
|
177
202
|
|
|
178
203
|
```bash
|
|
@@ -184,11 +209,15 @@ npx -y wkgeo-cli@latest login --json --timeout 500ms # 也可以显式写毫
|
|
|
184
209
|
|
|
185
210
|
它会**阻塞**(默认最多 5 分钟)并输出 JSONL:
|
|
186
211
|
|
|
212
|
+
> ★ **0.2.2 起:默认就是这条回调**,等多久都**不会**自动改成设备码;整段超时只报
|
|
213
|
+
> `kind:"timeout"`(并在 hint 里给出"显式改用 `--device`"的下一步)。设备码只在
|
|
214
|
+
> ① 显式 `--device` ② 检测到系统代理 ③ 本地回调端口真的起不来 时出现(见 §5.3 / §5.4)。
|
|
215
|
+
|
|
187
216
|
```jsonc
|
|
188
217
|
// 第一行 —— 拿到它就应该**立刻**把网址交给用户(不要等命令结束!)
|
|
189
218
|
// ⚠️ `authorize/` 的**尾斜杠不能丢**:它是托管侧 302(会丢掉全部 query)的分界线
|
|
190
219
|
{"ok":true,"command":"login","mode":"callback","stage":"awaiting_callback",
|
|
191
|
-
"authorization_url":"https://
|
|
220
|
+
"authorization_url":"https://wkgeo.com/oauth/authorize/?client_id=wkgeo-cli&…",
|
|
192
221
|
"redirect_uri":"http://127.0.0.1:53682/callback","scope":"site:read site:write billing:self",
|
|
193
222
|
"timeout_ms":300000,
|
|
194
223
|
"user_action_required":"请让用户在浏览器中打开上面的 authorization_url,登录并点「同意」"}
|
|
@@ -239,7 +268,14 @@ npx -y wkgeo-cli@latest login --json --timeout 500ms # 也可以显式写毫
|
|
|
239
268
|
* 用户也可以在网页「我已授权的应用」里一键吊销(吊销后 CLI 会收到 40102)。
|
|
240
269
|
* 🔒 不要把这个文件内容读出来放进任何输出/日志/第三方请求里。
|
|
241
270
|
|
|
242
|
-
### 5.3 设备码模式(`login --device`)——
|
|
271
|
+
### 5.3 设备码模式(`login --device`)—— **本地读不了回调 / 代理 / 远程机器时的兜底**
|
|
272
|
+
|
|
273
|
+
> ★ **默认不是设备码**:`wkgeo login` 默认走浏览器回调(授权页 + 本地 `127.0.0.1` 回调,见 §5.1)。
|
|
274
|
+
> 只有这几种情况才用设备码:
|
|
275
|
+
> 1. 用户**显式** `--device` / `--no-wait` / `--device-continue`;
|
|
276
|
+
> 2. **检测到系统代理**(CLI 自动改道,见 §5.4;`--no-auto-device` 可关);
|
|
277
|
+
> 3. 本地回调端口**真的起不来**(CLI 自动兜底,`reason:"callback_listen_failed"`;`--no-auto-device` 可关)。
|
|
278
|
+
> **等待超时不会**自动改设备码(0.2.2 起)。
|
|
243
279
|
|
|
244
280
|
**什么时候用它**(不用问用户,直接选它就行):
|
|
245
281
|
|
|
@@ -254,7 +290,7 @@ npx -y wkgeo-cli@latest login --json --timeout 500ms # 也可以显式写毫
|
|
|
254
290
|
# ① 交互式终端 / 你有长超时能力:一口气跑完(阻塞,最多 expires_in 秒)
|
|
255
291
|
npx -y wkgeo-cli@latest login --device --json
|
|
256
292
|
# → {"stage":"awaiting_user","user_code":"ABCD-1234",
|
|
257
|
-
# "verification_uri":"https://
|
|
293
|
+
# "verification_uri":"https://wkgeo.com/oauth/device/",
|
|
258
294
|
# "verification_uri_complete":"…/?user_code=ABCD-1234","open_url":"…",
|
|
259
295
|
# "expires_in":600,"interval":5,"paste_text":"请打开 … 并完成「同意授权」(短码:ABCD-1234)。",
|
|
260
296
|
# "user_action_required":"请让用户访问 … 并输入短码 ABCD-1234"}
|
|
@@ -312,7 +348,7 @@ npx -y wkgeo-cli@latest login --device-continue --json # 用户说"点好
|
|
|
312
348
|
**机理**:回调要求**浏览器**访问 `http://127.0.0.1:<端口>/callback?code=…`;
|
|
313
349
|
全局/系统代理若没把回环地址排除,这条请求会被代理接管 → CLI 收不到 code。
|
|
314
350
|
|
|
315
|
-
**CLI 已经自己处理好了**(2026-10-02
|
|
351
|
+
**CLI 已经自己处理好了**(2026-10-02 第二版加固 + 2026-10-21 默认模式调整):
|
|
316
352
|
|
|
317
353
|
* ★ **只要检测到"生效中的系统代理"就直接改用设备码模式**(事件流里第一行就是
|
|
318
354
|
`stage:"awaiting_user"`,而不是 `awaiting_callback`);`data.auto_device.reason = "proxy_detected"`。
|
|
@@ -321,22 +357,22 @@ npx -y wkgeo-cli@latest login --device-continue --json # 用户说"点好
|
|
|
321
357
|
证据 `curl -x http://127.0.0.1:7890 http://127.0.0.1:1/x` → 502)。
|
|
322
358
|
`proxy_warning.loopback_bypassed` / `risk` 现在**只是诊断字段**,不再代表"回调没问题";
|
|
323
359
|
`proxy_warning.loopback_bypass_trusted` 恒为 `false`。
|
|
324
|
-
*
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
⚠️ **切换时不再关掉本地回调监听**(同一次修复):两条路**并存**,哪条先成功就用哪条 ——
|
|
360
|
+
* ★★ **0.2.2 起:等待超时不再自动改设备码**(老板 2026-10-21 反馈):
|
|
361
|
+
老板原话「默认的也不应该是设备授权,默认的就是那个传统的授权方式(浏览器打开授权页 +
|
|
362
|
+
本地 localhost 回调)。设备码是本地读不了/代理时才用的。」
|
|
363
|
+
⇒ 没有代理时 `login` 会**一路等回调到 `--timeout`**(默认 300 秒),超时只报
|
|
364
|
+
`kind:"timeout"`,并在 `hint` 里给出"显式改用 `--device`"的下一步。
|
|
365
|
+
⚠️ 历史行为(0.2.1 及更早):有代理时"首轮等待 180 秒"到点会改设备码、整段超时也会改;
|
|
366
|
+
现在那个"首轮等待"**默认关闭**,只有用户**显式**写 `--callback-first-wait <秒>` /
|
|
367
|
+
`WKONGAI_CALLBACK_FIRST_WAIT_MS` 才启用(显式优先,`reason:"callback_first_wait"`)。
|
|
368
|
+
显式启用时仍然是**两条路并存**:本地回调监听继续保留,哪条先成功就用哪条 ——
|
|
334
369
|
用户之后才点的那次【同意授权】照样能完成登录;旧逻辑在切换那一刻关了监听,用户随后点同意
|
|
335
|
-
只会看到 **ERR_CONNECTION_REFUSED**(真机截图见过的"无法访问此网站"
|
|
370
|
+
只会看到 **ERR_CONNECTION_REFUSED**(真机截图见过的"无法访问此网站",2026-10-03 已修)。
|
|
336
371
|
若设备码先成功,之后到达的回调会拿到一张「本次登录已经完成」的页面(不是错误页);
|
|
337
372
|
若回调先成功,设备码轮询会被停掉并说明(`ℹ️ 本地回调已经拿到令牌:设备码那条路已停止…`)。
|
|
338
|
-
*
|
|
339
|
-
(`reason: "
|
|
373
|
+
* 本地回环端口**真的起不来**(防火墙/安全软件/端口非法)→ 自动兜底设备码
|
|
374
|
+
(`reason: "callback_listen_failed"`),**不会**直接失败退出;
|
|
375
|
+
`--no-auto-device` 可关闭这个兜底(此时如实报 `kind:"listen"`)。
|
|
340
376
|
* 换票失败 / 用户点了拒绝 → **不降级**(授权已经走到下一步了,别让用户白做一遍);
|
|
341
377
|
* 上述情况下,`meta.proxy_warning` / `data.proxy_warning` 都会告诉你原因与建议动作:
|
|
342
378
|
|
|
@@ -359,12 +395,18 @@ npx -y wkgeo-cli@latest login --device-continue --json # 用户说"点好
|
|
|
359
395
|
* 看到 `proxy_warning.callback_may_fail: true`:**不要**叫用户去改代理设置(很多用户不懂),
|
|
360
396
|
直接按设备码流程走 —— CLI 通常已经自动切过去了;
|
|
361
397
|
只有当用户明确说"我就想用浏览器回调"时,才把 `actions` 里第 2/3 条念给他;
|
|
362
|
-
* 看到 `auto_device.applied: true
|
|
363
|
-
|
|
398
|
+
* 看到 `auto_device.applied: true`:按 `reason` 如实说明,别隐瞒:
|
|
399
|
+
* `"proxy_detected"` → 「检测到你开着代理,已自动改用设备码模式(不需要本地回调)」;
|
|
400
|
+
* `"callback_listen_failed"` → 「本地回调端口起不来,已自动改用设备码模式继续」;
|
|
401
|
+
* `"callback_first_wait"` → **只可能**是用户自己显式开了 `--callback-first-wait`:
|
|
402
|
+
「等待到点没收到回调,已同时改用设备码(两条路哪条先成功算哪条)」。
|
|
403
|
+
* 没有 `auto_device`(`applied:false`)就是**默认的浏览器回调**,不要主动提设备码。
|
|
364
404
|
* 想让 CLI **不要**自动改道(例如你确认回调一定通):加 `--no-auto-device`,或设
|
|
365
405
|
`WKONGAI_AUTO_DEVICE=0`。⚠️ 此时 CLI 会**打印警告**说"若代理接管 127.0.0.1,
|
|
366
|
-
点了【同意授权】也收不到结果"
|
|
367
|
-
|
|
406
|
+
点了【同意授权】也收不到结果",并且**不会**再用首轮等待自愈、端口起不来也**不兜底** ——
|
|
407
|
+
尊重用户的选择,但要**把这个风险如实转述**给他;
|
|
408
|
+
* 用户只是**等得久**(没代理、也没报错):**不要**自己改成设备码 —— 0.2.2 起默认就是回调,
|
|
409
|
+
等多久都不会自动变;要设备码必须**显式**加 `--device`(先问用户,别擅自换模式);
|
|
368
410
|
* 排障:`npx -y wkgeo-cli@latest config --json` 里有 `data.proxy` 与 `meta.proxy_warning`,
|
|
369
411
|
是"用户机器上是不是代理挡了回调"的**唯一权威判断**(只读检测,不会改用户任何设置)。
|
|
370
412
|
|
|
@@ -450,6 +492,14 @@ Set-Content -LiteralPath "$env:USERPROFILE\.dsh\browser-open.txt" -Value "<完
|
|
|
450
492
|
| `not_found` / `404` | 订单/站点/产品不存在 | 用 `orders list` / `products list` 重新确认 ID |
|
|
451
493
|
| `bad_request` / `400` | 参数不对 | 按 `message` 修正参数;别硬改着重试 |
|
|
452
494
|
| `not_deployed` | 该接口服务端还没发布 | 告诉用户"这是服务端缺口",不要反复重试 |
|
|
495
|
+
| `cms_auth` / `401`(CMS 命令) | CMS 没接受 Bearer 令牌:通常是**令牌无效**(过期/吊销/客户端停用);只有旧部署才会是"没启用 CLI 认证" | 先 `wkgeo login` 重新授权一次(正常环境一定能解决);仍不行再用 `whoami` 判断是否服务端旧部署,让管理员确认(**不要**反复登录十几次) |
|
|
496
|
+
| `cms_site_required` / `400` | 账号有多个站点,没指定 | 先问用户是哪个站,再 `site use <站点ID>` 或 `--site <站点ID>` |
|
|
497
|
+
| `cms_not_member` / `403` | 不是该站成员 / 站点 id 不对 | 让用户确认站点(`site use` 重选);协作站要 owner 先加成员 |
|
|
498
|
+
| `cms_readonly` / `403` | 站点角色是 viewer(只读) | 让 owner 在后台「用户与角色」里升为 editor;**不要**换令牌硬试 |
|
|
499
|
+
| `cms_scope` / `403` | 令牌 scope 不够(如 `template:write`) | 需要更高授权:`login --scope "<原有 + 缺的>"`;已知官方 CLI 客户端没放开 `template:write` / `attachment:delete` |
|
|
500
|
+
| `cms_unavailable` | CMS 地址不通 / 云函数没部署 / 返回不是 JSON | 检查 `wkgeo config` 的 `cms_base`;多半是服务端没部署,告诉用户"后台暂时连不上" |
|
|
501
|
+
| `import_unavailable` | 本机没有 `tencent/cloudbase/import-site.mjs` | 告诉用户"老站导入需要运维权限/本仓库环境",**不要**承诺普通客户能用 |
|
|
502
|
+
| `import_failed` | 导入脚本非 0 退出 | 念 `hint` 与日志尾巴;dry-run 失败不动库,可安全重试 |
|
|
453
503
|
| `missing_skill` | `skill` 在本包里找不到 `SKILL.md`(包被裁剪/只拷了 `lib/`) | 换官方包 `npx -y wkgeo-cli@latest skill`;**不是**命令用错了,别让用户去排查 |
|
|
454
504
|
| `server` / `5xx` | 服务端错误 | 保留原文告知用户,可稍后重试 |
|
|
455
505
|
| `network` | 连不上/超时 | 检查网络后重试;`message` 里是原始错误(如 `getaddrinfo ENOTFOUND`) |
|
|
@@ -493,7 +543,7 @@ npx -y wkgeo-cli@latest wallet txns --limit 3
|
|
|
493
543
|
```bash
|
|
494
544
|
npx -y wkgeo-cli@latest wallet recharge --dry-run --amount-cents 10000 # 先彩排,确认金额
|
|
495
545
|
npx -y wkgeo-cli@latest wallet recharge --amount-cents 10000 # 生成待支付订单,并把收银台地址交出来(不扣款)
|
|
496
|
-
# ★ 读 data.pay_url —— 这是**我们网站的收银台页面**(https://pay.wkgeo.com
|
|
546
|
+
# ★ 读 data.pay_url —— 这是**我们网站的收银台页面**(https://pay.wkgeo.com/?order_id=…&token=…)。
|
|
497
547
|
# ⚠️ **不要把 data.code_url 当成主流程丢给用户自己想办法**(那是微信内部支付链接,
|
|
498
548
|
# 手机直接扫不了;终端二维码只是"网页打不开"时的兜底)。
|
|
499
549
|
# ★ `token=` 是服务端在下单那一刻签发的**订单支付令牌**(只对这一单有效):
|
|
@@ -527,6 +577,29 @@ npx -y wkgeo-cli@latest orders check <order_id> # 用
|
|
|
527
577
|
⚠️ 打开 `pay_url` 的方式见 **§5.5**:CLI **默认就会尝试弹系统浏览器**(老板最终拍板走传统路线);
|
|
528
578
|
只有它**没打开成功**时,才考虑可选地在客户端**内置浏览器 / 侧边面板**里打开。
|
|
529
579
|
|
|
580
|
+
#### 7.2.1 另一种:**让用户自己选金额**(`wallet recharge-link`,独立充值页)
|
|
581
|
+
|
|
582
|
+
用户**没给金额**、或说"我自己选"/"给我个充值链接"时用它。它**不建单、不定金额**,
|
|
583
|
+
只换一张**一次性 ticket** 并给出链接:
|
|
584
|
+
|
|
585
|
+
```bash
|
|
586
|
+
npx -y wkgeo-cli@latest wallet recharge-link # 默认不弹浏览器:交接物就是链接本身
|
|
587
|
+
# ★ 读 data.pay_url —— 形如 https://pay.wkgeo.com/recharge/?ticket=…
|
|
588
|
+
# 把它**原样**发给用户(或做成可点的链接)。他在那一页上:
|
|
589
|
+
# 选金额(¥10 / ¥20 快捷,或自定义;最低 ¥9.90、**不设上限**)→ 提交 → 微信扫码支付。
|
|
590
|
+
# ⚠️ **不需要登录会员中心** —— 凭证就是地址里的 ticket,整条链路与登录态无关。
|
|
591
|
+
# ★ data.paste_text 是"照着念"的一句话(含完整地址),直接转述,别自己组织语言。
|
|
592
|
+
# ★ 有效期只有 10 分钟、且**用掉即失效**(一次性):过期/已用过时页面会明确提示"请重新获取",
|
|
593
|
+
# 这时**重新跑一次本命令**拿一条新链接即可(不要反复让用户刷新旧链接)。
|
|
594
|
+
# ★ 默认**不**打开浏览器(这条命令通常跑在服务器/容器里,且交接物是链接);
|
|
595
|
+
# 确实要在本机弹出时加 --open-browser;--no-browser 优先级最高。
|
|
596
|
+
# ★ ticket 只是"建一笔充值单"的窄凭证:⛔ 不要把它当登录凭据、不要拿它去调别的 action。
|
|
597
|
+
npx -y wkgeo-cli@latest orders check <order_id> # 用户说付完了再查(order_id 从他那句"付完了"对应的单拿)
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
⚠️ **AI 永远不要替用户"确认支付成功"**:只能查。查不到就是没付。
|
|
601
|
+
⚠️ 别把 `ticket` 单独展示成"验证码"念出来:它是**链接的一部分**,原样交付整条链接即可。
|
|
602
|
+
|
|
530
603
|
### 7.3 用户说"查一下我的余额和订单"
|
|
531
604
|
|
|
532
605
|
```bash
|
|
@@ -559,6 +632,61 @@ npx -y wkgeo-cli@latest apps revoke <client_id> # 该应用所有令牌立
|
|
|
559
632
|
|
|
560
633
|
---
|
|
561
634
|
|
|
635
|
+
### 7.5 用户说"帮我在站上发一篇文章 / 换个模板 / 传张图"
|
|
636
|
+
|
|
637
|
+
**这是 CMS 面**(客户站后台的同一批接口)。⛔ 不要用 `orders` / `sites` 那套平台接口去做内容。
|
|
638
|
+
|
|
639
|
+
```bash
|
|
640
|
+
# ① 先定站点(只属于一个站的账号可以跳过;多站必须先选,否则会报 cms_site_required)
|
|
641
|
+
npx -y wkgeo-cli@latest site use 8f3c1a2e-4b5d-4f6a-8b7c-9d0e1f2a3b4c # 或 www.example.com
|
|
642
|
+
npx -y wkgeo-cli@latest site use --json # 看当前选中的是哪个站
|
|
643
|
+
|
|
644
|
+
# ② 看结构(栏目 = 导航;内容挂在栏目下)
|
|
645
|
+
npx -y wkgeo-cli@latest categories list --json # 读 data.rows[].id / name / path / kind / template_path
|
|
646
|
+
|
|
647
|
+
# ③ 写内容(默认草稿;--status published 就立刻在前台可见)
|
|
648
|
+
npx -y wkgeo-cli@latest contents create --category 新闻 --title "公司参展 2026" \
|
|
649
|
+
--body "<p>正文…</p>" --status draft --json
|
|
650
|
+
# 读 data.content.id / status
|
|
651
|
+
# 正文较长时用 --body-file ./article.html(避免命令行转义地狱)
|
|
652
|
+
# 自定义字段用 --ext '{"型号":"X1"}'(键就是后台「字段管理」里的键)
|
|
653
|
+
|
|
654
|
+
# ④ 传图(三步:签名 → 直传 OSS → 登记;CLI 不碰 AK)
|
|
655
|
+
npx -y wkgeo-cli@latest assets upload ./banner.jpg --json # 读 data.asset.id
|
|
656
|
+
npx -y wkgeo-cli@latest contents update <内容ID> --cover <素材ID> --json
|
|
657
|
+
|
|
658
|
+
# ⑤ 改版式(模板是整段 html;改了先备份)
|
|
659
|
+
npx -y wkgeo-cli@latest templates list --json # 读 data.files[].path
|
|
660
|
+
npx -y wkgeo-cli@latest templates get index.html > index.html # 人类模式直出源码(备份)
|
|
661
|
+
npx -y wkgeo-cli@latest templates save index.html --file ./index.html --json
|
|
662
|
+
npx -y wkgeo-cli@latest categories bind-template /about/ about.html --json
|
|
663
|
+
|
|
664
|
+
# ⑥ 看发布状态(前台按需渲染:published 即上线,**没有**"发布"这一步)
|
|
665
|
+
npx -y wkgeo-cli@latest publish --json
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
**怎么把这些命令的失败讲给用户**(`--json` 的 `error.kind`):
|
|
669
|
+
|
|
670
|
+
| kind | 真实含义 | 对用户怎么说 |
|
|
671
|
+
|---|---|---|
|
|
672
|
+
| `cms_site_required` | 他有多个站点,得说清是哪个 | "你的账号有多个站,这次要改哪一个?" |
|
|
673
|
+
| `cms_auth` | 令牌没被 CMS 接受(多半过期/吊销;旧部署才可能是"没启用 CLI 认证") | "内容后台说我的登录失效了,我帮你重新授权一次"(跑 `login`) |
|
|
674
|
+
| `cms_not_member` | 不是这个站的成员 / 站点 id 不对 | "这个站我没有权限,帮我确认一下是哪个站?" |
|
|
675
|
+
| `cms_readonly` | 他的站点角色是只读 | "你在这个站是只读权限,要改成能编辑得找站长加一下" |
|
|
676
|
+
| `cms_scope` | 令牌能力不够(如模板保存要 `template:write`) | "这个操作需要更高的授权范围,得重新授权一次(或让管理员放开)" |
|
|
677
|
+
| `cms_unavailable` | CMS 地址不通 / 云函数没部署 | "内容后台暂时连不上,可能要等运维部署" |
|
|
678
|
+
| `not_deployed` | 服务端版本落后(没有这个动作) | "后台那边还没更新到这个功能,稍后再试" |
|
|
679
|
+
|
|
680
|
+
**铁律(CMS 面)**:
|
|
681
|
+
|
|
682
|
+
1. **先 `site use` 或 `--site`** —— 改错站的代价比多问一句高得多;
|
|
683
|
+
2. **写内容默认草稿**(`--status draft`),用户明确说"发出去"才用 `published`;
|
|
684
|
+
3. **不要顺手删**:`contents delete` / `categories delete` 前必须让用户确认对象(标题 + 栏目);
|
|
685
|
+
4. **单页栏目**(`kind=page`)的内容只能改不能建;用户要"加一页"= 加子栏目,不是建内容;
|
|
686
|
+
5. `import`(老站导入)**默认 dry-run**、且需要运维权限 —— 不要对普通客户承诺"我能直接导"。
|
|
687
|
+
|
|
688
|
+
---
|
|
689
|
+
|
|
562
690
|
## 8. 安全(**必须遵守**)
|
|
563
691
|
|
|
564
692
|
1. **绝不打印/转述令牌**:不要 `cat ~/.wkongai/credentials.json`,不要把它放进任何请求体或日志。
|
|
@@ -570,7 +698,7 @@ npx -y wkgeo-cli@latest apps revoke <client_id> # 该应用所有令牌立
|
|
|
570
698
|
5. **不要发起真实扣款**:`login`/`wallet recharge` 只创建订单/链接;
|
|
571
699
|
所有"付款"都必须由用户在**我们网站的收银台页面**用微信完成。自动化测试里**绝不**走真钱路径。
|
|
572
700
|
6. **收银台是我们自己的页面**:`wallet recharge` 的正确交接物是 `pay_url`
|
|
573
|
-
(`https://pay.wkgeo.com
|
|
701
|
+
(`https://pay.wkgeo.com/?order_id=…`),不是 `code_url`。
|
|
574
702
|
不要在本地自己画一个二维码页面让用户扫 —— 那是被明确否掉的做法。
|
|
575
703
|
7. **限流是保护,不是故障**:429 时按 `retry_after` 退避;**不要**用重新登录或换令牌来"绕过"限流。
|
|
576
704
|
8. 遇到 `client_secret`、`authorization_code`、`access_token` 之类的字段:
|
|
@@ -584,15 +712,31 @@ npx -y wkgeo-cli@latest apps revoke <client_id> # 该应用所有令牌立
|
|
|
584
712
|
| --- | --- | --- |
|
|
585
713
|
| `whoami` 返回 exit 3 | 还没登录 / 令牌过期 / 被吊销 | 跑 `login`,把网址给用户点同意 |
|
|
586
714
|
| 浏览器授权后显示"无法访问此网站" | 那一刻本机没有 CLI 在监听(login 被 Ctrl+C 或已退出);**或代理接管了 127.0.0.1** | 重新 `login`(开着代理时 CLI 会自动改设备码);并**保持它在前台**直到点完「同意」 |
|
|
587
|
-
| `login` 等到超时(`kind:"timeout"`) | 用户没点完,**或代理把回调吃掉了** |
|
|
588
|
-
| 事件流第一行是 `awaiting_user` 而不是 `awaiting_callback` |
|
|
589
|
-
| 事件流是 `awaiting_callback`,然后 `data.auto_device.reason:"callback_first_wait"` | ★
|
|
590
|
-
| 用户说「我**没开代理**,为什么变成设备码了」 | ★
|
|
591
|
-
| 用户随后才点【同意授权】→ 浏览器显示 **ERR_CONNECTION_REFUSED** | ★ 2026-10-03
|
|
715
|
+
| `login` 等到超时(`kind:"timeout"`) | 用户没点完,**或代理把回调吃掉了** | ★ 0.2.2 起超时**不会**自动改设备码:看 `hint` 与 `meta.proxy_warning`。若用户确认本地读不了回调,让他**显式**加 `--device` 重跑;若检测到代理,CLI 默认**已经**在第一跳直接改设备码了(除非加了 `--no-auto-device`) |
|
|
716
|
+
| 事件流第一行是 `awaiting_user` 而不是 `awaiting_callback` | 只有两种可能:**检测到系统代理**(CLI 直接改设备码;绕过列表写了 127.* 也照样改)或用户显式 `--device` | 按 §5.3 把 `paste_text` 转述给用户;想强制回调加 `--no-auto-device`(CLI 会警告风险) |
|
|
717
|
+
| 事件流是 `awaiting_callback`,然后 `data.auto_device.reason:"callback_first_wait"` | ★ **0.2.2 起只可能**是用户/调用方**显式**写了 `--callback-first-wait`(默认关闭):首轮等待没收到回调 → CLI 并发改设备码(**本地回调监听同时保留**) | 正常自愈;如实告诉用户"已同时改用设备码,两条路哪条先成功算哪条,不用重来" |
|
|
718
|
+
| 用户说「我**没开代理**,为什么变成设备码了」 | ★ 0.2.2 起默认就是浏览器回调,正常情况下**不会**再发生。若真出现,只可能是:① `proxy_warning.detected:true`(真探到了系统代理);② `reason:"callback_listen_failed"`(本地端口起不来);③ 用户自己显式 `--device` / `--callback-first-wait` | 按 `data.auto_device.reason` 如实解释;先看 `data.proxy_warning.detected`(`config --json` 能看来源) |
|
|
719
|
+
| 用户随后才点【同意授权】→ 浏览器显示 **ERR_CONNECTION_REFUSED** | ★ 2026-10-03 已修:显式首轮等待切设备码时**不再关掉**本地回调监听(旧版一关就是这个报错)。若仍出现,说明 CLI 进程已经退出(Ctrl+C / 终端关掉了) | 让用户直接在**这一次**的浏览器页面上点同意即可(监听还在),或重跑 `login`;不要让他以为授权失败 |
|
|
592
720
|
| `login --device-continue` 报 `kind:"expired"` | 短码过期(默认 10 分钟)或已被换过票 | 重新 `login --device --no-wait` 申请新短码;**别**反复续跑 |
|
|
593
721
|
| 下单直接返回 `paid:true` | 服务端设计:下单时余额足够就直接扣款并履约 | 这是正常的"钱包支付";用 `wallet` 复核余额 |
|
|
594
722
|
| `sites create` 报 400「无法确定所属客户」 | `owner/admin` 这类账号必须显式指定客户 | 加 `--customer <客户ID>` |
|
|
723
|
+
| CMS 命令报 `cms_auth`(401) | 令牌失效(过期/吊销/客户端停用);旧部署才可能是"没启用 CLI 认证桥" | 先 `wkgeo login` 重新授权一次;仍 401 再让管理员确认服务是否为新版(**别**反复 login) |
|
|
724
|
+
| CMS 命令报 `cms_site_required` | 账号有多个站点、没指定 | `wkgeo site use <站点ID>` 或加 `--site <站点ID>` |
|
|
725
|
+
| `--site` 写了域名没生效 | 后端只按**站点 id** 查,域名会被当成"没指定" | 先 `wkgeo site use <域名>` 解析成 id(CLI 已在本地挡住这种写法) |
|
|
726
|
+
| `templates save` / `assets list` 报 403 `cms_scope` | 令牌是**升级前签的**,缺 `template:*` / `attachment:*`(客户端与默认 scope 现已放开) | 让用户重新授权一次:`login`(默认就带全部所需能力);**不是** bug,也别改用别的通道 |
|
|
727
|
+
| `assets upload` 报 403 | 令牌缺 `attachment:write`(或站点角色只读) | 看 `error.kind`:`cms_scope` → 重新授权;`cms_readonly` → 找 owner 提权 |
|
|
728
|
+
| `import` 报 `import_unavailable` | 本机没有 `tencent/cloudbase/import-site.mjs`(npx 装的包里没有它) | 只能在本仓库机器上跑;**不要**对客户承诺"我能直接导" |
|
|
595
729
|
| 429 | 调用过于频繁 | 等 `retry_after` 秒;**不要**重新授权 |
|
|
596
730
|
| `apps list` 报"未部署" | 该环境的 data 云函数还没发版(**线上已发版并实测过**,见 README §9) | 告诉用户"这是服务端缺口",不要反复重试;`logout` 仍可清理本地登录态 |
|
|
597
731
|
| `skill` 报「当前安装包里没有手册文件(SKILL.md)」 | 跑的是**被裁剪的包**或只拷了 `lib/` 的开发目录(正常 npm 包一定有) | 换 `npx -y wkgeo-cli@latest skill`;这不是命令用错了(`error.kind="missing_skill"`,退出码 1) |
|
|
598
732
|
| 想升级 CLI | 全局安装不会自动升级 | 用 `npx -y wkgeo-cli@latest`,或 `npm i -g wkgeo-cli@latest` |
|
|
733
|
+
|
|
734
|
+
## 云端能力(阿里云侧由云函数执行,CLI 不持有 AK)
|
|
735
|
+
|
|
736
|
+
绑域名 / 新建 ESA 站点 / 传 OSS / 发布边缘函数 / 查配额这些**阿里云侧操作**,
|
|
737
|
+
一律通过云端管理接口(FC 函数 `wkgeo-admin`)完成 —— **CLI 与桌面都不持有阿里云 AK**。
|
|
738
|
+
|
|
739
|
+
- 能力清单、权限范围(scope)、请求头要求、curl 示例、已知坑:`aliyun/fc/wkgeo-admin/README.md`
|
|
740
|
+
- 背景与验证记录:`docs/建站-云端管理接口.md`
|
|
741
|
+
- 地址 `https://wkgeo-admin-nyvdudigpb.cn-shanghai.fcapp.run`;必带 `Authorization: Bearer <平台签发的 JWT>` 与 `Date`(RFC1123)
|
|
742
|
+
- scope:`read` / `domain:bind` / `site:create` / `kv:write` / `oss:write` / `routine:deploy`
|
package/lib/args.mjs
CHANGED
|
@@ -20,6 +20,11 @@ import { UsageError } from './errors.mjs';
|
|
|
20
20
|
/** 全局标志:任何命令都接受(写在 spec 之外,避免每个命令重复声明) */
|
|
21
21
|
export const GLOBAL_FLAGS = {
|
|
22
22
|
base: { type: 'string', desc: 'API 基址(默认线上网关,可用 WKONGAI_BASE 覆盖)' },
|
|
23
|
+
/**
|
|
24
|
+
* CMS 面是**另一个云函数 / 另一个域名**(新写法 `https://api.wkgeo.com/cms`),
|
|
25
|
+
* 所以单独给一个基址开关:联调 / 换环境时不用去改平台面的 `--base`。
|
|
26
|
+
*/
|
|
27
|
+
'cms-base': { type: 'string', desc: 'CMS 接口基址(默认 https://api.wkgeo.com/cms,可用 WKONGAI_CMS_BASE 覆盖)' },
|
|
23
28
|
'web-base': { type: 'string', desc: '前端基址(授权页兜底地址)' },
|
|
24
29
|
'client-id': { type: 'string', desc: 'OAuth 客户端 id(默认 wkgeo-cli)' },
|
|
25
30
|
scope: { type: 'string', desc: '申请的能力范围(空格分隔)' },
|
package/lib/cli.mjs
CHANGED
|
@@ -98,6 +98,11 @@ export async function run(argv = [], io = {}) {
|
|
|
98
98
|
*/
|
|
99
99
|
platform: io.platform,
|
|
100
100
|
exec: io.exec,
|
|
101
|
+
/**
|
|
102
|
+
* `wkgeo import` 起子进程的注入点(同步;生产默认 `spawnSync`)。
|
|
103
|
+
* 单测注入它就能验证"脚本参数怎么拼、退出码怎么转述",不真的去起子进程抓网站。
|
|
104
|
+
*/
|
|
105
|
+
runScript: io.runScript,
|
|
101
106
|
/** 同上:`skill` 手册位置的注入点(单测验证"包里没有手册"分支时用,见 lib/commands/skill.mjs) */
|
|
102
107
|
skillUrl: io.skillUrl,
|
|
103
108
|
});
|