@manturhub/cli 0.8.1 → 0.8.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 CHANGED
@@ -43,7 +43,7 @@ CLI 会在付费调用前按算子实时 schema 校验未知字段、必填项
43
43
  | `manturhub upload <本地文件>` | 流式上传图片、音频或视频并输出公网 URL |
44
44
  | `manturhub status <poll_url>` | 查询 `run --no-wait` 返回的异步任务 |
45
45
  | `manturhub balance [--json]` | 查询余额及美元等值(1 馒头 = $0.01 USD) |
46
- | `manturhub skill ls [--json]` / `skill add <slug> --client codex` | 浏览和安装业务 Skill |
46
+ | `manturhub skill ls [--json]` / `skill add <slug> [--client codex]` | 浏览和安装业务 Skill;默认自动识别 Agent |
47
47
  | `manturhub recipe [关键词]` / `recipe get <ID>` | 搜索并查看已验证配方 |
48
48
  | `manturhub suite ls [--json]` / `suite install <slug>` | 安装多角色 Agent 套件,不复制 API Key |
49
49
  | `manturhub init` | 给当前项目写入 Agent 使用引导 |
package/bin/cli.js CHANGED
@@ -100,7 +100,7 @@ const HELP = `manturhub — ManturHub 算子广场 CLI v${VERSION}
100
100
  manturhub init 装「ManturHub 使用 skill」+ 写 agent 引导(推荐:让 agent 会用算子)
101
101
  manturhub skill ls 列出平台 Skill(业务成品流程,如爆款复刻)
102
102
  manturhub skill add <slug> [--client claude-code|codex|all]
103
- 安装 Skill 到指定 Agent
103
+ 自动识别 Agent 并安装 Skill(可显式指定)
104
104
  manturhub suite ls 列出 Agent 套件(多角色团队工作区,给 Agent 配一整个团队)
105
105
  manturhub suite install <slug> 安装套件为工作目录 ./<slug>/(不复制 API Key)
106
106
  manturhub recipe [关键词] [--cat x] 搜配方(已验证创作的效果+可复现参数;分类 video/image/script)
@@ -469,7 +469,7 @@ async function main() {
469
469
  console.error(error.message);
470
470
  process.exit(1);
471
471
  }
472
- await skillAdd(args[2], getFlag("client", "claude-code"));
472
+ await skillAdd(args[2], getFlag("client"));
473
473
  }
474
474
  else {
475
475
  console.error("用法: manturhub skill ls | manturhub skill add <slug> [--client claude-code|codex|all]");
@@ -0,0 +1,88 @@
1
+ import { existsSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { createInterface } from "node:readline/promises";
5
+ import { determineAgent } from "@vercel/detect-agent";
6
+
7
+ const SUPPORTED_CLIENTS = new Set(["claude", "claude-code", "codex", "all"]);
8
+
9
+ export function normalizeClient(client) {
10
+ if (client === undefined || client === null || client === "") return null;
11
+ if (!SUPPORTED_CLIENTS.has(client)) {
12
+ throw new Error("不支持的 client。可用值: claude-code | codex | all");
13
+ }
14
+ return client === "claude" ? "claude-code" : client;
15
+ }
16
+
17
+ export function clientForAgentName(name) {
18
+ if (name === "claude" || name === "cowork") return "claude-code";
19
+ if (name === "codex") return "codex";
20
+ return null;
21
+ }
22
+
23
+ export function detectInstalledClients({ home = homedir(), exists = existsSync } = {}) {
24
+ const clients = [];
25
+ if (exists(join(home, ".claude"))) clients.push("claude-code");
26
+ if (exists(join(home, ".codex")) || exists("/etc/codex")) clients.push("codex");
27
+ return clients;
28
+ }
29
+
30
+ function displayClient(client) {
31
+ if (client === "all") return "Claude Code、Codex";
32
+ return client === "codex" ? "Codex" : "Claude Code";
33
+ }
34
+
35
+ async function promptForClient(input, output, installedClients) {
36
+ const detected = installedClients.length
37
+ ? `\n检测到: ${installedClients.map(displayClient).join("、")}`
38
+ : "";
39
+ output.write(`${detected}\n请选择 Skill 安装目标:\n 1) Codex\n 2) Claude Code\n 3) 两者\n`);
40
+ const rl = createInterface({ input, output });
41
+ try {
42
+ const answer = (await rl.question("请输入 1 / 2 / 3: ")).trim();
43
+ if (answer === "1") return "codex";
44
+ if (answer === "2") return "claude-code";
45
+ if (answer === "3") return "all";
46
+ throw new Error("已取消:请输入 1、2 或 3,或使用 --client 明确指定。");
47
+ } finally {
48
+ rl.close();
49
+ }
50
+ }
51
+
52
+ export async function resolveSkillClient(
53
+ client,
54
+ {
55
+ detectAgent = determineAgent,
56
+ installedClients,
57
+ input = process.stdin,
58
+ output = process.stdout,
59
+ } = {}
60
+ ) {
61
+ const explicit = normalizeClient(client);
62
+ if (explicit) return { client: explicit, detected: false };
63
+
64
+ const agent = await detectAgent();
65
+ const runtimeClient = agent.isAgent ? clientForAgentName(agent.agent?.name) : null;
66
+ if (runtimeClient) return { client: runtimeClient, detected: true };
67
+
68
+ const installed = installedClients ?? detectInstalledClients();
69
+ if (installed.length === 1) return { client: installed[0], detected: true };
70
+
71
+ if (input.isTTY && output.isTTY) {
72
+ return {
73
+ client: await promptForClient(input, output, installed),
74
+ detected: false,
75
+ };
76
+ }
77
+
78
+ if (installed.length > 1) {
79
+ throw new Error(
80
+ "检测到 Claude Code 和 Codex,但当前无法交互选择。请加 --client codex、--client claude-code 或 --client all。"
81
+ );
82
+ }
83
+ throw new Error(
84
+ "未识别到 Codex 或 Claude Code。请在 Agent 内重试,或加 --client codex|claude-code|all。"
85
+ );
86
+ }
87
+
88
+ export { displayClient };
@@ -5,6 +5,7 @@ import { getKey, getBaseUrl } from "./config.js";
5
5
  import { extractZipSafely, validateSlug } from "./archive.js";
6
6
  import { apiFetch } from "./api.js";
7
7
  import { assertSecureDownloadUrl, downloadResponseToFile } from "./download.js";
8
+ import { displayClient, resolveSkillClient } from "./agent-target.js";
8
9
 
9
10
  // `manturhub skill ls` — 列出平台上线 Skill(公开元数据,无需 key;
10
11
  // 配了 key 则带上——管理员租户的 key 能看到 admin 专属 Skill)。
@@ -34,11 +35,11 @@ export async function skillLs({ json = false } = {}) {
34
35
  const ver = s.version ? `v${s.version}` : "";
35
36
  console.log(` ${slug} ${s.name || ""} ${cat} ${ver}`.trimEnd());
36
37
  }
37
- console.log(`\n用 \`manturhub skill add <slug> --client claude-code|codex|all\` 安装到指定 Agent。`);
38
+ console.log(`\n用 \`manturhub skill add <slug>\` 自动识别 Agent;也可用 \`--client\` 明确指定。`);
38
39
  }
39
40
 
40
- // `manturhub skill add <slug>` — 下载并安全解压到指定 Agent 的用户级 skills 目录。
41
- export async function skillAdd(slug, client = "claude-code") {
41
+ // `manturhub skill add <slug>` — 自动识别 Agent,下载并安全解压到用户级 skills 目录。
42
+ export async function skillAdd(slug, client) {
42
43
  if (!slug) {
43
44
  console.error("用法: manturhub skill add <slug> (先 `manturhub skill ls` 看可用 Skill)");
44
45
  process.exit(1);
@@ -49,6 +50,16 @@ export async function skillAdd(slug, client = "claude-code") {
49
50
  console.error(error.message);
50
51
  process.exit(1);
51
52
  }
53
+ let target;
54
+ try {
55
+ target = await resolveSkillClient(client);
56
+ } catch (error) {
57
+ console.error(error.message);
58
+ process.exit(1);
59
+ }
60
+ client = target.client;
61
+ if (target.detected) console.log(`✓ 已识别 Agent:${displayClient(client)}`);
62
+
52
63
  const key = getKey();
53
64
  if (!key) {
54
65
  console.error("下载 Skill 需 API Key。运行 `manturhub login`,或设置环境变量 MANTURHUB_KEY。");
@@ -96,13 +107,8 @@ export async function skillAdd(slug, client = "claude-code") {
96
107
  console.error(`下载失败(HTTP ${res.status})`);
97
108
  process.exit(1);
98
109
  }
99
- const supported = new Set(["claude", "claude-code", "codex", "all"]);
100
- if (!supported.has(client)) {
101
- console.error("不支持的 client。可用值: claude-code | codex | all");
102
- process.exit(1);
103
- }
104
110
  const destinations = [];
105
- if (client === "claude" || client === "claude-code" || client === "all") {
111
+ if (client === "claude-code" || client === "all") {
106
112
  destinations.push(join(homedir(), ".claude", "skills", slug));
107
113
  }
108
114
  if (client === "codex" || client === "all") {
@@ -122,5 +128,5 @@ export async function skillAdd(slug, client = "claude-code") {
122
128
  }
123
129
  rmSync(tempDir, { recursive: true, force: true });
124
130
  for (const dest of destinations) console.log(`✓ 已安装 Skill「${slug}」→ ${dest}`);
125
- console.log(" 重启对应 Agent 后,用自然语言描述任务;Claude Code 也可用 /<slug> 触发。");
131
+ console.log(" 重启对应 Agent 后,用自然语言描述任务即可使用。");
126
132
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manturhub/cli",
3
- "version": "0.8.1",
3
+ "version": "0.8.2",
4
4
  "description": "ManturHub 算子广场 CLI:通过 REST 发现和调用 AI 算子、浏览配方,并安装 Skill 与 Agent 套件",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,6 +9,9 @@
9
9
  "engines": {
10
10
  "node": ">=18"
11
11
  },
12
+ "dependencies": {
13
+ "@vercel/detect-agent": "^1.2.1"
14
+ },
12
15
  "scripts": {
13
16
  "test": "node --test",
14
17
  "prepack": "npm test"