ability-cli 0.2.2 → 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 +156 -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
|
@@ -15,22 +15,16 @@ var DEFAULT_CONFIG = {
|
|
|
15
15
|
profiles: {
|
|
16
16
|
test: {
|
|
17
17
|
baseUrl: "https://biz-gw.zyqltest.com",
|
|
18
|
-
zyAppId: "",
|
|
19
|
-
appSecret: "",
|
|
20
18
|
authToken: ""
|
|
21
19
|
},
|
|
22
20
|
prod: {
|
|
23
21
|
baseUrl: "https://biz-gw.zyql.com",
|
|
24
|
-
zyAppId: "",
|
|
25
|
-
appSecret: "",
|
|
26
22
|
authToken: ""
|
|
27
23
|
}
|
|
28
24
|
},
|
|
29
25
|
defaults: {
|
|
30
26
|
deviceId: "",
|
|
31
|
-
|
|
32
|
-
osVersion: "",
|
|
33
|
-
timeout: 30
|
|
27
|
+
timeout: 3e4
|
|
34
28
|
}
|
|
35
29
|
};
|
|
36
30
|
function getDefaultConfigPath() {
|
|
@@ -101,7 +95,7 @@ function printAbilityDetail(a) {
|
|
|
101
95
|
console.log(` ${chalk.gray("\u5E94\u7528:")} ${a.appName} (${a.packageName})`);
|
|
102
96
|
console.log(` ${chalk.gray("\u63CF\u8FF0:")} ${a.description}`);
|
|
103
97
|
console.log(` ${chalk.gray("\u8C03\u7528\u65B9\u5F0F:")} ${a.callingMethod}`);
|
|
104
|
-
console.log(` ${chalk.gray("\u8D85\u65F6:")} ${a.timeout}
|
|
98
|
+
console.log(` ${chalk.gray("\u8D85\u65F6:")} ${a.timeout ?? ""} \u6BEB\u79D2`);
|
|
105
99
|
console.log(` ${chalk.gray("\u6743\u9650:")} ${a.permission}`);
|
|
106
100
|
console.log(` ${chalk.gray("\u8BBE\u5907\u7C7B\u578B:")} ${a.deviceType}`);
|
|
107
101
|
if (a.inputSchema) {
|
|
@@ -127,24 +121,36 @@ function handleApiResponse(res, jsonMode, formatter) {
|
|
|
127
121
|
}
|
|
128
122
|
|
|
129
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
|
+
}
|
|
130
136
|
function registerConfigCommand(program2) {
|
|
131
137
|
const cfg = program2.command("config").description("\u7BA1\u7406 CLI \u914D\u7F6E");
|
|
132
|
-
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);
|
|
133
140
|
const configPath = getDefaultConfigPath();
|
|
134
141
|
const config = loadConfig(configPath);
|
|
135
|
-
const env =
|
|
142
|
+
const env = m.env ?? config.env;
|
|
136
143
|
config.env = env;
|
|
137
144
|
if (!config.profiles[env]) {
|
|
138
|
-
config.profiles[env] = { baseUrl: "",
|
|
145
|
+
config.profiles[env] = { baseUrl: "", authToken: "" };
|
|
139
146
|
}
|
|
140
147
|
const p = config.profiles[env];
|
|
141
|
-
if (
|
|
142
|
-
if (
|
|
143
|
-
if (
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
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
|
+
}
|
|
148
154
|
saveConfig(configPath, config);
|
|
149
155
|
printSuccess(`\u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230 ${configPath}`);
|
|
150
156
|
});
|
|
@@ -155,38 +161,38 @@ function registerConfigCommand(program2) {
|
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
// src/context.ts
|
|
158
|
-
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) {
|
|
159
171
|
const config = loadConfig();
|
|
160
|
-
if (
|
|
172
|
+
if (merged.env) config.env = merged.env;
|
|
161
173
|
const profile = getActiveProfile(config);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
+
);
|
|
166
191
|
return {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
function getDefaults() {
|
|
173
|
-
return loadConfig().defaults;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// src/signer.ts
|
|
177
|
-
import { createHmac, randomBytes } from "crypto";
|
|
178
|
-
function sign(message, secret) {
|
|
179
|
-
return createHmac("sha256", secret).update(message, "utf8").digest("hex");
|
|
180
|
-
}
|
|
181
|
-
function buildSignHeaders(appId, appSecret, opts = {}) {
|
|
182
|
-
const nonce = opts.nonce ?? randomBytes(8).toString("hex");
|
|
183
|
-
const timestamp = opts.timestamp ?? Date.now().toString();
|
|
184
|
-
const zySign = opts.magicSign ? "123456" : sign(`${appId}${nonce}${timestamp}${appSecret}`, appSecret);
|
|
185
|
-
return {
|
|
186
|
-
"zy-app-id": appId,
|
|
187
|
-
"zy-nonce": nonce,
|
|
188
|
-
"zy-timestamp": timestamp,
|
|
189
|
-
"zy-sign": zySign
|
|
192
|
+
baseUrl,
|
|
193
|
+
authToken,
|
|
194
|
+
deviceId,
|
|
195
|
+
verbose: merged.verbose
|
|
190
196
|
};
|
|
191
197
|
}
|
|
192
198
|
|
|
@@ -200,15 +206,23 @@ function buildUrl(base, path2, params) {
|
|
|
200
206
|
}
|
|
201
207
|
return url.toString();
|
|
202
208
|
}
|
|
203
|
-
function
|
|
204
|
-
const
|
|
205
|
-
|
|
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
|
+
}
|
|
206
221
|
return headers;
|
|
207
222
|
}
|
|
208
223
|
async function apiGet(ctx, path2, params) {
|
|
209
|
-
const
|
|
210
|
-
const
|
|
211
|
-
const url = buildUrl(ctx.profile.baseUrl, path2, params);
|
|
224
|
+
const headers = buildAgentHeaders(ctx.authToken, ctx.deviceId);
|
|
225
|
+
const url = buildUrl(ctx.baseUrl, path2, params);
|
|
212
226
|
if (ctx.verbose) {
|
|
213
227
|
console.error(`[verbose] GET ${url}`);
|
|
214
228
|
console.error(`[verbose] Headers: ${JSON.stringify(headers, null, 2)}`);
|
|
@@ -219,10 +233,9 @@ async function apiGet(ctx, path2, params) {
|
|
|
219
233
|
return body;
|
|
220
234
|
}
|
|
221
235
|
async function apiPost(ctx, path2, data) {
|
|
222
|
-
const
|
|
223
|
-
const headers = buildRequestHeaders(signHeaders, ctx.profile.authToken);
|
|
236
|
+
const headers = buildAgentHeaders(ctx.authToken, ctx.deviceId);
|
|
224
237
|
headers["Content-Type"] = "application/json";
|
|
225
|
-
const url = buildUrl(ctx.
|
|
238
|
+
const url = buildUrl(ctx.baseUrl, path2);
|
|
226
239
|
if (ctx.verbose) {
|
|
227
240
|
console.error(`[verbose] POST ${url}`);
|
|
228
241
|
console.error(`[verbose] Headers: ${JSON.stringify(headers, null, 2)}`);
|
|
@@ -240,53 +253,56 @@ async function apiPost(ctx, path2, data) {
|
|
|
240
253
|
|
|
241
254
|
// src/commands/raw.ts
|
|
242
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
|
|
243
268
|
function registerRawCommand(program2) {
|
|
244
269
|
const raw = program2.command("raw").description("\u539F\u59CB\u63A5\u53E3\u76F4\u901A\uFF08\u8054\u8C03/\u6392\u969C\uFF09");
|
|
245
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) => {
|
|
246
|
-
const
|
|
271
|
+
const merged = { ...program2.opts(), ...opts };
|
|
272
|
+
const ctx = buildAgentRequestContext(merged);
|
|
247
273
|
const params = {};
|
|
248
|
-
if (
|
|
274
|
+
if (ctx.deviceId) params.deviceId = ctx.deviceId;
|
|
249
275
|
if (opts.appName) params.appName = opts.appName;
|
|
250
276
|
if (opts.category) params.category = opts.category;
|
|
251
277
|
if (opts.naturalLang) params.naturalLang = opts.naturalLang;
|
|
252
|
-
const res = await apiGet(ctx,
|
|
278
|
+
const res = await apiGet(ctx, agentPath.abilityList, params);
|
|
253
279
|
handleApiResponse(res, opts.json, (data) => printAbilityTable(data));
|
|
254
280
|
});
|
|
255
|
-
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) => {
|
|
256
|
-
const ctx = buildContext(program2.opts());
|
|
257
|
-
const data = JSON.parse(fs2.readFileSync(opts.file, "utf-8"));
|
|
258
|
-
const res = await apiPost(ctx, "/ability-service/api/v1/ability/record", data);
|
|
259
|
-
handleApiResponse(res, opts.json, () => printSuccess("\u80FD\u529B\u4E0A\u62A5\u6210\u529F"));
|
|
260
|
-
});
|
|
261
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) => {
|
|
262
|
-
const
|
|
263
|
-
const
|
|
282
|
+
const merged = { ...program2.opts(), ...opts };
|
|
283
|
+
const ctx = buildAgentRequestContext(merged);
|
|
284
|
+
const res = await apiGet(ctx, agentPath.appInfo, { packageName: opts.packageName });
|
|
264
285
|
handleApiResponse(res, opts.json, (data) => printJson(data));
|
|
265
286
|
});
|
|
266
|
-
raw.command("ability-info").description("GET \u80FD\u529B\u8BE6\u60C5").requiredOption("--ability-id <id>", "\u80FD\u529BID").option("--device-id <id>", "\u8BBE\u5907 ID\uFF1B\
|
|
267
|
-
const
|
|
268
|
-
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);
|
|
269
290
|
const params = { abilityId: opts.abilityId };
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
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);
|
|
273
293
|
handleApiResponse(res, opts.json, (data) => printJson(data));
|
|
274
294
|
});
|
|
275
|
-
raw.command("call
|
|
276
|
-
const
|
|
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);
|
|
277
298
|
const data = JSON.parse(fs2.readFileSync(opts.file, "utf-8"));
|
|
278
|
-
const res = await apiPost(ctx,
|
|
279
|
-
handleApiResponse(res, opts.json, (data2) => printJson(data2));
|
|
280
|
-
});
|
|
281
|
-
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) => {
|
|
282
|
-
const ctx = buildContext(program2.opts());
|
|
283
|
-
const data = JSON.parse(fs2.readFileSync(opts.file, "utf-8"));
|
|
284
|
-
const res = await apiPost(ctx, "/ability-service/api/v1/ability/callback", data);
|
|
299
|
+
const res = await apiPost(ctx, agentPath.abilityCall, data);
|
|
285
300
|
handleApiResponse(res, opts.json, (data2) => printJson(data2));
|
|
286
301
|
});
|
|
287
302
|
raw.command("category-list").description("GET \u5168\u91CF\u5206\u7C7B").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
|
|
288
|
-
const
|
|
289
|
-
const
|
|
303
|
+
const merged = { ...program2.opts(), ...opts };
|
|
304
|
+
const ctx = buildAgentRequestContext(merged);
|
|
305
|
+
const res = await apiGet(ctx, agentPath.abilityCategory);
|
|
290
306
|
handleApiResponse(res, opts.json, (data) => printJson(data));
|
|
291
307
|
});
|
|
292
308
|
}
|
|
@@ -294,16 +310,15 @@ function registerRawCommand(program2) {
|
|
|
294
310
|
// src/commands/search.ts
|
|
295
311
|
function registerSearchCommand(program2) {
|
|
296
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) => {
|
|
297
|
-
const
|
|
298
|
-
const
|
|
313
|
+
const merged = { ...program2.opts(), ...opts };
|
|
314
|
+
const ctx = buildAgentRequestContext(merged);
|
|
299
315
|
const params = {};
|
|
300
|
-
|
|
301
|
-
if (deviceId) params.deviceId = deviceId;
|
|
316
|
+
if (ctx.deviceId) params.deviceId = ctx.deviceId;
|
|
302
317
|
const naturalLang = opts.naturalLang ?? query;
|
|
303
318
|
if (naturalLang) params.naturalLang = naturalLang;
|
|
304
319
|
if (opts.appName) params.appName = opts.appName;
|
|
305
320
|
if (opts.category) params.category = opts.category;
|
|
306
|
-
const res = await apiGet(ctx,
|
|
321
|
+
const res = await apiGet(ctx, agentPath.abilityList, params);
|
|
307
322
|
handleApiResponse(res, opts.json, (data) => {
|
|
308
323
|
const list = Array.isArray(data) ? data : [];
|
|
309
324
|
if (list.length === 0) {
|
|
@@ -343,13 +358,12 @@ function generateTemplate(schema) {
|
|
|
343
358
|
return result;
|
|
344
359
|
}
|
|
345
360
|
function registerInspectCommand(program2) {
|
|
346
|
-
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\
|
|
347
|
-
const
|
|
348
|
-
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);
|
|
349
364
|
const params = { abilityId: opts.abilityId };
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
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);
|
|
353
367
|
handleApiResponse(res, opts.json, (data) => {
|
|
354
368
|
if (opts.genTemplate && data.inputSchema) {
|
|
355
369
|
printJson(generateTemplate(data.inputSchema));
|
|
@@ -364,9 +378,11 @@ function registerInspectCommand(program2) {
|
|
|
364
378
|
import { randomUUID } from "crypto";
|
|
365
379
|
import fs3 from "fs";
|
|
366
380
|
function registerExecCommand(program2) {
|
|
367
|
-
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("--
|
|
368
|
-
const
|
|
369
|
-
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;
|
|
370
386
|
let params = {};
|
|
371
387
|
if (opts.params) {
|
|
372
388
|
if (fs3.existsSync(opts.params)) {
|
|
@@ -382,11 +398,13 @@ function registerExecCommand(program2) {
|
|
|
382
398
|
toolCallId: opts.toolCallId ?? "",
|
|
383
399
|
taskId: opts.taskId ?? "",
|
|
384
400
|
messageId: opts.messageId ?? "",
|
|
385
|
-
deviceId:
|
|
386
|
-
timeoutMillis
|
|
401
|
+
deviceId: ctx.deviceId ?? "",
|
|
402
|
+
timeoutMillis,
|
|
387
403
|
params
|
|
388
404
|
};
|
|
389
|
-
|
|
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);
|
|
390
408
|
handleApiResponse(res, opts.json, (data) => {
|
|
391
409
|
printSuccess("\u80FD\u529B\u6267\u884C\u5B8C\u6210");
|
|
392
410
|
printJson(data);
|
|
@@ -396,18 +414,36 @@ function registerExecCommand(program2) {
|
|
|
396
414
|
|
|
397
415
|
// src/commands/sign.ts
|
|
398
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
|
|
399
436
|
function registerSignCommand(program2) {
|
|
400
|
-
const signCmd = program2.command("sign").description("\u7B7E\u540D\u5DE5\u5177");
|
|
401
|
-
signCmd.command("debug").description("\u8C03\u8BD5\u7B7E\u540D\uFF08\u6253\u5370\u539F\u4E32\u548C\
|
|
402
|
-
const
|
|
403
|
-
const
|
|
404
|
-
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 ?? "";
|
|
405
441
|
const headers = buildSignHeaders(appId, secret, {
|
|
406
442
|
nonce: opts.nonce,
|
|
407
443
|
timestamp: opts.timestamp
|
|
408
444
|
});
|
|
409
445
|
const rawStr = `${appId}${headers["zy-nonce"]}${headers["zy-timestamp"]}${secret}`;
|
|
410
|
-
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"));
|
|
411
447
|
console.log(` ${chalk2.gray("appId:")} ${appId}`);
|
|
412
448
|
console.log(` ${chalk2.gray("nonce:")} ${headers["zy-nonce"]}`);
|
|
413
449
|
console.log(` ${chalk2.gray("timestamp:")} ${headers["zy-timestamp"]}`);
|
|
@@ -420,16 +456,18 @@ function registerSignCommand(program2) {
|
|
|
420
456
|
import chalk3 from "chalk";
|
|
421
457
|
function registerDoctorCommand(program2) {
|
|
422
458
|
program2.command("doctor").description("\u68C0\u67E5\u914D\u7F6E\u5B8C\u6574\u6027\u548C\u7F51\u5173\u8FDE\u901A\u6027").action(async () => {
|
|
423
|
-
const
|
|
424
|
-
const
|
|
459
|
+
const merged = program2.opts();
|
|
460
|
+
const ctx = buildAgentRequestContext(merged);
|
|
425
461
|
let ok = true;
|
|
426
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();
|
|
427
465
|
const checks = [
|
|
428
|
-
["\u914D\u7F6E\u6587\u4EF6",
|
|
466
|
+
["\u914D\u7F6E\u6587\u4EF6", configPath, true],
|
|
429
467
|
["\u5F53\u524D\u73AF\u5883", config.env, true],
|
|
430
|
-
["
|
|
431
|
-
["
|
|
432
|
-
["
|
|
468
|
+
["baseUrl", ctx.baseUrl || "(\u7A7A)", !!ctx.baseUrl],
|
|
469
|
+
["Authorization(sk)", ctx.authToken ? "******" : "(\u7A7A)", !!ctx.authToken],
|
|
470
|
+
["zy-device-id", ctx.deviceId || "(\u7A7A)", !!ctx.deviceId]
|
|
433
471
|
];
|
|
434
472
|
for (const [label, val, pass] of checks) {
|
|
435
473
|
const icon = pass ? chalk3.green("\u2714") : chalk3.red("\u2716");
|
|
@@ -437,21 +475,16 @@ function registerDoctorCommand(program2) {
|
|
|
437
475
|
if (!pass) ok = false;
|
|
438
476
|
}
|
|
439
477
|
try {
|
|
440
|
-
const res = await fetch(`${
|
|
478
|
+
const res = await fetch(`${ctx.baseUrl}/time`);
|
|
441
479
|
const body = await res.json();
|
|
442
480
|
if (body.code === 200) {
|
|
443
|
-
console.log(` ${chalk3.green("\u2714")} ${chalk3.gray("\u7F51\u5173\u8FDE\u901A:")} ${body.data}`);
|
|
444
|
-
const serverTs = Number(String(body.data).slice(0, -1) + "0");
|
|
445
|
-
const drift = Math.abs(Date.now() - serverTs);
|
|
446
|
-
if (drift > 3e4) {
|
|
447
|
-
console.log(` ${chalk3.yellow("\u26A0")} ${chalk3.gray("\u65F6\u949F\u504F\u5DEE:")} ${drift}ms\uFF08\u5EFA\u8BAE\u4F7F\u7528 --sync-time\uFF09`);
|
|
448
|
-
}
|
|
481
|
+
console.log(` ${chalk3.green("\u2714")} ${chalk3.gray("\u7F51\u5173\u8FDE\u901A(/time):")} ${body.data}`);
|
|
449
482
|
} else {
|
|
450
|
-
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}`);
|
|
451
484
|
ok = false;
|
|
452
485
|
}
|
|
453
486
|
} catch (e) {
|
|
454
|
-
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}`);
|
|
455
488
|
ok = false;
|
|
456
489
|
}
|
|
457
490
|
console.log();
|
|
@@ -471,7 +504,7 @@ function readPackageVersion() {
|
|
|
471
504
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
472
505
|
return pkg.version ?? "0.0.0";
|
|
473
506
|
}
|
|
474
|
-
program.name("ability-cli").description("\u539F\u5B50\u80FD\u529B\u5E73\u53F0 CLI \u5DE5\u5177").version(readPackageVersion()).option("--env <env>", "\u73AF\u5883 (test/prod)
|
|
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");
|
|
475
508
|
registerConfigCommand(program);
|
|
476
509
|
registerRawCommand(program);
|
|
477
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
|
+
}
|