@manturhub/cli 0.6.0 → 0.7.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/bin/cli.js CHANGED
@@ -5,6 +5,7 @@ import { runMcpBridge } from "../lib/mcp.js";
5
5
  import { runInit, runMcpInstall } from "../lib/setup.js";
6
6
  import { skillLs, skillAdd } from "../lib/skill-install.js";
7
7
  import { suiteLs, suiteInstall } from "../lib/suite-install.js";
8
+ import { loginViaBrowser } from "../lib/login-link.js";
8
9
  import { maybeNotifyUpdate } from "../lib/update-check.js";
9
10
  import { readFileSync } from "node:fs";
10
11
  import { fileURLToPath } from "node:url";
@@ -37,7 +38,8 @@ function getFlag(name, def) {
37
38
  const HELP = `manturhub — ManturHub 算子广场 CLI v${VERSION}
38
39
 
39
40
  用法:
40
- manturhub login --key sk-xxx 配置 API Key(存 ~/.manturhub/config.json)
41
+ manturhub login 浏览器授权登录(生成链接→登录创建 Key→自动导入,推荐)
42
+ manturhub login --key sk-xxx 手动配置 API Key(存 ~/.manturhub/config.json)
41
43
  manturhub ls [--cat <分类>] 列出上线算子(分类: text/image/video/audio/data)
42
44
  manturhub describe <算子ID> 查看算子入参字段(喂参数前先看)
43
45
  manturhub run <算子ID> --json '{}' 调用算子(异步算子自动轮询到出结果;--no-wait 只拿 job_id)
@@ -71,8 +73,9 @@ async function main() {
71
73
  case "login": {
72
74
  const key = getFlag("key");
73
75
  if (!key) {
74
- console.error("用法: manturhub login --key sk-xxx");
75
- process.exit(1);
76
+ // --key → 浏览器授权流:生成链接,登录创建 key 后自动导入
77
+ await loginViaBrowser();
78
+ break;
76
79
  }
77
80
  const cfg = loadConfig();
78
81
  cfg.key = key;
@@ -0,0 +1,88 @@
1
+ // 浏览器授权登录(OAuth 2.0 Device Authorization Grant 变体)。
2
+ // manturhub login(不带 --key)→ 生成链接 → 浏览器登录创建 key → 自动回传 CLI。
3
+ // key 只经后端 poll(device_code)下发,绝不进浏览器 URL。
4
+ import { spawn } from "node:child_process";
5
+ import { getBaseUrl, loadConfig, saveConfig } from "./config.js";
6
+ import { apiFetch } from "./api.js";
7
+
8
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
9
+
10
+ // 尽力自动打开浏览器;打不开也没关系,链接已打印在终端
11
+ function openBrowser(url) {
12
+ const p = process.platform;
13
+ const cmd = p === "darwin" ? "open" : p === "win32" ? "cmd" : "xdg-open";
14
+ const cmdArgs = p === "win32" ? ["/c", "start", "", url] : [url];
15
+ try {
16
+ const child = spawn(cmd, cmdArgs, { stdio: "ignore", detached: true });
17
+ child.on("error", () => {});
18
+ child.unref();
19
+ } catch {
20
+ /* ignore */
21
+ }
22
+ }
23
+
24
+ export async function loginViaBrowser() {
25
+ const base = getBaseUrl();
26
+
27
+ // 1. 发起 CLI 会话(无鉴权)
28
+ let session;
29
+ try {
30
+ const r = await fetch(base + "/api/v1/cli/session", { method: "POST" });
31
+ if (!r.ok) throw new Error("HTTP " + r.status);
32
+ session = await r.json();
33
+ } catch (e) {
34
+ console.error(
35
+ `\n 发起登录失败(${e.message})。可改用手动方式:\n manturhub login --key sk-xxx\n`
36
+ );
37
+ process.exit(1);
38
+ }
39
+ const { device_code, user_code, verify_url, interval = 2, expires_in = 600 } = session;
40
+
41
+ console.log("\n 在浏览器里打开以下链接,登录后创建并授权 Key(已尝试自动打开):\n");
42
+ console.log(" \x1b[36m" + verify_url + "\x1b[0m\n");
43
+ console.log(
44
+ " 核对码(请确认浏览器页面显示的码与此一致再创建): \x1b[1m" + user_code + "\x1b[0m\n"
45
+ );
46
+ openBrowser(verify_url);
47
+ console.log(" 等待授权中…(在网页里给这次登录起个 Key 名称并点「创建」)");
48
+
49
+ // 2. 轮询领 key
50
+ const deadline = Date.now() + expires_in * 1000;
51
+ while (Date.now() < deadline) {
52
+ await sleep(interval * 1000);
53
+ let poll;
54
+ try {
55
+ const r = await fetch(
56
+ base + "/api/v1/cli/poll?device_code=" + encodeURIComponent(device_code)
57
+ );
58
+ poll = await r.json();
59
+ if (r.status === 410 || poll.status === "expired") {
60
+ console.error("\n 授权码已过期,请重新运行 manturhub login。\n");
61
+ process.exit(1);
62
+ }
63
+ } catch {
64
+ continue; // 网络抖动,继续轮询
65
+ }
66
+ if (poll.status === "ready" && poll.key) {
67
+ const cfg = loadConfig();
68
+ cfg.key = poll.key;
69
+ saveConfig(cfg);
70
+ const me = await apiFetch("/api/v1/me", { key: poll.key });
71
+ if (me.ok) {
72
+ console.log(
73
+ `\n ✓ 授权成功,Key 已导入 ~/.manturhub/config.json。账号: ${
74
+ me.json.email || "-"
75
+ } 余额: ${me.json.balance ?? "-"} 馒头\n`
76
+ );
77
+ } else {
78
+ console.log(
79
+ `\n ✓ Key 已导入,但验证返回 HTTP ${me.status}(稍后可用 manturhub balance 再确认)。\n`
80
+ );
81
+ }
82
+ return;
83
+ }
84
+ // pending → 继续等
85
+ }
86
+ console.error("\n 等待超时(未在时限内完成授权)。请重新运行 manturhub login。\n");
87
+ process.exit(1);
88
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manturhub/cli",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "ManturHub 算子广场 CLI:命令行直调 AI 算子 + 安装平台 Skill + 给 Claude Code / Codex / Cursor 等当 stdio MCP server",
5
5
  "type": "module",
6
6
  "bin": {