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.
Files changed (3) hide show
  1. package/README.md +48 -58
  2. package/dist/index.js +156 -123
  3. package/package.json +53 -53
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 1. 项目简介
4
4
 
5
- **ability-cli** 是面向原子能力平台的命令行工具,用于在终端中搜索能力、查看详情、执行调用,以及直接访问底层 HTTP 接口。
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 --app-id <your-app-id> --app-secret <your-secret>
51
+ # 配置授权密钥(sk)与默认设备 ID(也可改用环境变量,见下文)
52
+ ability-cli config set --auth-token sk-xxxx --device-id <device-id>
53
53
 
54
- # 搜索能力
55
- ability-cli search "帮我导航回家" --device-id abc123
54
+ # 搜索能力(请求头:Authorization + zy-device-id,不发网关 zy-sign)
55
+ ability-cli search --natural-lang "发送一条微信消息"
56
56
 
57
- # 查看能力详情(端侧能力需带设备 ID,也可用 config 里的 defaults.deviceId
58
- ability-cli inspect --ability-id 20001 --device-id <device-id>
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 params.json --device-id abc123
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 --env prod search "查询天气"`)。
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`,决定使用配置文件中哪一套 `profiles` |
81
- | `--app-id <id>` | `zy-app-id` |
82
- | `--app-secret <secret>` | `appSecret` |
83
- | `--auth-token <token>` | `Authorization` 请求头 |
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
- 执行能力(异步 `call-tool`)。
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;默认可来自 `defaults.deviceId` |
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>` | 超时(毫秒),默认 `30000` |
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-tool`
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
- | `--app-id <id>` | `zy-app-id` |
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
- | `--device-model <model>` | 默认设备型号 |
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
- 检查配置文件路径、当前环境、`zy-app-id` / `appSecret` / `baseUrl` 是否已配置,并请求 `{baseUrl}/time` 做网关连通性探测。
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
- 首次运行若文件不存在,会使用内置默认:当前环境 `test`,`test` / `prod` 各有一套 `baseUrl`(测试/生产网关),`zy-appId`、`appSecret` 等为空;`defaults` 中可存默认设备信息等。
226
+ 首次运行若文件不存在,会使用内置默认:当前环境 **`prod`**,`test` / `prod` 各有一套 `baseUrl`;`profiles.*.authToken`(sk)、`defaults.deviceId` 等为空字符串。
237
227
 
238
- 通过 `ability-cli config set` 写入后,会按 `env` 更新对应 `profiles[env]` 下的 `baseUrl`、`zyAppId`、`appSecret`、`authToken` 等。
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
- | `ABILITY_CLI_APP_ID` | 覆盖 `zy-app-id` |
246
- | `ABILITY_CLI_APP_SECRET` | 覆盖 `appSecret` |
247
- | `ABILITY_CLI_AUTH_TOKEN` | 覆盖 Authorization |
248
- | `ABILITY_CLI_BASE_URL` | 覆盖网关根地址 |
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
- **appId / appSecret / authToken / baseUrl** 等请求上下文:**命令行全局选项 > 对应环境变量 > 配置文件当前 profile > 内置默认值**。
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
- 请求头中的 `zy-sign` 使用 **HMAC-SHA256** 计算:
251
+ 调用 **`/ability-service/api/agent/v1/**`** 时,CLI 仅发送:
261
252
 
262
- 1. 拼接**原串**(字符串直接相连,无分隔符):
263
- `zy-app-id` + `zy-nonce` + `zy-timestamp` + `appSecret`
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
- 同时会带上 `zy-app-id`、`zy-nonce`、`zy-timestamp`。
256
+ **不发送**网关侧的 `zy-app-id`、`zy-nonce`、`zy-timestamp`、`zy-sign`。
267
257
 
268
- 在**测试环境**下,若使用全局选项 **`--magic-sign`**,则跳过上述计算,`zy-sign` 使用固定测试值(便于跳过网关验签联调)。
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
- deviceModel: "",
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}s`);
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("--app-id <id>", "zy-app-id").option("--app-secret <secret>", "appSecret").option("--auth-token <token>", "Authorization token").option("--base-url <url>", "\u7F51\u5173\u5730\u5740").option("--device-id <id>", "\u9ED8\u8BA4\u8BBE\u5907ID").option("--device-model <model>", "\u9ED8\u8BA4\u8BBE\u5907\u578B\u53F7").option("--os-version <ver>", "\u9ED8\u8BA4\u7CFB\u7EDF\u7248\u672C").action((opts) => {
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 = opts.env ?? config.env;
142
+ const env = m.env ?? config.env;
136
143
  config.env = env;
137
144
  if (!config.profiles[env]) {
138
- config.profiles[env] = { baseUrl: "", zyAppId: "", appSecret: "", authToken: "" };
145
+ config.profiles[env] = { baseUrl: "", authToken: "" };
139
146
  }
140
147
  const p = config.profiles[env];
141
- if (opts.appId) p.zyAppId = opts.appId;
142
- if (opts.appSecret) p.appSecret = opts.appSecret;
143
- if (opts.authToken) p.authToken = opts.authToken;
144
- if (opts.baseUrl) p.baseUrl = opts.baseUrl;
145
- if (opts.deviceId) config.defaults.deviceId = opts.deviceId;
146
- if (opts.deviceModel) config.defaults.deviceModel = opts.deviceModel;
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 buildContext(opts) {
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 (opts.env) config.env = opts.env;
172
+ if (merged.env) config.env = merged.env;
161
173
  const profile = getActiveProfile(config);
162
- profile.zyAppId = resolveOption(opts.appId, process.env.ABILITY_CLI_APP_ID, profile.zyAppId, "");
163
- profile.appSecret = resolveOption(opts.appSecret, process.env.ABILITY_CLI_APP_SECRET, profile.appSecret, "");
164
- profile.authToken = resolveOption(opts.authToken, process.env.ABILITY_CLI_AUTH_TOKEN, profile.authToken, "");
165
- profile.baseUrl = resolveOption(opts.baseUrl, process.env.ABILITY_CLI_BASE_URL, profile.baseUrl, "https://biz-gw.zyql.com");
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
- profile,
168
- signOpts: { magicSign: opts.magicSign },
169
- verbose: opts.verbose
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 buildRequestHeaders(signHeaders, authToken) {
204
- const headers = { ...signHeaders };
205
- if (authToken) headers["Authorization"] = authToken;
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 signHeaders = buildSignHeaders(ctx.profile.zyAppId, ctx.profile.appSecret, ctx.signOpts);
210
- const headers = buildRequestHeaders(signHeaders, ctx.profile.authToken);
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 signHeaders = buildSignHeaders(ctx.profile.zyAppId, ctx.profile.appSecret, ctx.signOpts);
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.profile.baseUrl, path2);
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 ctx = buildContext(program2.opts());
271
+ const merged = { ...program2.opts(), ...opts };
272
+ const ctx = buildAgentRequestContext(merged);
247
273
  const params = {};
248
- if (opts.deviceId) params.deviceId = opts.deviceId;
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, "/ability-service/api/v1/ability/list", params);
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 ctx = buildContext(program2.opts());
263
- const res = await apiGet(ctx, "/ability-service/api/v1/ability/appInfo", { packageName: opts.packageName });
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\u5F53\u80FD\u529B\u4E3A\u7AEF\u4FA7\u80FD\u529B\u65F6\u5FC5\u586B").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
267
- const ctx = buildContext(program2.opts());
268
- const defaults = getDefaults();
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
- const deviceId = opts.deviceId ?? defaults.deviceId;
271
- if (deviceId) params.deviceId = deviceId;
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-tool").description("POST \u6267\u884C\u80FD\u529B").requiredOption("--file <path>", "JSON \u6587\u4EF6\u8DEF\u5F84").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
276
- 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);
277
298
  const data = JSON.parse(fs2.readFileSync(opts.file, "utf-8"));
278
- const res = await apiPost(ctx, "/ability-service/api/mcp/async/call-tool", data);
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 ctx = buildContext(program2.opts());
289
- const res = await apiGet(ctx, "/ability-service/api/v1/ability/category");
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 ctx = buildContext(program2.opts());
298
- const defaults = getDefaults();
313
+ const merged = { ...program2.opts(), ...opts };
314
+ const ctx = buildAgentRequestContext(merged);
299
315
  const params = {};
300
- const deviceId = opts.deviceId ?? defaults.deviceId;
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, "/ability-service/api/v1/ability/list", params);
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\u5F53\u80FD\u529B\u4E3A\u7AEF\u4FA7\u80FD\u529B\u65F6\u5FC5\u586B").option("--gen-template", "\u751F\u6210\u53C2\u6570\u6A21\u677F JSON").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
347
- const ctx = buildContext(program2.opts());
348
- const defaults = getDefaults();
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
- const deviceId = opts.deviceId ?? defaults.deviceId;
351
- if (deviceId) params.deviceId = deviceId;
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("--session-id <id>", "sessionId").option("--tool-call-id <id>", "toolCallId").option("--task-id <id>", "taskId").option("--message-id <id>", "messageId").option("--trace-id <id>", "traceId").option("--timeout <ms>", "\u8D85\u65F6\u65F6\u95F4(\u6BEB\u79D2)", "30000").option("--json", "JSON \u8F93\u51FA").action(async (opts) => {
368
- const ctx = buildContext(program2.opts());
369
- const defaults = getDefaults();
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: opts.deviceId ?? defaults.deviceId ?? "",
386
- timeoutMillis: Number(opts.timeout),
401
+ deviceId: ctx.deviceId ?? "",
402
+ timeoutMillis,
387
403
  params
388
404
  };
389
- const res = await apiPost(ctx, "/ability-service/api/mcp/async/call-tool", body);
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\u7ED3\u679C\uFF09").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) => {
402
- const ctx = buildContext(program2.opts());
403
- const appId = opts.appId ?? ctx.profile.zyAppId;
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 config = loadConfig();
424
- const profile = getActiveProfile(config);
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", getDefaultConfigPath(), true],
466
+ ["\u914D\u7F6E\u6587\u4EF6", configPath, true],
429
467
  ["\u5F53\u524D\u73AF\u5883", config.env, true],
430
- ["zy-app-id", profile.zyAppId || "(\u7A7A)", !!profile.zyAppId],
431
- ["appSecret", profile.appSecret ? "******" : "(\u7A7A)", !!profile.appSecret],
432
- ["baseUrl", profile.baseUrl || "(\u7A7A)", !!profile.baseUrl]
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(`${profile.baseUrl}/time`);
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)").option("--app-id <id>", "zy-app-id").option("--app-secret <secret>", "appSecret").option("--auth-token <token>", "Authorization").option("--base-url <url>", "\u7F51\u5173\u5730\u5740").option("--magic-sign", "\u6D4B\u8BD5\u73AF\u5883\u8DF3\u8FC7\u9A8C\u7B7E").option("-v, --verbose", "\u8BE6\u7EC6\u8F93\u51FA");
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.2.2",
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
+ }