c456-cli 0.1.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 +134 -0
- package/dist/index.js +742 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="logo.svg" alt="C456" width="160" height="160" />
|
|
4
|
+
|
|
5
|
+
<br />
|
|
6
|
+
|
|
7
|
+
<a href="https://c456.com">https://c456.com</a>
|
|
8
|
+
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
# c456-cli
|
|
12
|
+
|
|
13
|
+
C456 命令行工具:通过 **HTTP API v1** 读写收录、打法等数据,适合本地使用或与 AI Agent 集成。
|
|
14
|
+
|
|
15
|
+
## 安装
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g c456-cli
|
|
19
|
+
# 或
|
|
20
|
+
bun add -g c456-cli
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
安装后的命令名为 **`c456`**。也可用 `npx` / `bunx` 单次执行:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx c456-cli --help
|
|
27
|
+
bunx c456-cli --help
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 配置
|
|
31
|
+
|
|
32
|
+
### API Key
|
|
33
|
+
|
|
34
|
+
在 Web 端登录后,于「API Key / 访问令牌」中创建密钥(仅创建时可见全文)。
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
c456 config set-key <your-token>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
或通过环境变量(适合 CI / Agent):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
export C456_API_KEY=<your-token>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 站点地址
|
|
47
|
+
|
|
48
|
+
若使用自托管实例,需指定**站点根 URL**(与浏览器访问地址一致,无尾部 `/api`):
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
c456 config set-url https://your-c456.example.com
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
或环境变量:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
export C456_URL=https://your-c456.example.com
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
命令行临时覆盖(**推荐用于多环境**,注意与子命令里的 `-u`「目标 URL」区分):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
c456 -B https://your-c456.example.com intake list
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 查看配置
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
c456 config show
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
配置文件遵循 XDG:默认 `~/.config/c456/config.json`(可通过 `XDG_CONFIG_HOME` 调整)。**请勿将含密钥的文件提交到仓库**;密钥等效于账户凭据。
|
|
73
|
+
|
|
74
|
+
## 全局选项
|
|
75
|
+
|
|
76
|
+
| 选项 | 环境变量 | 说明 |
|
|
77
|
+
| --- | --- | --- |
|
|
78
|
+
| `-B`, `--base-url <url>` | `C456_URL` | C456 站点根地址;未设置时默认 `https://c456.com`(仍以配置文件为准) |
|
|
79
|
+
|
|
80
|
+
**API Key** 不设全局短选项(与子命令里 **`-k` = kind** 冲突):请用「[配置 > API Key](#api-key)」中的 `c456 config set-key` 或 `C456_API_KEY`。
|
|
81
|
+
|
|
82
|
+
`baseUrl` 优先级:**`-B` / 环境变量 / 配置文件 / 内置默认**;`apiKey` 优先级:**环境变量 / 配置文件**(无内置默认)。
|
|
83
|
+
|
|
84
|
+
## 常用命令
|
|
85
|
+
|
|
86
|
+
### 收录(intake)
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# 按 URL 创建 tool 收录(-B 为站点,-u 为收录目标)
|
|
90
|
+
c456 -B https://c456.example.com intake new -k tool -u "https://github.com/owner/repo"
|
|
91
|
+
|
|
92
|
+
# 纯文本信号(可无 URL)
|
|
93
|
+
c456 intake new -k signal -t "标题" -b "正文"
|
|
94
|
+
|
|
95
|
+
c456 intake show <id>
|
|
96
|
+
c456 intake list -k signal -q "关键词"
|
|
97
|
+
c456 intake update <id> -t "新标题"
|
|
98
|
+
c456 intake delete <id> --force
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 资料抓取(fetch)
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
c456 fetch profile -u "https://..." -p link_product
|
|
105
|
+
c456 fetch detect -u "https://..."
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 搜索(search)
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
c456 search signals -q "关键词"
|
|
112
|
+
c456 search playbooks -q "关键词"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 打法(playbook)
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
c456 playbook new -t "标题" -b "Markdown 正文"
|
|
119
|
+
c456 playbook show <id>
|
|
120
|
+
c456 playbook list -q "关键词"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## 开发
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
cd c456-cli
|
|
127
|
+
bun install
|
|
128
|
+
bun run build
|
|
129
|
+
node dist/index.js --help
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 许可证
|
|
133
|
+
|
|
134
|
+
MIT
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,742 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.js
|
|
4
|
+
import { Command as Command6 } from "commander";
|
|
5
|
+
|
|
6
|
+
// package.json
|
|
7
|
+
var package_default = {
|
|
8
|
+
name: "c456-cli",
|
|
9
|
+
version: "0.1.0",
|
|
10
|
+
description: "C456 CLI - \u5185\u5BB9\u5F55\u5165\u4E0E\u6574\u7406\u5DE5\u5177",
|
|
11
|
+
type: "module",
|
|
12
|
+
bin: {
|
|
13
|
+
c456: "dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
files: [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
scripts: {
|
|
20
|
+
build: "node scripts/build.js",
|
|
21
|
+
prepublishOnly: "npm run build"
|
|
22
|
+
},
|
|
23
|
+
dependencies: {
|
|
24
|
+
cfonts: "^3.3.1",
|
|
25
|
+
commander: "^12.1.0",
|
|
26
|
+
open: "^10.1.0"
|
|
27
|
+
},
|
|
28
|
+
devDependencies: {
|
|
29
|
+
esbuild: "^0.24.0"
|
|
30
|
+
},
|
|
31
|
+
keywords: [
|
|
32
|
+
"c456",
|
|
33
|
+
"cli",
|
|
34
|
+
"content",
|
|
35
|
+
"intake"
|
|
36
|
+
],
|
|
37
|
+
license: "MIT",
|
|
38
|
+
engines: {
|
|
39
|
+
node: ">=20.0.0"
|
|
40
|
+
},
|
|
41
|
+
homepage: "https://github.com/xiaohui-zhangxh/c456#c456-cli",
|
|
42
|
+
repository: {
|
|
43
|
+
type: "git",
|
|
44
|
+
url: "git+https://github.com/xiaohui-zhangxh/c456.git",
|
|
45
|
+
directory: "c456-cli"
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// src/commands/intake.js
|
|
50
|
+
import { Command } from "commander";
|
|
51
|
+
|
|
52
|
+
// src/client.js
|
|
53
|
+
import { readFileSync } from "node:fs";
|
|
54
|
+
import { join, dirname } from "node:path";
|
|
55
|
+
import { fileURLToPath } from "node:url";
|
|
56
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
57
|
+
var CONFIG_DIR = join(process.env.XDG_CONFIG_HOME || process.env.HOME || process.env.USERPROFILE || ".", ".config", "c456");
|
|
58
|
+
var CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
59
|
+
function loadConfig() {
|
|
60
|
+
try {
|
|
61
|
+
const raw = readFileSync(CONFIG_PATH, "utf-8");
|
|
62
|
+
return JSON.parse(raw);
|
|
63
|
+
} catch {
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async function saveConfig(config) {
|
|
68
|
+
const fs = await import("node:fs");
|
|
69
|
+
const path = await import("node:path");
|
|
70
|
+
const dir = path.dirname(CONFIG_PATH);
|
|
71
|
+
if (!fs.existsSync(dir)) {
|
|
72
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
73
|
+
}
|
|
74
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
|
|
75
|
+
}
|
|
76
|
+
function getApiKey() {
|
|
77
|
+
return process.env.C456_API_KEY || loadConfig().apiKey || null;
|
|
78
|
+
}
|
|
79
|
+
function getBaseUrl(cliBaseUrl) {
|
|
80
|
+
const fromCli = cliBaseUrl !== void 0 && cliBaseUrl !== null && String(cliBaseUrl).trim() !== "" ? String(cliBaseUrl).replace(/\/+$/, "") : null;
|
|
81
|
+
const raw = fromCli || process.env.C456_URL || loadConfig().baseUrl || "https://c456.com";
|
|
82
|
+
return String(raw).replace(/\/+$/, "");
|
|
83
|
+
}
|
|
84
|
+
function getRootCommand(cmd) {
|
|
85
|
+
let c = cmd;
|
|
86
|
+
while (c.parent) c = c.parent;
|
|
87
|
+
return c;
|
|
88
|
+
}
|
|
89
|
+
function metaPerPage(meta) {
|
|
90
|
+
if (!meta) return 20;
|
|
91
|
+
const n = meta.per_page ?? meta.perPage;
|
|
92
|
+
return n !== void 0 && n !== null && Number(n) > 0 ? Number(n) : 20;
|
|
93
|
+
}
|
|
94
|
+
function formatApiErrorMessage(error) {
|
|
95
|
+
if (!error || typeof error !== "object") {
|
|
96
|
+
return String(error ?? "\u8BF7\u6C42\u5931\u8D25");
|
|
97
|
+
}
|
|
98
|
+
const base = (error.message ?? "\u8BF7\u6C42\u5931\u8D25").trim();
|
|
99
|
+
const fields = error.fields;
|
|
100
|
+
if (!fields || typeof fields !== "object") {
|
|
101
|
+
return base;
|
|
102
|
+
}
|
|
103
|
+
const keys = Object.keys(fields);
|
|
104
|
+
if (keys.length === 0) {
|
|
105
|
+
return base;
|
|
106
|
+
}
|
|
107
|
+
const label = (k) => k === "base" ? "\u8BF4\u660E" : k;
|
|
108
|
+
const lines = keys.map((k) => ` \u2022 ${label(k)}\uFF1A${fields[k]}`);
|
|
109
|
+
return `${base}
|
|
110
|
+
${lines.join("\n")}`;
|
|
111
|
+
}
|
|
112
|
+
var ApiClient = class {
|
|
113
|
+
constructor(baseUrl, apiKey) {
|
|
114
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
115
|
+
this.apiKey = apiKey;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* 构建请求头
|
|
119
|
+
*/
|
|
120
|
+
headers() {
|
|
121
|
+
const h = { "Content-Type": "application/json" };
|
|
122
|
+
if (this.apiKey) {
|
|
123
|
+
h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
124
|
+
}
|
|
125
|
+
return h;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* GET 请求
|
|
129
|
+
*/
|
|
130
|
+
async get(path, params = {}) {
|
|
131
|
+
const url = new URL(`${this.baseUrl}/api/v1${path}`);
|
|
132
|
+
Object.entries(params).forEach(([k, v]) => {
|
|
133
|
+
if (v !== void 0 && v !== null) url.searchParams.set(k, String(v));
|
|
134
|
+
});
|
|
135
|
+
const res = await fetch(url.toString(), { headers: this.headers() });
|
|
136
|
+
return this.handleResponse(res);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* POST 请求
|
|
140
|
+
*/
|
|
141
|
+
async post(path, body = {}) {
|
|
142
|
+
const url = `${this.baseUrl}/api/v1${path}`;
|
|
143
|
+
const res = await fetch(url, {
|
|
144
|
+
method: "POST",
|
|
145
|
+
headers: this.headers(),
|
|
146
|
+
body: JSON.stringify(body)
|
|
147
|
+
});
|
|
148
|
+
return this.handleResponse(res);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* PATCH 请求
|
|
152
|
+
*/
|
|
153
|
+
async patch(path, body = {}) {
|
|
154
|
+
const url = `${this.baseUrl}/api/v1${path}`;
|
|
155
|
+
const res = await fetch(url, {
|
|
156
|
+
method: "PATCH",
|
|
157
|
+
headers: this.headers(),
|
|
158
|
+
body: JSON.stringify(body)
|
|
159
|
+
});
|
|
160
|
+
return this.handleResponse(res);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* DELETE 请求
|
|
164
|
+
*/
|
|
165
|
+
async delete(path) {
|
|
166
|
+
const url = `${this.baseUrl}/api/v1${path}`;
|
|
167
|
+
const res = await fetch(url, {
|
|
168
|
+
method: "DELETE",
|
|
169
|
+
headers: this.headers()
|
|
170
|
+
});
|
|
171
|
+
return this.handleResponse(res);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* 统一响应处理
|
|
175
|
+
*/
|
|
176
|
+
async handleResponse(res) {
|
|
177
|
+
const data = await res.json().catch(() => ({}));
|
|
178
|
+
if (!res.ok) {
|
|
179
|
+
const error = data.error || { message: `HTTP ${res.status}` };
|
|
180
|
+
const message = formatApiErrorMessage(error);
|
|
181
|
+
throw new ApiError(message, res.status, {
|
|
182
|
+
fields: error.fields && typeof error.fields === "object" ? error.fields : void 0,
|
|
183
|
+
code: error.code
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
return data;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
var ApiError = class extends Error {
|
|
190
|
+
/**
|
|
191
|
+
* @param {string} message
|
|
192
|
+
* @param {number} status
|
|
193
|
+
* @param {{ fields?: Record<string, string>, code?: string }} [meta]
|
|
194
|
+
*/
|
|
195
|
+
constructor(message, status, meta = {}) {
|
|
196
|
+
super(message);
|
|
197
|
+
this.name = "ApiError";
|
|
198
|
+
this.status = status;
|
|
199
|
+
this.fields = meta.fields;
|
|
200
|
+
this.code = meta.code;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// src/context.js
|
|
205
|
+
function resolveApi(cmd) {
|
|
206
|
+
const root = getRootCommand(cmd);
|
|
207
|
+
const o = root.opts();
|
|
208
|
+
const apiKey = getApiKey();
|
|
209
|
+
const baseUrl = getBaseUrl(o.baseUrl);
|
|
210
|
+
return { apiKey, baseUrl, client: new ApiClient(baseUrl, apiKey) };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/commands/intake.js
|
|
214
|
+
var intake = new Command().name("intake").description("\u6536\u5F55\u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u5DE5\u5177/\u6E20\u9053/\u4FE1\u53F7");
|
|
215
|
+
intake.command("new").description("\u521B\u5EFA\u65B0\u6536\u5F55").option("-u, --url <url>", "\u76EE\u6807 URL\uFF08tool/channel \u65F6\u53EF\u9009\uFF0C\u7528\u4E8E\u81EA\u52A8\u89E3\u6790\u8D44\u6599\uFF09").option("-k, --kind <type>", "\u7C7B\u578B\uFF1Asignal/tool/channel\uFF08\u9ED8\u8BA4 signal\uFF09", "signal").option("-t, --title <title>", "\u6807\u9898\uFF08tool/channel \u5FC5\u586B\uFF09").option("-b, --body <text>", "\u6B63\u6587/\u63CF\u8FF0").option("--profile-data-json <json>", "\u8D44\u6599\u6BB5 JSON\uFF08tool/channel\uFF09").action(async (opts, cmd) => {
|
|
216
|
+
const { apiKey, baseUrl, client } = resolveApi(cmd);
|
|
217
|
+
if (!apiKey) {
|
|
218
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
219
|
+
console.error("\u4F7F\u7528 c456 config set-key <token> \u914D\u7F6E\uFF0C\u6216\u8BBE\u7F6E C456_API_KEY \u73AF\u5883\u53D8\u91CF");
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
const body = {
|
|
224
|
+
kind: opts.kind,
|
|
225
|
+
title: opts.title || "",
|
|
226
|
+
body: opts.body || ""
|
|
227
|
+
};
|
|
228
|
+
if (opts.url) {
|
|
229
|
+
body.url = opts.url;
|
|
230
|
+
}
|
|
231
|
+
if (opts.profileDataJson) {
|
|
232
|
+
body.profile_data_json = opts.profileDataJson;
|
|
233
|
+
}
|
|
234
|
+
const result = await client.post("/intakes", body);
|
|
235
|
+
console.log("\u2705 \u6536\u5F55\u521B\u5EFA\u6210\u529F");
|
|
236
|
+
console.log(` ID: ${result.data.id}`);
|
|
237
|
+
console.log(` \u7C7B\u578B\uFF1A${result.data.kind}`);
|
|
238
|
+
console.log(` \u6807\u9898\uFF1A${result.data.title || "(\u65E0)"}`);
|
|
239
|
+
} catch (err) {
|
|
240
|
+
console.error(`\u274C \u521B\u5EFA\u5931\u8D25\uFF1A${err.message}`);
|
|
241
|
+
const kind = String(opts.kind ?? "signal");
|
|
242
|
+
const urlHint = Boolean(opts.url) && kind === "signal" && err instanceof ApiError && err.status === 422;
|
|
243
|
+
if (urlHint) {
|
|
244
|
+
console.error("");
|
|
245
|
+
console.error("\u63D0\u793A\uFF1A\u5F53\u524D\u4E3A signal\uFF08\u9ED8\u8BA4\uFF09\u3002`-u` \u4EC5\u5728 `-k tool` \u6216 `-k channel` \u65F6\u4F1A\u7528\u4E8E\u81EA\u52A8\u89E3\u6790\u8D44\u6599\u3002");
|
|
246
|
+
console.error(" \u793A\u4F8B\uFF1A");
|
|
247
|
+
console.error(' c456 -B <\u7AD9\u70B9> intake new -k channel -u "<\u9891\u9053\u6216\u4E3B\u9875 URL>"');
|
|
248
|
+
console.error(' c456 -B <\u7AD9\u70B9> intake new -k tool -u "<\u5DE5\u5177 / \u4ED3\u5E93 URL>"');
|
|
249
|
+
}
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
intake.command("show").description("\u67E5\u770B\u6536\u5F55\u8BE6\u60C5").argument("<id>", "\u6536\u5F55 ID").action(async (id, opts, cmd) => {
|
|
254
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
255
|
+
if (!apiKey) {
|
|
256
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
try {
|
|
260
|
+
const result = await client.get(`/intakes/${id}`);
|
|
261
|
+
const data = result.data;
|
|
262
|
+
console.log(`ID: ${data.id}`);
|
|
263
|
+
console.log(`\u7C7B\u578B\uFF1A${data.kind}`);
|
|
264
|
+
console.log(`\u6807\u9898\uFF1A${data.title || "(\u65E0)"}`);
|
|
265
|
+
console.log(`\u6B63\u6587\uFF1A${data.body || "(\u65E0)"}`);
|
|
266
|
+
if (data.profileData) {
|
|
267
|
+
console.log(`\u8D44\u6599\u6BB5\uFF1A${JSON.stringify(data.profileData, null, 2)}`);
|
|
268
|
+
}
|
|
269
|
+
} catch (err) {
|
|
270
|
+
console.error(`\u274C \u67E5\u8BE2\u5931\u8D25\uFF1A${err.message}`);
|
|
271
|
+
process.exit(1);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
intake.command("update").description("\u66F4\u65B0\u6536\u5F55").argument("<id>", "\u6536\u5F55 ID").option("-t, --title <title>", "\u65B0\u6807\u9898").option("-b, --body <text>", "\u65B0\u6B63\u6587").option("--favorited", "\u6807\u8BB0\u4E3A\u6536\u85CF").option("--unfavorited", "\u53D6\u6D88\u6536\u85CF").action(async (id, opts, cmd) => {
|
|
275
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
276
|
+
if (!apiKey) {
|
|
277
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
const body = {};
|
|
281
|
+
if (opts.title) body.title = opts.title;
|
|
282
|
+
if (opts.body) body.body = opts.body;
|
|
283
|
+
if (opts.favorited) body.favorited = true;
|
|
284
|
+
if (opts.unfavorited) body.favorited = false;
|
|
285
|
+
try {
|
|
286
|
+
await client.patch(`/intakes/${id}`, body);
|
|
287
|
+
console.log("\u2705 \u6536\u5F55\u66F4\u65B0\u6210\u529F");
|
|
288
|
+
} catch (err) {
|
|
289
|
+
console.error(`\u274C \u66F4\u65B0\u5931\u8D25\uFF1A${err.message}`);
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
intake.command("delete").description("\u5220\u9664\u6536\u5F55").argument("<id>", "\u6536\u5F55 ID").option("-f, --force", "\u5F3A\u5236\u5220\u9664\uFF08\u65E0\u9700\u786E\u8BA4\uFF09").action(async (id, opts, cmd) => {
|
|
294
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
295
|
+
if (!apiKey) {
|
|
296
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
if (!opts.force) {
|
|
300
|
+
const readline = await import("node:readline");
|
|
301
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
302
|
+
const answer = await new Promise((resolve) => {
|
|
303
|
+
rl.question("\u786E\u8BA4\u5220\u9664\uFF1F(y/N): ", (ans) => {
|
|
304
|
+
rl.close();
|
|
305
|
+
resolve(ans.toLowerCase());
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
if (answer !== "y" && answer !== "yes") {
|
|
309
|
+
console.log("\u5DF2\u53D6\u6D88");
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
try {
|
|
314
|
+
await client.delete(`/intakes/${id}`);
|
|
315
|
+
console.log("\u2705 \u6536\u5F55\u5DF2\u5220\u9664");
|
|
316
|
+
} catch (err) {
|
|
317
|
+
console.error(`\u274C \u5220\u9664\u5931\u8D25\uFF1A${err.message}`);
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
intake.command("list").description("\u5217\u51FA\u6536\u5F55\uFF08\u5206\u9875\uFF09").option("-k, --kind <type>", "\u7C7B\u578B\u8FC7\u6EE4\uFF1Asignal/tool/channel").option("-q, --query <text>", "\u641C\u7D22\u5173\u952E\u8BCD").option("-p, --page <num>", "\u9875\u7801", "1").option("-n, --per-page <num>", "\u6BCF\u9875\u6570\u91CF", "20").action(async (opts, cmd) => {
|
|
322
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
323
|
+
if (!apiKey) {
|
|
324
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
325
|
+
process.exit(1);
|
|
326
|
+
}
|
|
327
|
+
try {
|
|
328
|
+
const result = await client.get("/intakes", {
|
|
329
|
+
kind: opts.kind,
|
|
330
|
+
q: opts.query,
|
|
331
|
+
page: opts.page,
|
|
332
|
+
per_page: opts.perPage
|
|
333
|
+
});
|
|
334
|
+
const { data, meta } = result;
|
|
335
|
+
const perPage = metaPerPage(meta);
|
|
336
|
+
const totalPages = Math.max(1, Math.ceil(meta.total / perPage));
|
|
337
|
+
console.log(`\u5171 ${meta.total} \u6761\u6536\u5F55\uFF08\u7B2C ${meta.page}/${totalPages} \u9875\uFF09
|
|
338
|
+
`);
|
|
339
|
+
data.forEach((item) => {
|
|
340
|
+
const kindBadge = { signal: "\u{1F4E1}", tool: "\u{1F527}", channel: "\u{1F4E2}" }[item.kind] || "\u2022";
|
|
341
|
+
console.log(`${kindBadge} [${item.id}] ${item.kind}`);
|
|
342
|
+
console.log(` ${item.title || item.listSummary || "(\u65E0\u6807\u9898)"}`);
|
|
343
|
+
});
|
|
344
|
+
} catch (err) {
|
|
345
|
+
console.error(`\u274C \u67E5\u8BE2\u5931\u8D25\uFF1A${err.message}`);
|
|
346
|
+
process.exit(1);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
var intake_default = intake;
|
|
350
|
+
|
|
351
|
+
// src/commands/fetch.js
|
|
352
|
+
import { Command as Command2 } from "commander";
|
|
353
|
+
var fetchProfile = new Command2().name("fetch").description("\u8D44\u6599\u6293\u53D6 - \u4ECE URL \u81EA\u52A8\u89E3\u6790\u5E73\u53F0\u8D44\u6599");
|
|
354
|
+
fetchProfile.command("profile").description("\u6293\u53D6\u6307\u5B9A URL \u7684\u8D44\u6599\u6BB5\u6570\u636E").requiredOption("-u, --url <url>", "\u76EE\u6807 URL").option("-p, --profile-id <type>", "\u8D44\u6599\u7C7B\u578B\uFF1Alink_product/package_registry/github_origin/social_account").action(async (opts, cmd) => {
|
|
355
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
356
|
+
if (!apiKey) {
|
|
357
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
358
|
+
process.exit(1);
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
const body = { url: opts.url };
|
|
362
|
+
if (opts.profileId) {
|
|
363
|
+
body.profile_id = opts.profileId;
|
|
364
|
+
}
|
|
365
|
+
const result = await client.post("/fetches", body);
|
|
366
|
+
const { data, suggested_title } = result.data;
|
|
367
|
+
console.log("\u2705 \u8D44\u6599\u6293\u53D6\u6210\u529F");
|
|
368
|
+
if (suggested_title) {
|
|
369
|
+
console.log(`\u5EFA\u8BAE\u6807\u9898\uFF1A${suggested_title}`);
|
|
370
|
+
}
|
|
371
|
+
console.log("\n\u8D44\u6599\u6570\u636E\uFF1A");
|
|
372
|
+
console.log(JSON.stringify(data, null, 2));
|
|
373
|
+
} catch (err) {
|
|
374
|
+
console.error(`\u274C \u6293\u53D6\u5931\u8D25\uFF1A${err.message}`);
|
|
375
|
+
process.exit(1);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
fetchProfile.command("detect").description("\u81EA\u52A8\u68C0\u6D4B URL \u7C7B\u578B\u5E76\u6293\u53D6\u8D44\u6599\u5E76\u521B\u5EFA tool \u6536\u5F55").requiredOption("-u, --url <url>", "\u76EE\u6807 URL").action(async (opts, cmd) => {
|
|
379
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
380
|
+
if (!apiKey) {
|
|
381
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
382
|
+
process.exit(1);
|
|
383
|
+
}
|
|
384
|
+
try {
|
|
385
|
+
const result = await client.post("/intakes", {
|
|
386
|
+
kind: "tool",
|
|
387
|
+
url: opts.url
|
|
388
|
+
});
|
|
389
|
+
console.log("\u2705 \u81EA\u52A8\u68C0\u6D4B\u5E76\u6536\u5F55\u6210\u529F");
|
|
390
|
+
console.log(`ID: ${result.data.id}`);
|
|
391
|
+
console.log(`\u7C7B\u578B\uFF1A${result.data.kind}`);
|
|
392
|
+
if (result.data.profileData) {
|
|
393
|
+
console.log("\n\u89E3\u6790\u7684\u8D44\u6599\u6BB5\uFF1A");
|
|
394
|
+
console.log(JSON.stringify(result.data.profileData, null, 2));
|
|
395
|
+
}
|
|
396
|
+
} catch (err) {
|
|
397
|
+
console.error(`\u274C \u68C0\u6D4B\u5931\u8D25\uFF1A${err.message}`);
|
|
398
|
+
process.exit(1);
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
var fetch_default = fetchProfile;
|
|
402
|
+
|
|
403
|
+
// src/commands/search.js
|
|
404
|
+
import { Command as Command3 } from "commander";
|
|
405
|
+
var searchCmd = new Command3().name("search").description("\u641C\u7D22 - \u67E5\u627E\u53EF\u5173\u8054\u7684\u6536\u5F55\u6216\u6253\u6CD5");
|
|
406
|
+
searchCmd.command("signals").description("\u641C\u7D22\u6536\u5F55\uFF08\u7528\u4E8E\u4FE1\u53F7\u5173\u8054\uFF09").option("-q, --query <text>", "\u641C\u7D22\u5173\u952E\u8BCD", "").option("-k, --kind <type>", "\u7C7B\u578B\u8FC7\u6EE4\uFF1Asignal/tool/channel").option("-l, --limit <num>", "\u7ED3\u679C\u6570\u91CF\u9650\u5236", "20").action(async (opts, cmd) => {
|
|
407
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
408
|
+
if (!apiKey) {
|
|
409
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
410
|
+
process.exit(1);
|
|
411
|
+
}
|
|
412
|
+
try {
|
|
413
|
+
const result = await client.get("/search/intakes", {
|
|
414
|
+
q: opts.query,
|
|
415
|
+
kind: opts.kind,
|
|
416
|
+
limit: opts.limit
|
|
417
|
+
});
|
|
418
|
+
const data = result.data;
|
|
419
|
+
if (data.length === 0) {
|
|
420
|
+
console.log("\u672A\u627E\u5230\u5339\u914D\u7684\u6536\u5F55");
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
console.log(`\u627E\u5230 ${data.length} \u6761\u7ED3\u679C\uFF1A
|
|
424
|
+
`);
|
|
425
|
+
data.forEach((item) => {
|
|
426
|
+
const kindBadge = { signal: "\u{1F4E1}", tool: "\u{1F527}", channel: "\u{1F4E2}" }[item.kind] || "\u2022";
|
|
427
|
+
const sourceKey = item.source_key ? ` [${item.source_key}]` : "";
|
|
428
|
+
console.log(`${kindBadge} #${item.id}${sourceKey} ${item.title || "(\u65E0\u6807\u9898)"}`);
|
|
429
|
+
if (item.list_summary) {
|
|
430
|
+
console.log(` ${item.list_summary}`);
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
console.log("\n--- JSON ---");
|
|
434
|
+
console.log(JSON.stringify(data, null, 2));
|
|
435
|
+
} catch (err) {
|
|
436
|
+
console.error(`\u274C \u641C\u7D22\u5931\u8D25\uFF1A${err.message}`);
|
|
437
|
+
process.exit(1);
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
searchCmd.command("playbooks").description("\u641C\u7D22\u6253\u6CD5\uFF08\u7528\u4E8E\u4FE1\u53F7\u5173\u8054\uFF09").option("-q, --query <text>", "\u641C\u7D22\u5173\u952E\u8BCD", "").option("-l, --limit <num>", "\u7ED3\u679C\u6570\u91CF\u9650\u5236", "20").action(async (opts, cmd) => {
|
|
441
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
442
|
+
if (!apiKey) {
|
|
443
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
444
|
+
process.exit(1);
|
|
445
|
+
}
|
|
446
|
+
try {
|
|
447
|
+
const result = await client.get("/search/playbooks", {
|
|
448
|
+
q: opts.query,
|
|
449
|
+
limit: opts.limit
|
|
450
|
+
});
|
|
451
|
+
const data = result.data;
|
|
452
|
+
if (data.length === 0) {
|
|
453
|
+
console.log("\u672A\u627E\u5230\u5339\u914D\u7684\u6253\u6CD5");
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
console.log(`\u627E\u5230 ${data.length} \u6761\u7ED3\u679C\uFF1A
|
|
457
|
+
`);
|
|
458
|
+
data.forEach((item) => {
|
|
459
|
+
console.log(`\u{1F4D8} #${item.id} ${item.title || "(\u65E0\u6807\u9898)"}`);
|
|
460
|
+
if (item.list_summary) {
|
|
461
|
+
console.log(` ${item.list_summary}`);
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
console.log("\n--- JSON ---");
|
|
465
|
+
console.log(JSON.stringify(data, null, 2));
|
|
466
|
+
} catch (err) {
|
|
467
|
+
console.error(`\u274C \u641C\u7D22\u5931\u8D25\uFF1A${err.message}`);
|
|
468
|
+
process.exit(1);
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
var search_default = searchCmd;
|
|
472
|
+
|
|
473
|
+
// src/commands/playbook.js
|
|
474
|
+
import { Command as Command4 } from "commander";
|
|
475
|
+
var playbookCmd = new Command4().name("playbook").description("\u6253\u6CD5\u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u6253\u6CD5");
|
|
476
|
+
playbookCmd.command("new").description("\u521B\u5EFA\u65B0\u6253\u6CD5").requiredOption("-t, --title <title>", "\u6253\u6CD5\u6807\u9898").option("-b, --body <text>", "\u6253\u6CD5\u6B63\u6587\uFF08Markdown\uFF09").option("--ref-intake <id>", "\u5F15\u7528\u6536\u5F55 ID\uFF08\u53EF\u591A\u6B21\u6307\u5B9A\uFF09").option("--ref-playbook <id>", "\u5F15\u7528\u6253\u6CD5 ID\uFF08\u53EF\u591A\u6B21\u6307\u5B9A\uFF09").action(async (opts, cmd) => {
|
|
477
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
478
|
+
if (!apiKey) {
|
|
479
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
480
|
+
process.exit(1);
|
|
481
|
+
}
|
|
482
|
+
const referenceTargets = [];
|
|
483
|
+
if (opts.refIntake) {
|
|
484
|
+
const intakeIds = Array.isArray(opts.refIntake) ? opts.refIntake : [opts.refIntake];
|
|
485
|
+
intakeIds.forEach((id) => {
|
|
486
|
+
referenceTargets.push({ type: "intake", id: parseInt(id, 10) });
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
if (opts.refPlaybook) {
|
|
490
|
+
const playbookIds = Array.isArray(opts.refPlaybook) ? opts.refPlaybook : [opts.refPlaybook];
|
|
491
|
+
playbookIds.forEach((id) => {
|
|
492
|
+
referenceTargets.push({ type: "playbook", id: parseInt(id, 10) });
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
try {
|
|
496
|
+
const body = {
|
|
497
|
+
title: opts.title,
|
|
498
|
+
body: opts.body || ""
|
|
499
|
+
};
|
|
500
|
+
if (referenceTargets.length > 0) {
|
|
501
|
+
body.reference_targets = referenceTargets;
|
|
502
|
+
}
|
|
503
|
+
const result = await client.post("/playbooks", body);
|
|
504
|
+
console.log("\u2705 \u6253\u6CD5\u521B\u5EFA\u6210\u529F");
|
|
505
|
+
console.log(` ID: ${result.data.id}`);
|
|
506
|
+
console.log(` \u6807\u9898\uFF1A${result.data.title}`);
|
|
507
|
+
} catch (err) {
|
|
508
|
+
console.error(`\u274C \u521B\u5EFA\u5931\u8D25\uFF1A${err.message}`);
|
|
509
|
+
process.exit(1);
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
playbookCmd.command("show").description("\u67E5\u770B\u6253\u6CD5\u8BE6\u60C5").argument("<id>", "\u6253\u6CD5 ID").action(async (id, opts, cmd) => {
|
|
513
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
514
|
+
if (!apiKey) {
|
|
515
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
516
|
+
process.exit(1);
|
|
517
|
+
}
|
|
518
|
+
try {
|
|
519
|
+
const result = await client.get(`/playbooks/${id}`);
|
|
520
|
+
const data = result.data;
|
|
521
|
+
console.log(`ID: ${data.id}`);
|
|
522
|
+
console.log(`\u6807\u9898\uFF1A${data.title}`);
|
|
523
|
+
console.log(`\u6B63\u6587\uFF1A
|
|
524
|
+
${data.body || "(\u65E0)"}`);
|
|
525
|
+
if (data.referenceTargets && data.referenceTargets.length > 0) {
|
|
526
|
+
console.log("\n\u5F15\u7528\u76EE\u6807\uFF1A");
|
|
527
|
+
data.referenceTargets.forEach((ref) => {
|
|
528
|
+
console.log(` - ${ref.targetType} #${ref.targetId}: ${ref.title}`);
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
if (data.workflow && (data.workflow.nodes?.length || 0) > 0) {
|
|
532
|
+
console.log("\n\u5DE5\u4F5C\u6D41\uFF1A");
|
|
533
|
+
data.workflow.nodes.forEach((node, i) => {
|
|
534
|
+
console.log(` ${i + 1}. ${node.title || "(\u65E0\u6807\u9898)"}`);
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
} catch (err) {
|
|
538
|
+
console.error(`\u274C \u67E5\u8BE2\u5931\u8D25\uFF1A${err.message}`);
|
|
539
|
+
process.exit(1);
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
playbookCmd.command("update").description("\u66F4\u65B0\u6253\u6CD5").argument("<id>", "\u6253\u6CD5 ID").option("-t, --title <title>", "\u65B0\u6807\u9898").option("-b, --body <text>", "\u65B0\u6B63\u6587").action(async (id, opts, cmd) => {
|
|
543
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
544
|
+
if (!apiKey) {
|
|
545
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
546
|
+
process.exit(1);
|
|
547
|
+
}
|
|
548
|
+
const body = {};
|
|
549
|
+
if (opts.title) body.title = opts.title;
|
|
550
|
+
if (opts.body) body.body = opts.body;
|
|
551
|
+
try {
|
|
552
|
+
await client.patch(`/playbooks/${id}`, body);
|
|
553
|
+
console.log("\u2705 \u6253\u6CD5\u66F4\u65B0\u6210\u529F");
|
|
554
|
+
} catch (err) {
|
|
555
|
+
console.error(`\u274C \u66F4\u65B0\u5931\u8D25\uFF1A${err.message}`);
|
|
556
|
+
process.exit(1);
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
playbookCmd.command("delete").description("\u5220\u9664\u6253\u6CD5").argument("<id>", "\u6253\u6CD5 ID").option("-f, --force", "\u5F3A\u5236\u5220\u9664\uFF08\u65E0\u9700\u786E\u8BA4\uFF09").action(async (id, opts, cmd) => {
|
|
560
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
561
|
+
if (!apiKey) {
|
|
562
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
563
|
+
process.exit(1);
|
|
564
|
+
}
|
|
565
|
+
if (!opts.force) {
|
|
566
|
+
const readline = await import("node:readline");
|
|
567
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
568
|
+
const answer = await new Promise((resolve) => {
|
|
569
|
+
rl.question("\u786E\u8BA4\u5220\u9664\uFF1F(y/N): ", (ans) => {
|
|
570
|
+
rl.close();
|
|
571
|
+
resolve(ans.toLowerCase());
|
|
572
|
+
});
|
|
573
|
+
});
|
|
574
|
+
if (answer !== "y" && answer !== "yes") {
|
|
575
|
+
console.log("\u5DF2\u53D6\u6D88");
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
try {
|
|
580
|
+
await client.delete(`/playbooks/${id}`);
|
|
581
|
+
console.log("\u2705 \u6253\u6CD5\u5DF2\u5220\u9664");
|
|
582
|
+
} catch (err) {
|
|
583
|
+
console.error(`\u274C \u5220\u9664\u5931\u8D25\uFF1A${err.message}`);
|
|
584
|
+
process.exit(1);
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
playbookCmd.command("list").description("\u5217\u51FA\u6253\u6CD5\uFF08\u5206\u9875\uFF09").option("-q, --query <text>", "\u641C\u7D22\u5173\u952E\u8BCD").option("-p, --page <num>", "\u9875\u7801", "1").option("-n, --per-page <num>", "\u6BCF\u9875\u6570\u91CF", "20").action(async (opts, cmd) => {
|
|
588
|
+
const { apiKey, client } = resolveApi(cmd);
|
|
589
|
+
if (!apiKey) {
|
|
590
|
+
console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
|
|
591
|
+
process.exit(1);
|
|
592
|
+
}
|
|
593
|
+
try {
|
|
594
|
+
const result = await client.get("/playbooks", {
|
|
595
|
+
q: opts.query,
|
|
596
|
+
page: opts.page,
|
|
597
|
+
per_page: opts.perPage
|
|
598
|
+
});
|
|
599
|
+
const { data, meta } = result;
|
|
600
|
+
const perPage = metaPerPage(meta);
|
|
601
|
+
const totalPages = Math.max(1, Math.ceil(meta.total / perPage));
|
|
602
|
+
console.log(`\u5171 ${meta.total} \u6761\u6253\u6CD5\uFF08\u7B2C ${meta.page}/${totalPages} \u9875\uFF09
|
|
603
|
+
`);
|
|
604
|
+
data.forEach((item) => {
|
|
605
|
+
console.log(`\u{1F4D8} [${item.id}] ${item.title}`);
|
|
606
|
+
if (item.listSummary) {
|
|
607
|
+
console.log(` ${item.listSummary}`);
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
} catch (err) {
|
|
611
|
+
console.error(`\u274C \u67E5\u8BE2\u5931\u8D25\uFF1A${err.message}`);
|
|
612
|
+
process.exit(1);
|
|
613
|
+
}
|
|
614
|
+
});
|
|
615
|
+
var playbook_default = playbookCmd;
|
|
616
|
+
|
|
617
|
+
// src/commands/config.js
|
|
618
|
+
import { Command as Command5 } from "commander";
|
|
619
|
+
var configCmd = new Command5().name("config").description("\u914D\u7F6E\u7BA1\u7406 - \u8BBE\u7F6E API Key \u548C\u7CFB\u7EDF\u5730\u5740");
|
|
620
|
+
configCmd.command("set-key").description("\u8BBE\u7F6E API Key").argument("<token>", "API Key \u4EE4\u724C").action((token, cmd) => {
|
|
621
|
+
const config = loadConfig();
|
|
622
|
+
config.apiKey = token;
|
|
623
|
+
saveConfig(config);
|
|
624
|
+
console.log("\u2705 API Key \u5DF2\u4FDD\u5B58\u81F3 ~/.config/c456/config.json");
|
|
625
|
+
console.log(` \u63D0\u793A\uFF1A\u4E5F\u53EF\u901A\u8FC7 C456_API_KEY \u73AF\u5883\u53D8\u91CF\u8BBE\u7F6E`);
|
|
626
|
+
});
|
|
627
|
+
configCmd.command("set-url").description("\u8BBE\u7F6E C456 \u7CFB\u7EDF\u5730\u5740").argument("<url>", "\u7CFB\u7EDF\u5730\u5740\uFF08\u5982 https://c456.com\uFF09").action((url, cmd) => {
|
|
628
|
+
const config = loadConfig();
|
|
629
|
+
config.baseUrl = url;
|
|
630
|
+
saveConfig(config);
|
|
631
|
+
console.log(`\u2705 \u7CFB\u7EDF\u5730\u5740\u5DF2\u8BBE\u7F6E\u4E3A\uFF1A${url}`);
|
|
632
|
+
console.log(` \u63D0\u793A\uFF1A\u4E5F\u53EF\u901A\u8FC7 C456_URL \u73AF\u5883\u53D8\u91CF\u8BBE\u7F6E`);
|
|
633
|
+
});
|
|
634
|
+
configCmd.command("show").description("\u663E\u793A\u5F53\u524D\u914D\u7F6E").action(() => {
|
|
635
|
+
const config = loadConfig();
|
|
636
|
+
console.log("\u5F53\u524D\u914D\u7F6E\uFF1A");
|
|
637
|
+
console.log(` \u7CFB\u7EDF\u5730\u5740\uFF1A${config.baseUrl || "https://c456.com"}`);
|
|
638
|
+
console.log(` API Key\uFF1A${config.apiKey ? config.apiKey.slice(0, 8) + "..." : "(\u672A\u8BBE\u7F6E)"}`);
|
|
639
|
+
console.log(`
|
|
640
|
+
\u914D\u7F6E\u6587\u4EF6\uFF1A~/.config/c456/config.json`);
|
|
641
|
+
});
|
|
642
|
+
configCmd.command("reset").description("\u91CD\u7F6E\u914D\u7F6E\uFF08\u5220\u9664\u914D\u7F6E\u6587\u4EF6\uFF09").option("-f, --force", "\u5F3A\u5236\u91CD\u7F6E\uFF08\u65E0\u9700\u786E\u8BA4\uFF09").action(async (opts) => {
|
|
643
|
+
const fs = await import("node:fs");
|
|
644
|
+
if (!opts.force) {
|
|
645
|
+
const readline = await import("node:readline");
|
|
646
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
647
|
+
const answer = await new Promise((resolve) => {
|
|
648
|
+
rl.question("\u786E\u8BA4\u5220\u9664\u914D\u7F6E\u6587\u4EF6\uFF1F(y/N): ", (ans) => {
|
|
649
|
+
rl.close();
|
|
650
|
+
resolve(ans.toLowerCase());
|
|
651
|
+
});
|
|
652
|
+
});
|
|
653
|
+
if (answer !== "y" && answer !== "yes") {
|
|
654
|
+
console.log("\u5DF2\u53D6\u6D88");
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
659
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
660
|
+
console.log("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u5220\u9664");
|
|
661
|
+
} else {
|
|
662
|
+
console.log("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u65E0\u9700\u5220\u9664");
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
var config_default = configCmd;
|
|
666
|
+
|
|
667
|
+
// src/banner.js
|
|
668
|
+
import cfonts from "cfonts";
|
|
669
|
+
var { render } = cfonts;
|
|
670
|
+
var CFONTS_OPTIONS = {
|
|
671
|
+
font: "block",
|
|
672
|
+
colors: ["red", "white"],
|
|
673
|
+
env: "node",
|
|
674
|
+
spaceless: true
|
|
675
|
+
};
|
|
676
|
+
var ANSI_RE = /\u001b\[[\d;]*m/g;
|
|
677
|
+
function stripAnsi(s) {
|
|
678
|
+
return s.replace(ANSI_RE, "");
|
|
679
|
+
}
|
|
680
|
+
function renderBannerColored() {
|
|
681
|
+
const out = render("C456", CFONTS_OPTIONS, false, 0);
|
|
682
|
+
if (!out || !out.string) {
|
|
683
|
+
return "";
|
|
684
|
+
}
|
|
685
|
+
return out.string;
|
|
686
|
+
}
|
|
687
|
+
var _cachedColored;
|
|
688
|
+
var _cachedPlain;
|
|
689
|
+
function getBannerColored() {
|
|
690
|
+
if (_cachedColored === void 0) {
|
|
691
|
+
_cachedColored = renderBannerColored();
|
|
692
|
+
}
|
|
693
|
+
return _cachedColored;
|
|
694
|
+
}
|
|
695
|
+
function getBannerPlainText() {
|
|
696
|
+
if (_cachedPlain === void 0) {
|
|
697
|
+
_cachedPlain = stripAnsi(getBannerColored());
|
|
698
|
+
}
|
|
699
|
+
return _cachedPlain;
|
|
700
|
+
}
|
|
701
|
+
function getHelpBanner() {
|
|
702
|
+
if (process.env.C456_NO_BANNER === "1") {
|
|
703
|
+
return "";
|
|
704
|
+
}
|
|
705
|
+
const body = process.stdout.isTTY ? getBannerColored() : getBannerPlainText();
|
|
706
|
+
if (!body) {
|
|
707
|
+
return "";
|
|
708
|
+
}
|
|
709
|
+
return `
|
|
710
|
+
${body}
|
|
711
|
+
`;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// src/index.js
|
|
715
|
+
var program = new Command6();
|
|
716
|
+
program.name("c456").description("C456 CLI - \u5FEB\u901F\u5185\u5BB9\u5F55\u5165\u4E0E\u6574\u7406\u5DE5\u5177").version(package_default.version);
|
|
717
|
+
program.addHelpText("before", () => getHelpBanner());
|
|
718
|
+
program.option(
|
|
719
|
+
"-B, --base-url <url>",
|
|
720
|
+
"C456 \u7AD9\u70B9\u6839\u5730\u5740\uFF1B\u672A\u4F20\u5219\u4F7F\u7528 C456_URL \u73AF\u5883\u53D8\u91CF\u6216 ~/.config/c456/config.json \u7684 baseUrl\uFF0C\u9ED8\u8BA4 https://c456.com"
|
|
721
|
+
);
|
|
722
|
+
program.addCommand(intake_default);
|
|
723
|
+
program.addCommand(fetch_default);
|
|
724
|
+
program.addCommand(search_default);
|
|
725
|
+
program.addCommand(playbook_default);
|
|
726
|
+
program.addCommand(config_default);
|
|
727
|
+
program.on("--help", () => {
|
|
728
|
+
console.log("\n\u793A\u4F8B:");
|
|
729
|
+
console.log(" # \u914D\u7F6E API Key");
|
|
730
|
+
console.log(" c456 config set-key your-api-token");
|
|
731
|
+
console.log("");
|
|
732
|
+
console.log(" # \u81EA\u6258\u7BA1\u7AD9\u70B9 + \u6309 URL \u6536\u5F55\u5DE5\u5177\uFF08-B=\u7AD9\u70B9\uFF0C-u=\u76EE\u6807 URL\uFF09");
|
|
733
|
+
console.log(' c456 -B https://c456.example.com intake new -k tool -u "https://github.com/owner/repo"');
|
|
734
|
+
console.log("");
|
|
735
|
+
console.log(" # \u641C\u7D22\u6536\u5F55");
|
|
736
|
+
console.log(' c456 search signals -q "AI agent"');
|
|
737
|
+
console.log("");
|
|
738
|
+
console.log("\u73AF\u5883\u53D8\u91CF:");
|
|
739
|
+
console.log(" C456_URL - \u7AD9\u70B9\u6839\u5730\u5740\uFF08\u4E0E -B / --base-url \u4E00\u81F4\uFF09");
|
|
740
|
+
console.log(" C456_API_KEY - API Key");
|
|
741
|
+
});
|
|
742
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "c456-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "C456 CLI - 内容录入与整理工具",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"c456": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "node scripts/build.js",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"cfonts": "^3.3.1",
|
|
19
|
+
"commander": "^12.1.0",
|
|
20
|
+
"open": "^10.1.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"esbuild": "^0.24.0"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"c456",
|
|
27
|
+
"cli",
|
|
28
|
+
"content",
|
|
29
|
+
"intake"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=20.0.0"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/xiaohui-zhangxh/c456#c456-cli",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/xiaohui-zhangxh/c456.git",
|
|
39
|
+
"directory": "c456-cli"
|
|
40
|
+
}
|
|
41
|
+
}
|