ability-cli 0.2.1 → 0.3.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 +48 -58
- package/dist/index.js +165 -123
- package/package.json +53 -53
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## 1. 项目简介
|
|
4
4
|
|
|
5
|
-
**ability-cli**
|
|
5
|
+
**ability-cli** 是面向原子能力平台的命令行工具,用于在终端中搜索能力、查看详情、执行调用,以及直接访问 **Agent API**(路径前缀 `/ability-service/api/agent/v1`)。
|
|
6
6
|
|
|
7
7
|
采用**双层设计**:
|
|
8
8
|
|
|
@@ -48,20 +48,20 @@ pnpm link --global
|
|
|
48
48
|
## 3. 快速上手
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
#
|
|
52
|
-
ability-cli config set --
|
|
51
|
+
# 配置授权密钥(sk)与默认设备 ID(也可改用环境变量,见下文)
|
|
52
|
+
ability-cli config set --auth-token sk-xxxx --device-id <device-id>
|
|
53
53
|
|
|
54
|
-
#
|
|
55
|
-
ability-cli search
|
|
54
|
+
# 搜索能力(请求头:Authorization + zy-device-id,不发网关 zy-sign)
|
|
55
|
+
ability-cli search --natural-lang "发送一条微信消息"
|
|
56
56
|
|
|
57
|
-
#
|
|
58
|
-
ability-cli inspect --ability-id 20001
|
|
57
|
+
# 查看能力详情(端侧能力建议带设备 ID)
|
|
58
|
+
ability-cli inspect --ability-id 20001
|
|
59
59
|
|
|
60
60
|
# 生成参数模板
|
|
61
61
|
ability-cli inspect --ability-id 20001 --gen-template > params.json
|
|
62
62
|
|
|
63
|
-
#
|
|
64
|
-
ability-cli exec --ability-id 20001 --params
|
|
63
|
+
# 执行能力(对应 POST /ability-service/api/agent/v1/ability/call)
|
|
64
|
+
ability-cli exec --ability-id 20001 --params '{"contact":"张三","message":"你好"}'
|
|
65
65
|
|
|
66
66
|
# 健康检查
|
|
67
67
|
ability-cli doctor
|
|
@@ -73,16 +73,16 @@ ability-cli doctor
|
|
|
73
73
|
|
|
74
74
|
### 全局选项
|
|
75
75
|
|
|
76
|
-
下列选项可写在任意子命令**之前**,作用于本次整条命令(例如 `ability-cli --
|
|
76
|
+
下列选项可写在任意子命令**之前**,作用于本次整条命令(例如 `ability-cli --auth-token sk-xxx search --natural-lang "查询"`)。
|
|
77
|
+
|
|
78
|
+
同一字段的优先级为:**子命令参数 > 全局参数 > 环境变量 > 配置文件**(合并后的命令行优先于 `ABILITY_CLI_*` 与 `~/.ability-cli/config.json`)。
|
|
77
79
|
|
|
78
80
|
| 选项 | 说明 |
|
|
79
81
|
|------|------|
|
|
80
|
-
| `--env <env>` | 环境:`test` / `prod
|
|
81
|
-
| `--
|
|
82
|
-
| `--
|
|
83
|
-
| `--
|
|
84
|
-
| `--base-url <url>` | 网关根地址 |
|
|
85
|
-
| `--magic-sign` | 测试环境跳过验签(`zy-sign` 固定为测试用魔数) |
|
|
82
|
+
| `--env <env>` | 环境:`test` / `prod`,选用配置文件中哪一套 `profiles`(主要影响 `baseUrl`) |
|
|
83
|
+
| `--auth-token <token>` | 授权密钥 `sk-…`,写入请求头 `Authorization` |
|
|
84
|
+
| `--base-url <url>` | 网关根地址(真实路径为 `{baseUrl}/ability-service/api/agent/v1/...`) |
|
|
85
|
+
| `--device-id <id>` | 设备 ID,写入请求头 `zy-device-id`,并参与部分接口 query |
|
|
86
86
|
| `-v, --verbose` | 详细输出(请求 URL、头、体与响应等) |
|
|
87
87
|
|
|
88
88
|
### 上层命令
|
|
@@ -113,28 +113,30 @@ ability-cli doctor
|
|
|
113
113
|
|
|
114
114
|
#### `exec`
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
执行能力(`POST /ability-service/api/agent/v1/ability/call`,同步等待结果)。
|
|
117
117
|
|
|
118
118
|
| 选项 | 说明 |
|
|
119
119
|
|------|------|
|
|
120
120
|
| `--ability-id <id>` | **必填**,能力 ID |
|
|
121
121
|
| `--params <json>` | 参数:JSON 字符串,或指向 JSON 文件的路径 |
|
|
122
|
-
| `--device-id <id>` | 设备 ID
|
|
122
|
+
| `--device-id <id>` | 设备 ID;默认可来自全局/环境变量/配置的合并结果 |
|
|
123
123
|
| `--session-id <id>` | `sessionId` |
|
|
124
124
|
| `--tool-call-id <id>` | `toolCallId` |
|
|
125
125
|
| `--task-id <id>` | `taskId` |
|
|
126
126
|
| `--message-id <id>` | `messageId` |
|
|
127
127
|
| `--trace-id <id>` | `traceId`;未指定时自动生成 |
|
|
128
|
-
| `--timeout <ms>` |
|
|
128
|
+
| `--timeout <ms>` | 超时(毫秒);不传则用配置文件 `defaults.timeout`,再默认 `30000` |
|
|
129
|
+
| `--response-type <type>` | `NONE` / `MCP` / `CONVERT`(可选) |
|
|
130
|
+
| `--mock-token <token>` | 模拟调用 token(可选,测试) |
|
|
129
131
|
| `--json` | 以 JSON 展示返回 `data` |
|
|
130
132
|
|
|
131
133
|
### 下层命令:`raw`
|
|
132
134
|
|
|
133
|
-
`raw`
|
|
135
|
+
`raw` 子命令与 **Agent API** 路径一一对应(前缀 `/ability-service/api/agent/v1`)。
|
|
134
136
|
|
|
135
137
|
#### `raw ability-list`
|
|
136
138
|
|
|
137
|
-
GET
|
|
139
|
+
GET `/ability-service/api/agent/v1/ability/list`。
|
|
138
140
|
|
|
139
141
|
| 选项 | 说明 |
|
|
140
142
|
|------|------|
|
|
@@ -144,18 +146,9 @@ GET 能力列表。
|
|
|
144
146
|
| `--natural-lang <text>` | 自然语言筛选 |
|
|
145
147
|
| `--json` | JSON 输出 |
|
|
146
148
|
|
|
147
|
-
#### `raw ability-record`
|
|
148
|
-
|
|
149
|
-
POST 能力上报。
|
|
150
|
-
|
|
151
|
-
| 选项 | 说明 |
|
|
152
|
-
|------|------|
|
|
153
|
-
| `--file <path>` | **必填**,请求体 JSON 文件路径 |
|
|
154
|
-
| `--json` | JSON 输出 |
|
|
155
|
-
|
|
156
149
|
#### `raw app-info`
|
|
157
150
|
|
|
158
|
-
GET
|
|
151
|
+
GET `/ability-service/api/agent/v1/ability/appInfo`。
|
|
159
152
|
|
|
160
153
|
| 选项 | 说明 |
|
|
161
154
|
|------|------|
|
|
@@ -164,7 +157,7 @@ GET 应用信息。
|
|
|
164
157
|
|
|
165
158
|
#### `raw ability-info`
|
|
166
159
|
|
|
167
|
-
GET
|
|
160
|
+
GET `/ability-service/api/agent/v1/ability/abilityInfo`。
|
|
168
161
|
|
|
169
162
|
| 选项 | 说明 |
|
|
170
163
|
|------|------|
|
|
@@ -172,9 +165,9 @@ GET 能力详情。
|
|
|
172
165
|
| `--device-id <id>` | 设备 ID;**端侧能力**时通常必填;未指定时可使用 `defaults.deviceId` |
|
|
173
166
|
| `--json` | JSON 输出 |
|
|
174
167
|
|
|
175
|
-
#### `raw call
|
|
168
|
+
#### `raw call`
|
|
176
169
|
|
|
177
|
-
POST
|
|
170
|
+
POST `/ability-service/api/agent/v1/ability/call`(请求体由 `--file` 提供完整 JSON)。
|
|
178
171
|
|
|
179
172
|
| 选项 | 说明 |
|
|
180
173
|
|------|------|
|
|
@@ -183,7 +176,7 @@ POST 执行能力。
|
|
|
183
176
|
|
|
184
177
|
#### `raw category-list`
|
|
185
178
|
|
|
186
|
-
GET
|
|
179
|
+
GET `/ability-service/api/agent/v1/ability/category`。
|
|
187
180
|
|
|
188
181
|
| 选项 | 说明 |
|
|
189
182
|
|------|------|
|
|
@@ -198,13 +191,10 @@ GET 全量分类。
|
|
|
198
191
|
| 选项 | 说明 |
|
|
199
192
|
|------|------|
|
|
200
193
|
| `--env <env>` | 目标环境;影响写入哪一段 `profiles`,并更新当前 `env` |
|
|
201
|
-
| `--
|
|
202
|
-
| `--app-secret <secret>` | `appSecret` |
|
|
203
|
-
| `--auth-token <token>` | Authorization token |
|
|
194
|
+
| `--auth-token <token>` | 授权密钥 `sk-…`(写入 `profiles.*.authToken`) |
|
|
204
195
|
| `--base-url <url>` | 网关地址 |
|
|
205
196
|
| `--device-id <id>` | 默认设备 ID(`defaults.deviceId`) |
|
|
206
|
-
| `--
|
|
207
|
-
| `--os-version <ver>` | 默认系统版本 |
|
|
197
|
+
| `--timeout <ms>` | 默认调用超时毫秒数(`defaults.timeout`);`exec` 未带 `--timeout` 时使用 |
|
|
208
198
|
|
|
209
199
|
#### `config show`
|
|
210
200
|
|
|
@@ -216,14 +206,14 @@ GET 全量分类。
|
|
|
216
206
|
|
|
217
207
|
| 选项 | 说明 |
|
|
218
208
|
|------|------|
|
|
219
|
-
| `--app-id <id>` | 覆盖 `zy-app-id
|
|
220
|
-
| `--app-secret <secret>` |
|
|
209
|
+
| `--app-id <id>` | 覆盖 `zy-app-id`(或环境变量 `ABILITY_CLI_APP_ID`) |
|
|
210
|
+
| `--app-secret <secret>` | 覆盖密钥(或环境变量 `ABILITY_CLI_APP_SECRET`) |
|
|
221
211
|
| `--nonce <nonce>` | 固定 nonce |
|
|
222
212
|
| `--timestamp <ts>` | 固定时间戳 |
|
|
223
213
|
|
|
224
214
|
#### `doctor`
|
|
225
215
|
|
|
226
|
-
|
|
216
|
+
检查配置文件路径、当前环境、解析后的 **`Authorization(sk)`** / **`zy-device-id`** / **`baseUrl`**,并请求 `{baseUrl}/time` 做网关连通性探测。
|
|
227
217
|
|
|
228
218
|
---
|
|
229
219
|
|
|
@@ -233,39 +223,39 @@ GET 全量分类。
|
|
|
233
223
|
|
|
234
224
|
默认路径:**`~/.ability-cli/config.json`**。
|
|
235
225
|
|
|
236
|
-
首次运行若文件不存在,会使用内置默认:当前环境
|
|
226
|
+
首次运行若文件不存在,会使用内置默认:当前环境 **`prod`**,`test` / `prod` 各有一套 `baseUrl`;`profiles.*.authToken`(sk)、`defaults.deviceId` 等为空字符串。
|
|
237
227
|
|
|
238
|
-
通过 `ability-cli config set` 写入后,会按 `env` 更新对应 `profiles[env]` 下的 `baseUrl`、`
|
|
228
|
+
通过 `ability-cli config set` 写入后,会按 `env` 更新对应 `profiles[env]` 下的 `baseUrl`、`authToken`(sk)等;`defaults` 下可保存默认设备 ID 等。
|
|
239
229
|
|
|
240
230
|
### 环境变量
|
|
241
231
|
|
|
242
232
|
| 变量 | 作用 |
|
|
243
233
|
|------|------|
|
|
244
234
|
| `ABILITY_CLI_ENV` | 选用 `profiles` 的环境键(如 `test` / `prod`) |
|
|
245
|
-
| `
|
|
246
|
-
| `
|
|
247
|
-
| `
|
|
248
|
-
| `
|
|
235
|
+
| `ABILITY_CLI_AUTH_TOKEN` | 授权密钥 `sk-…`,对应请求头 `Authorization` |
|
|
236
|
+
| `ABILITY_CLI_DEVICE_ID` | 设备 ID,对应请求头 `zy-device-id`,并参与部分 query |
|
|
237
|
+
| `ABILITY_CLI_BASE_URL` | 网关根地址 |
|
|
238
|
+
| `ABILITY_CLI_APP_ID` | 仅用于 `sign debug`(网关 zy-sign 调试) |
|
|
239
|
+
| `ABILITY_CLI_APP_SECRET` | 仅用于 `sign debug`(网关 zy-sign 调试) |
|
|
249
240
|
|
|
250
241
|
### 优先级
|
|
251
242
|
|
|
252
|
-
对
|
|
243
|
+
对 **`authToken` / `deviceId` / `baseUrl`**:**子命令参数 > 全局参数 > 对应环境变量 > 配置文件**(子命令与全局选项先做对象合并,后者覆盖前者)。
|
|
253
244
|
|
|
254
245
|
当前激活的 **profile(test 或 prod)** 由 **`ABILITY_CLI_ENV`(若设置)** 与配置文件中的 **`env`** 字段共同决定(环境变量优先)。
|
|
255
246
|
|
|
256
247
|
---
|
|
257
248
|
|
|
258
|
-
## 6.
|
|
249
|
+
## 6. 鉴权说明(Agent API)
|
|
259
250
|
|
|
260
|
-
|
|
251
|
+
调用 **`/ability-service/api/agent/v1/**`** 时,CLI 仅发送:
|
|
261
252
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
2. 以 **`appSecret` 作为 HMAC 密钥**,对原串做 UTF-8 编码后的 HMAC-SHA256,结果取 **hex** 字符串,作为 `zy-sign`。
|
|
253
|
+
- `Authorization`:`sk-…`(由 `--auth-token` / `ABILITY_CLI_AUTH_TOKEN` / 配置文件 `authToken` 解析)
|
|
254
|
+
- `zy-device-id`:设备 ID(由 `--device-id` / `ABILITY_CLI_DEVICE_ID` / `defaults.deviceId` 解析)
|
|
265
255
|
|
|
266
|
-
|
|
256
|
+
**不发送**网关侧的 `zy-app-id`、`zy-nonce`、`zy-timestamp`、`zy-sign`。
|
|
267
257
|
|
|
268
|
-
|
|
258
|
+
如需调试历史网关 **HMAC 签名字段**,可使用 `ability-cli sign debug`(凭据为命令行 `--app-id` / `--app-secret` 或环境变量 `ABILITY_CLI_APP_ID` / `ABILITY_CLI_APP_SECRET`,与 Agent API 请求无关)。
|
|
269
259
|
|
|
270
260
|
---
|
|
271
261
|
|
|
@@ -284,7 +274,7 @@ GET 全量分类。
|
|
|
284
274
|
| 0 | 成功 |
|
|
285
275
|
| 1 | 参数错误或未捕获的运行时错误 |
|
|
286
276
|
| 2 | 网络错误(如连接被拒绝、DNS 失败等) |
|
|
287
|
-
| 3 |
|
|
277
|
+
| 3 | 认证失败(保留码位;Agent API 常见错误见服务端 `code`) |
|
|
288
278
|
| 4 | 业务错误(接口返回 `code !== 200`) |
|
|
289
279
|
|
|
290
280
|
---
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
+
import { readFileSync } from "fs";
|
|
6
|
+
import { dirname, join } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
5
8
|
|
|
6
9
|
// src/config.ts
|
|
7
10
|
import fs from "fs";
|
|
@@ -12,22 +15,16 @@ var DEFAULT_CONFIG = {
|
|
|
12
15
|
profiles: {
|
|
13
16
|
test: {
|
|
14
17
|
baseUrl: "https://biz-gw.zyqltest.com",
|
|
15
|
-
zyAppId: "",
|
|
16
|
-
appSecret: "",
|
|
17
18
|
authToken: ""
|
|
18
19
|
},
|
|
19
20
|
prod: {
|
|
20
21
|
baseUrl: "https://biz-gw.zyql.com",
|
|
21
|
-
zyAppId: "",
|
|
22
|
-
appSecret: "",
|
|
23
22
|
authToken: ""
|
|
24
23
|
}
|
|
25
24
|
},
|
|
26
25
|
defaults: {
|
|
27
26
|
deviceId: "",
|
|
28
|
-
|
|
29
|
-
osVersion: "",
|
|
30
|
-
timeout: 30
|
|
27
|
+
timeout: 3e4
|
|
31
28
|
}
|
|
32
29
|
};
|
|
33
30
|
function getDefaultConfigPath() {
|
|
@@ -98,7 +95,7 @@ function printAbilityDetail(a) {
|
|
|
98
95
|
console.log(` ${chalk.gray("\u5E94\u7528:")} ${a.appName} (${a.packageName})`);
|
|
99
96
|
console.log(` ${chalk.gray("\u63CF\u8FF0:")} ${a.description}`);
|
|
100
97
|
console.log(` ${chalk.gray("\u8C03\u7528\u65B9\u5F0F:")} ${a.callingMethod}`);
|
|
101
|
-
console.log(` ${chalk.gray("\u8D85\u65F6:")} ${a.timeout}
|
|
98
|
+
console.log(` ${chalk.gray("\u8D85\u65F6:")} ${a.timeout ?? ""} \u6BEB\u79D2`);
|
|
102
99
|
console.log(` ${chalk.gray("\u6743\u9650:")} ${a.permission}`);
|
|
103
100
|
console.log(` ${chalk.gray("\u8BBE\u5907\u7C7B\u578B:")} ${a.deviceType}`);
|
|
104
101
|
if (a.inputSchema) {
|
|
@@ -124,24 +121,36 @@ function handleApiResponse(res, jsonMode, formatter) {
|
|
|
124
121
|
}
|
|
125
122
|
|
|
126
123
|
// src/commands/config.ts
|
|
124
|
+
function mergeConfigSetOpts(program2, opts) {
|
|
125
|
+
const g = program2.opts();
|
|
126
|
+
return {
|
|
127
|
+
...g,
|
|
128
|
+
...opts,
|
|
129
|
+
env: opts.env ?? g.env,
|
|
130
|
+
authToken: opts.authToken ?? g.authToken,
|
|
131
|
+
baseUrl: opts.baseUrl ?? g.baseUrl,
|
|
132
|
+
deviceId: opts.deviceId ?? g.deviceId,
|
|
133
|
+
timeout: opts.timeout
|
|
134
|
+
};
|
|
135
|
+
}
|
|
127
136
|
function registerConfigCommand(program2) {
|
|
128
137
|
const cfg = program2.command("config").description("\u7BA1\u7406 CLI \u914D\u7F6E");
|
|
129
|
-
cfg.command("set").description("\u8BBE\u7F6E\u914D\u7F6E\u9879").option("--env <env>", "\u73AF\u5883 (test/prod)").option("--
|
|
138
|
+
cfg.command("set").description("\u8BBE\u7F6E\u914D\u7F6E\u9879").option("--env <env>", "\u73AF\u5883 (test/prod)").option("--auth-token <token>", "Authorization token\uFF08sk\uFF09").option("--base-url <url>", "\u7F51\u5173\u5730\u5740").option("--device-id <id>", "\u9ED8\u8BA4\u8BBE\u5907ID").option("--timeout <ms>", "\u9ED8\u8BA4\u8C03\u7528\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09\uFF0C\u5199\u5165 defaults.timeout").action((opts) => {
|
|
139
|
+
const m = mergeConfigSetOpts(program2, opts);
|
|
130
140
|
const configPath = getDefaultConfigPath();
|
|
131
141
|
const config = loadConfig(configPath);
|
|
132
|
-
const env =
|
|
142
|
+
const env = m.env ?? config.env;
|
|
133
143
|
config.env = env;
|
|
134
144
|
if (!config.profiles[env]) {
|
|
135
|
-
config.profiles[env] = { baseUrl: "",
|
|
145
|
+
config.profiles[env] = { baseUrl: "", authToken: "" };
|
|
136
146
|
}
|
|
137
147
|
const p = config.profiles[env];
|
|
138
|
-
if (
|
|
139
|
-
if (
|
|
140
|
-
if (
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (opts.osVersion) config.defaults.osVersion = opts.osVersion;
|
|
148
|
+
if (m.authToken) p.authToken = m.authToken;
|
|
149
|
+
if (m.baseUrl) p.baseUrl = m.baseUrl;
|
|
150
|
+
if (m.deviceId) config.defaults.deviceId = m.deviceId;
|
|
151
|
+
if (m.timeout !== void 0 && String(m.timeout).trim() !== "") {
|
|
152
|
+
config.defaults.timeout = Number(m.timeout);
|
|
153
|
+
}
|
|
145
154
|
saveConfig(configPath, config);
|
|
146
155
|
printSuccess(`\u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230 ${configPath}`);
|
|
147
156
|
});
|
|
@@ -152,38 +161,38 @@ function registerConfigCommand(program2) {
|
|
|
152
161
|
}
|
|
153
162
|
|
|
154
163
|
// src/context.ts
|
|
155
|
-
function
|
|
164
|
+
function firstNonEmpty(...vals) {
|
|
165
|
+
for (const v of vals) {
|
|
166
|
+
if (v !== void 0 && v !== null && String(v).trim() !== "") return String(v).trim();
|
|
167
|
+
}
|
|
168
|
+
return "";
|
|
169
|
+
}
|
|
170
|
+
function buildAgentRequestContext(merged) {
|
|
156
171
|
const config = loadConfig();
|
|
157
|
-
if (
|
|
172
|
+
if (merged.env) config.env = merged.env;
|
|
158
173
|
const profile = getActiveProfile(config);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
return createHmac("sha256", secret).update(message, "utf8").digest("hex");
|
|
177
|
-
}
|
|
178
|
-
function buildSignHeaders(appId, appSecret, opts = {}) {
|
|
179
|
-
const nonce = opts.nonce ?? randomBytes(8).toString("hex");
|
|
180
|
-
const timestamp = opts.timestamp ?? Date.now().toString();
|
|
181
|
-
const zySign = opts.magicSign ? "123456" : sign(`${appId}${nonce}${timestamp}${appSecret}`, appSecret);
|
|
174
|
+
const defaults = config.defaults;
|
|
175
|
+
const authToken = firstNonEmpty(
|
|
176
|
+
merged.authToken,
|
|
177
|
+
process.env.ABILITY_CLI_AUTH_TOKEN,
|
|
178
|
+
profile.authToken
|
|
179
|
+
);
|
|
180
|
+
const deviceId = firstNonEmpty(
|
|
181
|
+
merged.deviceId,
|
|
182
|
+
process.env.ABILITY_CLI_DEVICE_ID,
|
|
183
|
+
defaults.deviceId
|
|
184
|
+
);
|
|
185
|
+
const baseUrl = resolveOption(
|
|
186
|
+
merged.baseUrl,
|
|
187
|
+
process.env.ABILITY_CLI_BASE_URL,
|
|
188
|
+
profile.baseUrl,
|
|
189
|
+
"https://biz-gw.zyql.com"
|
|
190
|
+
);
|
|
182
191
|
return {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
192
|
+
baseUrl,
|
|
193
|
+
authToken,
|
|
194
|
+
deviceId,
|
|
195
|
+
verbose: merged.verbose
|
|
187
196
|
};
|
|
188
197
|
}
|
|
189
198
|
|
|
@@ -197,15 +206,23 @@ function buildUrl(base, path2, params) {
|
|
|
197
206
|
}
|
|
198
207
|
return url.toString();
|
|
199
208
|
}
|
|
200
|
-
function
|
|
201
|
-
const
|
|
202
|
-
|
|
209
|
+
function normalizeAuthorization(token) {
|
|
210
|
+
const t = token.trim();
|
|
211
|
+
return t;
|
|
212
|
+
}
|
|
213
|
+
function buildAgentHeaders(authToken, deviceId) {
|
|
214
|
+
const headers = {};
|
|
215
|
+
if (authToken) {
|
|
216
|
+
headers["Authorization"] = normalizeAuthorization(authToken);
|
|
217
|
+
}
|
|
218
|
+
if (deviceId) {
|
|
219
|
+
headers["zy-device-id"] = deviceId;
|
|
220
|
+
}
|
|
203
221
|
return headers;
|
|
204
222
|
}
|
|
205
223
|
async function apiGet(ctx, path2, params) {
|
|
206
|
-
const
|
|
207
|
-
const
|
|
208
|
-
const url = buildUrl(ctx.profile.baseUrl, path2, params);
|
|
224
|
+
const headers = buildAgentHeaders(ctx.authToken, ctx.deviceId);
|
|
225
|
+
const url = buildUrl(ctx.baseUrl, path2, params);
|
|
209
226
|
if (ctx.verbose) {
|
|
210
227
|
console.error(`[verbose] GET ${url}`);
|
|
211
228
|
console.error(`[verbose] Headers: ${JSON.stringify(headers, null, 2)}`);
|
|
@@ -216,10 +233,9 @@ async function apiGet(ctx, path2, params) {
|
|
|
216
233
|
return body;
|
|
217
234
|
}
|
|
218
235
|
async function apiPost(ctx, path2, data) {
|
|
219
|
-
const
|
|
220
|
-
const headers = buildRequestHeaders(signHeaders, ctx.profile.authToken);
|
|
236
|
+
const headers = buildAgentHeaders(ctx.authToken, ctx.deviceId);
|
|
221
237
|
headers["Content-Type"] = "application/json";
|
|
222
|
-
const url = buildUrl(ctx.
|
|
238
|
+
const url = buildUrl(ctx.baseUrl, path2);
|
|
223
239
|
if (ctx.verbose) {
|
|
224
240
|
console.error(`[verbose] POST ${url}`);
|
|
225
241
|
console.error(`[verbose] Headers: ${JSON.stringify(headers, null, 2)}`);
|
|
@@ -237,53 +253,56 @@ async function apiPost(ctx, path2, data) {
|
|
|
237
253
|
|
|
238
254
|
// src/commands/raw.ts
|
|
239
255
|
import fs2 from "fs";
|
|
256
|
+
|
|
257
|
+
// src/agent-paths.ts
|
|
258
|
+
var AGENT_API_PREFIX = "/ability-service/api/agent/v1";
|
|
259
|
+
var agentPath = {
|
|
260
|
+
abilityList: `${AGENT_API_PREFIX}/ability/list`,
|
|
261
|
+
abilityCategory: `${AGENT_API_PREFIX}/ability/category`,
|
|
262
|
+
appInfo: `${AGENT_API_PREFIX}/ability/appInfo`,
|
|
263
|
+
abilityInfo: `${AGENT_API_PREFIX}/ability/abilityInfo`,
|
|
264
|
+
abilityCall: `${AGENT_API_PREFIX}/ability/call`
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
// src/commands/raw.ts
|
|
240
268
|
function registerRawCommand(program2) {
|
|
241
269
|
const raw = program2.command("raw").description("\u539F\u59CB\u63A5\u53E3\u76F4\u901A\uFF08\u8054\u8C03/\u6392\u969C\uFF09");
|
|
242
270
|
raw.command("ability-list").description("GET \u80FD\u529B\u5217\u8868").option("--device-id <id>", "\u8BBE\u5907ID").option("--app-name <name>", "\u5E94\u7528\u540D\u79F0").option("--category <category>", "\u4E09\u7EA7\u5206\u7C7B").option("--natural-lang <text>", "\u81EA\u7136\u8BED\u8A00\u7B5B\u9009").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
|
|
243
|
-
const
|
|
271
|
+
const merged = { ...program2.opts(), ...opts };
|
|
272
|
+
const ctx = buildAgentRequestContext(merged);
|
|
244
273
|
const params = {};
|
|
245
|
-
if (
|
|
274
|
+
if (ctx.deviceId) params.deviceId = ctx.deviceId;
|
|
246
275
|
if (opts.appName) params.appName = opts.appName;
|
|
247
276
|
if (opts.category) params.category = opts.category;
|
|
248
277
|
if (opts.naturalLang) params.naturalLang = opts.naturalLang;
|
|
249
|
-
const res = await apiGet(ctx,
|
|
278
|
+
const res = await apiGet(ctx, agentPath.abilityList, params);
|
|
250
279
|
handleApiResponse(res, opts.json, (data) => printAbilityTable(data));
|
|
251
280
|
});
|
|
252
|
-
raw.command("ability-record").description("POST \u80FD\u529B\u4E0A\u62A5").requiredOption("--file <path>", "JSON \u6587\u4EF6\u8DEF\u5F84").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
|
|
253
|
-
const ctx = buildContext(program2.opts());
|
|
254
|
-
const data = JSON.parse(fs2.readFileSync(opts.file, "utf-8"));
|
|
255
|
-
const res = await apiPost(ctx, "/ability-service/api/v1/ability/record", data);
|
|
256
|
-
handleApiResponse(res, opts.json, () => printSuccess("\u80FD\u529B\u4E0A\u62A5\u6210\u529F"));
|
|
257
|
-
});
|
|
258
281
|
raw.command("app-info").description("GET \u5E94\u7528\u4FE1\u606F").requiredOption("--package-name <pkg>", "\u5E94\u7528\u5305\u540D").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
|
|
259
|
-
const
|
|
260
|
-
const
|
|
282
|
+
const merged = { ...program2.opts(), ...opts };
|
|
283
|
+
const ctx = buildAgentRequestContext(merged);
|
|
284
|
+
const res = await apiGet(ctx, agentPath.appInfo, { packageName: opts.packageName });
|
|
261
285
|
handleApiResponse(res, opts.json, (data) => printJson(data));
|
|
262
286
|
});
|
|
263
|
-
raw.command("ability-info").description("GET \u80FD\u529B\u8BE6\u60C5").requiredOption("--ability-id <id>", "\u80FD\u529BID").option("--device-id <id>", "\u8BBE\u5907 ID\uFF1B\
|
|
264
|
-
const
|
|
265
|
-
const
|
|
287
|
+
raw.command("ability-info").description("GET \u80FD\u529B\u8BE6\u60C5").requiredOption("--ability-id <id>", "\u80FD\u529BID").option("--device-id <id>", "\u8BBE\u5907 ID\uFF1B\u7AEF\u4FA7\u80FD\u529B\u5EFA\u8BAE\u586B\u5199").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
|
|
288
|
+
const merged = { ...program2.opts(), ...opts };
|
|
289
|
+
const ctx = buildAgentRequestContext(merged);
|
|
266
290
|
const params = { abilityId: opts.abilityId };
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const res = await apiGet(ctx, "/ability-service/api/v1/ability/abilityInfo", params);
|
|
291
|
+
if (ctx.deviceId) params.deviceId = ctx.deviceId;
|
|
292
|
+
const res = await apiGet(ctx, agentPath.abilityInfo, params);
|
|
270
293
|
handleApiResponse(res, opts.json, (data) => printJson(data));
|
|
271
294
|
});
|
|
272
|
-
raw.command("call
|
|
273
|
-
const
|
|
274
|
-
const
|
|
275
|
-
const res = await apiPost(ctx, "/ability-service/api/mcp/async/call-tool", data);
|
|
276
|
-
handleApiResponse(res, opts.json, (data2) => printJson(data2));
|
|
277
|
-
});
|
|
278
|
-
raw.command("ability-callback").description("POST \u4E0A\u62A5\u80FD\u529B\u6267\u884C\u7ED3\u679C").requiredOption("--file <path>", "JSON \u6587\u4EF6\u8DEF\u5F84\uFF0C\u9700\u5305\u542B requestId\uFF0Cbody \u53EF\u9009").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
|
|
279
|
-
const ctx = buildContext(program2.opts());
|
|
295
|
+
raw.command("call").description("POST \u6267\u884C\u80FD\u529B\uFF08Agent API\uFF09").requiredOption("--file <path>", "\u8BF7\u6C42\u4F53 JSON \u6587\u4EF6\u8DEF\u5F84").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
|
|
296
|
+
const merged = { ...program2.opts(), ...opts };
|
|
297
|
+
const ctx = buildAgentRequestContext(merged);
|
|
280
298
|
const data = JSON.parse(fs2.readFileSync(opts.file, "utf-8"));
|
|
281
|
-
const res = await apiPost(ctx,
|
|
299
|
+
const res = await apiPost(ctx, agentPath.abilityCall, data);
|
|
282
300
|
handleApiResponse(res, opts.json, (data2) => printJson(data2));
|
|
283
301
|
});
|
|
284
302
|
raw.command("category-list").description("GET \u5168\u91CF\u5206\u7C7B").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
|
|
285
|
-
const
|
|
286
|
-
const
|
|
303
|
+
const merged = { ...program2.opts(), ...opts };
|
|
304
|
+
const ctx = buildAgentRequestContext(merged);
|
|
305
|
+
const res = await apiGet(ctx, agentPath.abilityCategory);
|
|
287
306
|
handleApiResponse(res, opts.json, (data) => printJson(data));
|
|
288
307
|
});
|
|
289
308
|
}
|
|
@@ -291,16 +310,15 @@ function registerRawCommand(program2) {
|
|
|
291
310
|
// src/commands/search.ts
|
|
292
311
|
function registerSearchCommand(program2) {
|
|
293
312
|
program2.command("search [query]").description("\u641C\u7D22\u80FD\u529B\uFF08\u652F\u6301\u81EA\u7136\u8BED\u8A00\uFF09").option("--device-id <id>", "\u8BBE\u5907ID").option("--app-name <name>", "\u5E94\u7528\u540D\u79F0").option("--category <category>", "\u4E09\u7EA7\u5206\u7C7B").option("--natural-lang <text>", "\u81EA\u7136\u8BED\u8A00\uFF08\u4F18\u5148\u4E8E query\uFF09").option("--json", "JSON \u8F93\u51FA").action(async (query, opts) => {
|
|
294
|
-
const
|
|
295
|
-
const
|
|
313
|
+
const merged = { ...program2.opts(), ...opts };
|
|
314
|
+
const ctx = buildAgentRequestContext(merged);
|
|
296
315
|
const params = {};
|
|
297
|
-
|
|
298
|
-
if (deviceId) params.deviceId = deviceId;
|
|
316
|
+
if (ctx.deviceId) params.deviceId = ctx.deviceId;
|
|
299
317
|
const naturalLang = opts.naturalLang ?? query;
|
|
300
318
|
if (naturalLang) params.naturalLang = naturalLang;
|
|
301
319
|
if (opts.appName) params.appName = opts.appName;
|
|
302
320
|
if (opts.category) params.category = opts.category;
|
|
303
|
-
const res = await apiGet(ctx,
|
|
321
|
+
const res = await apiGet(ctx, agentPath.abilityList, params);
|
|
304
322
|
handleApiResponse(res, opts.json, (data) => {
|
|
305
323
|
const list = Array.isArray(data) ? data : [];
|
|
306
324
|
if (list.length === 0) {
|
|
@@ -340,13 +358,12 @@ function generateTemplate(schema) {
|
|
|
340
358
|
return result;
|
|
341
359
|
}
|
|
342
360
|
function registerInspectCommand(program2) {
|
|
343
|
-
program2.command("inspect").description("\u67E5\u770B\u80FD\u529B\u8BE6\u60C5\u4E0E inputSchema").requiredOption("--ability-id <id>", "\u80FD\u529BID").option("--device-id <id>", "\u8BBE\u5907 ID\uFF1B\
|
|
344
|
-
const
|
|
345
|
-
const
|
|
361
|
+
program2.command("inspect").description("\u67E5\u770B\u80FD\u529B\u8BE6\u60C5\u4E0E inputSchema").requiredOption("--ability-id <id>", "\u80FD\u529BID").option("--device-id <id>", "\u8BBE\u5907 ID\uFF1B\u7AEF\u4FA7\u80FD\u529B\u5EFA\u8BAE\u586B\u5199").option("--gen-template", "\u751F\u6210\u53C2\u6570\u6A21\u677F JSON").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
|
|
362
|
+
const merged = { ...program2.opts(), ...opts };
|
|
363
|
+
const ctx = buildAgentRequestContext(merged);
|
|
346
364
|
const params = { abilityId: opts.abilityId };
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const res = await apiGet(ctx, "/ability-service/api/v1/ability/abilityInfo", params);
|
|
365
|
+
if (ctx.deviceId) params.deviceId = ctx.deviceId;
|
|
366
|
+
const res = await apiGet(ctx, agentPath.abilityInfo, params);
|
|
350
367
|
handleApiResponse(res, opts.json, (data) => {
|
|
351
368
|
if (opts.genTemplate && data.inputSchema) {
|
|
352
369
|
printJson(generateTemplate(data.inputSchema));
|
|
@@ -361,9 +378,11 @@ function registerInspectCommand(program2) {
|
|
|
361
378
|
import { randomUUID } from "crypto";
|
|
362
379
|
import fs3 from "fs";
|
|
363
380
|
function registerExecCommand(program2) {
|
|
364
|
-
program2.command("exec").description("\u6267\u884C\u80FD\u529B").requiredOption("--ability-id <id>", "\u80FD\u529BID").option("--params <json>", "\u53C2\u6570 JSON \u5B57\u7B26\u4E32\u6216\u6587\u4EF6\u8DEF\u5F84").option("--device-id <id>", "\u8BBE\u5907ID").option("--
|
|
365
|
-
const
|
|
366
|
-
const
|
|
381
|
+
program2.command("exec").description("\u6267\u884C\u80FD\u529B").requiredOption("--ability-id <id>", "\u80FD\u529BID").option("--params <json>", "\u53C2\u6570 JSON \u5B57\u7B26\u4E32\u6216\u6587\u4EF6\u8DEF\u5F84").option("--device-id <id>", "\u8BBE\u5907ID").option("--message-id <id>", "messageId").option("--trace-id <id>", "traceId").option("--timeout <ms>", "\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09\uFF1B\u4E0D\u4F20\u5219\u7528\u914D\u7F6E\u6587\u4EF6 defaults.timeout\uFF0C\u9ED8\u8BA4 30000").option("--response-type <type>", "\u8FD4\u56DE\u503C\u5904\u7406\u65B9\u5F0F: NONE | MCP | CONVERT").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
|
|
382
|
+
const merged = { ...program2.opts(), ...opts };
|
|
383
|
+
const ctx = buildAgentRequestContext(merged);
|
|
384
|
+
const cliCfg = loadConfig();
|
|
385
|
+
const timeoutMillis = opts.timeout !== void 0 && String(opts.timeout).trim() !== "" ? Number(opts.timeout) : cliCfg.defaults.timeout ?? 3e4;
|
|
367
386
|
let params = {};
|
|
368
387
|
if (opts.params) {
|
|
369
388
|
if (fs3.existsSync(opts.params)) {
|
|
@@ -379,11 +398,13 @@ function registerExecCommand(program2) {
|
|
|
379
398
|
toolCallId: opts.toolCallId ?? "",
|
|
380
399
|
taskId: opts.taskId ?? "",
|
|
381
400
|
messageId: opts.messageId ?? "",
|
|
382
|
-
deviceId:
|
|
383
|
-
timeoutMillis
|
|
401
|
+
deviceId: ctx.deviceId ?? "",
|
|
402
|
+
timeoutMillis,
|
|
384
403
|
params
|
|
385
404
|
};
|
|
386
|
-
|
|
405
|
+
if (opts.responseType) body.responseType = opts.responseType;
|
|
406
|
+
if (opts.mockToken) body.mockToken = opts.mockToken;
|
|
407
|
+
const res = await apiPost(ctx, agentPath.abilityCall, body);
|
|
387
408
|
handleApiResponse(res, opts.json, (data) => {
|
|
388
409
|
printSuccess("\u80FD\u529B\u6267\u884C\u5B8C\u6210");
|
|
389
410
|
printJson(data);
|
|
@@ -393,18 +414,36 @@ function registerExecCommand(program2) {
|
|
|
393
414
|
|
|
394
415
|
// src/commands/sign.ts
|
|
395
416
|
import chalk2 from "chalk";
|
|
417
|
+
|
|
418
|
+
// src/signer.ts
|
|
419
|
+
import { createHmac, randomBytes } from "crypto";
|
|
420
|
+
function sign(message, secret) {
|
|
421
|
+
return createHmac("sha256", secret).update(message, "utf8").digest("hex");
|
|
422
|
+
}
|
|
423
|
+
function buildSignHeaders(appId, appSecret, opts = {}) {
|
|
424
|
+
const nonce = opts.nonce ?? randomBytes(8).toString("hex");
|
|
425
|
+
const timestamp = opts.timestamp ?? Date.now().toString();
|
|
426
|
+
const zySign = opts.magicSign ? "123456" : sign(`${appId}${nonce}${timestamp}${appSecret}`, appSecret);
|
|
427
|
+
return {
|
|
428
|
+
"zy-app-id": appId,
|
|
429
|
+
"zy-nonce": nonce,
|
|
430
|
+
"zy-timestamp": timestamp,
|
|
431
|
+
"zy-sign": zySign
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// src/commands/sign.ts
|
|
396
436
|
function registerSignCommand(program2) {
|
|
397
|
-
const signCmd = program2.command("sign").description("\u7B7E\u540D\u5DE5\u5177");
|
|
398
|
-
signCmd.command("debug").description("\u8C03\u8BD5\u7B7E\u540D\uFF08\u6253\u5370\u539F\u4E32\u548C\
|
|
399
|
-
const
|
|
400
|
-
const
|
|
401
|
-
const secret = opts.appSecret ?? ctx.profile.appSecret;
|
|
437
|
+
const signCmd = program2.command("sign").description("\u7B7E\u540D\u5DE5\u5177\uFF08\u7F51\u5173 zy-sign \u8C03\u8BD5\uFF0C\u975E Agent API \u8BF7\u6C42\uFF09");
|
|
438
|
+
signCmd.command("debug").description("\u8C03\u8BD5\u7F51\u5173\u7B7E\u540D\uFF08\u6253\u5370\u539F\u4E32\u548C zy-sign\uFF09\uFF1B\u51ED\u636E\u6765\u81EA\u53C2\u6570\u6216\u73AF\u5883\u53D8\u91CF").option("--app-id <id>", "zy-app-id").option("--app-secret <secret>", "appSecret").option("--nonce <nonce>", "\u6307\u5B9A nonce").option("--timestamp <ts>", "\u6307\u5B9A timestamp").action((opts) => {
|
|
439
|
+
const appId = opts.appId ?? process.env.ABILITY_CLI_APP_ID ?? "";
|
|
440
|
+
const secret = opts.appSecret ?? process.env.ABILITY_CLI_APP_SECRET ?? "";
|
|
402
441
|
const headers = buildSignHeaders(appId, secret, {
|
|
403
442
|
nonce: opts.nonce,
|
|
404
443
|
timestamp: opts.timestamp
|
|
405
444
|
});
|
|
406
445
|
const rawStr = `${appId}${headers["zy-nonce"]}${headers["zy-timestamp"]}${secret}`;
|
|
407
|
-
console.log(chalk2.bold.cyan("\n\u2500\u2500 \u7B7E\u540D\u8C03\u8BD5 \u2500\u2500\n"));
|
|
446
|
+
console.log(chalk2.bold.cyan("\n\u2500\u2500 \u7F51\u5173\u7B7E\u540D\u8C03\u8BD5 \u2500\u2500\n"));
|
|
408
447
|
console.log(` ${chalk2.gray("appId:")} ${appId}`);
|
|
409
448
|
console.log(` ${chalk2.gray("nonce:")} ${headers["zy-nonce"]}`);
|
|
410
449
|
console.log(` ${chalk2.gray("timestamp:")} ${headers["zy-timestamp"]}`);
|
|
@@ -417,16 +456,18 @@ function registerSignCommand(program2) {
|
|
|
417
456
|
import chalk3 from "chalk";
|
|
418
457
|
function registerDoctorCommand(program2) {
|
|
419
458
|
program2.command("doctor").description("\u68C0\u67E5\u914D\u7F6E\u5B8C\u6574\u6027\u548C\u7F51\u5173\u8FDE\u901A\u6027").action(async () => {
|
|
420
|
-
const
|
|
421
|
-
const
|
|
459
|
+
const merged = program2.opts();
|
|
460
|
+
const ctx = buildAgentRequestContext(merged);
|
|
422
461
|
let ok = true;
|
|
423
462
|
console.log(chalk3.bold.cyan("\n\u2500\u2500 CLI \u5065\u5EB7\u68C0\u67E5 \u2500\u2500\n"));
|
|
463
|
+
const configPath = getDefaultConfigPath();
|
|
464
|
+
const config = loadConfig();
|
|
424
465
|
const checks = [
|
|
425
|
-
["\u914D\u7F6E\u6587\u4EF6",
|
|
466
|
+
["\u914D\u7F6E\u6587\u4EF6", configPath, true],
|
|
426
467
|
["\u5F53\u524D\u73AF\u5883", config.env, true],
|
|
427
|
-
["
|
|
428
|
-
["
|
|
429
|
-
["
|
|
468
|
+
["baseUrl", ctx.baseUrl || "(\u7A7A)", !!ctx.baseUrl],
|
|
469
|
+
["Authorization(sk)", ctx.authToken ? "******" : "(\u7A7A)", !!ctx.authToken],
|
|
470
|
+
["zy-device-id", ctx.deviceId || "(\u7A7A)", !!ctx.deviceId]
|
|
430
471
|
];
|
|
431
472
|
for (const [label, val, pass] of checks) {
|
|
432
473
|
const icon = pass ? chalk3.green("\u2714") : chalk3.red("\u2716");
|
|
@@ -434,21 +475,16 @@ function registerDoctorCommand(program2) {
|
|
|
434
475
|
if (!pass) ok = false;
|
|
435
476
|
}
|
|
436
477
|
try {
|
|
437
|
-
const res = await fetch(`${
|
|
478
|
+
const res = await fetch(`${ctx.baseUrl}/time`);
|
|
438
479
|
const body = await res.json();
|
|
439
480
|
if (body.code === 200) {
|
|
440
|
-
console.log(` ${chalk3.green("\u2714")} ${chalk3.gray("\u7F51\u5173\u8FDE\u901A:")} ${body.data}`);
|
|
441
|
-
const serverTs = Number(String(body.data).slice(0, -1) + "0");
|
|
442
|
-
const drift = Math.abs(Date.now() - serverTs);
|
|
443
|
-
if (drift > 3e4) {
|
|
444
|
-
console.log(` ${chalk3.yellow("\u26A0")} ${chalk3.gray("\u65F6\u949F\u504F\u5DEE:")} ${drift}ms\uFF08\u5EFA\u8BAE\u4F7F\u7528 --sync-time\uFF09`);
|
|
445
|
-
}
|
|
481
|
+
console.log(` ${chalk3.green("\u2714")} ${chalk3.gray("\u7F51\u5173\u8FDE\u901A(/time):")} ${body.data}`);
|
|
446
482
|
} else {
|
|
447
|
-
console.log(` ${chalk3.red("\u2716")} ${chalk3.gray("\u7F51\u5173\u8FDE\u901A:")} \u8FD4\u56DE code=${body.code}`);
|
|
483
|
+
console.log(` ${chalk3.red("\u2716")} ${chalk3.gray("\u7F51\u5173\u8FDE\u901A(/time):")} \u8FD4\u56DE code=${body.code}`);
|
|
448
484
|
ok = false;
|
|
449
485
|
}
|
|
450
486
|
} catch (e) {
|
|
451
|
-
console.log(` ${chalk3.red("\u2716")} ${chalk3.gray("\u7F51\u5173\u8FDE\u901A:")} ${e.message}`);
|
|
487
|
+
console.log(` ${chalk3.red("\u2716")} ${chalk3.gray("\u7F51\u5173\u8FDE\u901A(/time):")} ${e.message}`);
|
|
452
488
|
ok = false;
|
|
453
489
|
}
|
|
454
490
|
console.log();
|
|
@@ -462,7 +498,13 @@ function registerDoctorCommand(program2) {
|
|
|
462
498
|
|
|
463
499
|
// src/index.ts
|
|
464
500
|
var program = new Command();
|
|
465
|
-
|
|
501
|
+
function readPackageVersion() {
|
|
502
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
503
|
+
const pkgPath = join(here, "..", "package.json");
|
|
504
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
505
|
+
return pkg.version ?? "0.0.0";
|
|
506
|
+
}
|
|
507
|
+
program.name("ability-cli").description("\u539F\u5B50\u80FD\u529B\u5E73\u53F0 CLI \u5DE5\u5177").version(readPackageVersion()).option("--env <env>", "\u73AF\u5883 (test/prod)\uFF0C\u9009\u62E9 profiles \u4E2D\u54EA\u5957 baseUrl").option("--auth-token <token>", "Authorization\uFF08sk-\u2026\uFF09\uFF0C\u8986\u76D6\u73AF\u5883\u53D8\u91CF\u4E0E\u914D\u7F6E").option("--base-url <url>", "\u7F51\u5173\u6839\u5730\u5740\uFF0C\u8986\u76D6\u73AF\u5883\u53D8\u91CF\u4E0E\u914D\u7F6E").option("--device-id <id>", "\u8BBE\u5907 ID\uFF08zy-device-id \u8BF7\u6C42\u5934 / \u90E8\u5206 query\uFF09\uFF0C\u8986\u76D6\u73AF\u5883\u53D8\u91CF\u4E0E\u914D\u7F6E").option("-v, --verbose", "\u8BE6\u7EC6\u8F93\u51FA");
|
|
466
508
|
registerConfigCommand(program);
|
|
467
509
|
registerRawCommand(program);
|
|
468
510
|
registerSearchCommand(program);
|
package/package.json
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "ability-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "原子能力平台 CLI 工具",
|
|
5
|
-
"repository": {
|
|
6
|
-
"type": "git",
|
|
7
|
-
"url": "<repo-url>"
|
|
8
|
-
},
|
|
9
|
-
"homepage": "<repo-url>",
|
|
10
|
-
"bugs": {
|
|
11
|
-
"url": "<repo-url>/issues"
|
|
12
|
-
},
|
|
13
|
-
"type": "module",
|
|
14
|
-
"bin": {
|
|
15
|
-
"ability-cli": "./dist/index.js"
|
|
16
|
-
},
|
|
17
|
-
"files": [
|
|
18
|
-
"dist",
|
|
19
|
-
"README.md",
|
|
20
|
-
"LICENSE"
|
|
21
|
-
],
|
|
22
|
-
"scripts": {
|
|
23
|
-
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
24
|
-
"dev": "tsup src/index.ts --format esm --watch",
|
|
25
|
-
"test": "vitest run",
|
|
26
|
-
"test:watch": "vitest",
|
|
27
|
-
"prepublishOnly": "npm run build && npm test"
|
|
28
|
-
},
|
|
29
|
-
"keywords": [
|
|
30
|
-
"ability",
|
|
31
|
-
"cli",
|
|
32
|
-
"atomic-ability",
|
|
33
|
-
"mcp",
|
|
34
|
-
"zyql"
|
|
35
|
-
],
|
|
36
|
-
"author": "",
|
|
37
|
-
"license": "ISC",
|
|
38
|
-
"packageManager": "pnpm@10.28.2",
|
|
39
|
-
"dependencies": {
|
|
40
|
-
"chalk": "^5.6.2",
|
|
41
|
-
"cli-table3": "^0.6.5",
|
|
42
|
-
"commander": "^14.0.3"
|
|
43
|
-
},
|
|
44
|
-
"pnpm": {
|
|
45
|
-
"onlyBuiltDependencies": ["esbuild"]
|
|
46
|
-
},
|
|
47
|
-
"devDependencies": {
|
|
48
|
-
"@types/node": "^25.5.2",
|
|
49
|
-
"tsup": "^8.5.1",
|
|
50
|
-
"typescript": "^6.0.2",
|
|
51
|
-
"vitest": "^4.1.3"
|
|
52
|
-
}
|
|
53
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "ability-cli",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "原子能力平台 CLI 工具",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "<repo-url>"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "<repo-url>",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "<repo-url>/issues"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"bin": {
|
|
15
|
+
"ability-cli": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
24
|
+
"dev": "tsup src/index.ts --format esm --watch",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"test:watch": "vitest",
|
|
27
|
+
"prepublishOnly": "npm run build && npm test"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"ability",
|
|
31
|
+
"cli",
|
|
32
|
+
"atomic-ability",
|
|
33
|
+
"mcp",
|
|
34
|
+
"zyql"
|
|
35
|
+
],
|
|
36
|
+
"author": "",
|
|
37
|
+
"license": "ISC",
|
|
38
|
+
"packageManager": "pnpm@10.28.2",
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"chalk": "^5.6.2",
|
|
41
|
+
"cli-table3": "^0.6.5",
|
|
42
|
+
"commander": "^14.0.3"
|
|
43
|
+
},
|
|
44
|
+
"pnpm": {
|
|
45
|
+
"onlyBuiltDependencies": ["esbuild"]
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^25.5.2",
|
|
49
|
+
"tsup": "^8.5.1",
|
|
50
|
+
"typescript": "^6.0.2",
|
|
51
|
+
"vitest": "^4.1.3"
|
|
52
|
+
}
|
|
53
|
+
}
|