agent-resource-management 2.1.8 → 2.1.9

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/dist/main.js CHANGED
@@ -16,6 +16,9 @@ class ApiClient {
16
16
  clearToken() {
17
17
  this.token = null;
18
18
  }
19
+ getToken() {
20
+ return this.token;
21
+ }
19
22
  async request(path, options = {}) {
20
23
  const headers = {
21
24
  "Content-Type": "application/json",
@@ -170,7 +173,7 @@ class ApiClient {
170
173
  async listKnowledge(keyword, page = 1, pageSize = 20) {
171
174
  let path = `/knowledges?page=${page}&pageSize=${pageSize}`;
172
175
  if (keyword) {
173
- path += `&keyword=${encodeURIComponent(keyword)}`;
176
+ path += `&search=${encodeURIComponent(keyword)}`;
174
177
  }
175
178
  const res = await this.request(path);
176
179
  if (!res.ok) {
@@ -288,10 +291,10 @@ class ApiClient {
288
291
  throw new Error(res.msg);
289
292
  }
290
293
  }
291
- async bindKnowledgeToAgent(agentId, knowledgeId, version, retrievalConfig) {
294
+ async bindKnowledgeToAgent(agentId, knowledgeId, version, retrievalConfig, kind) {
292
295
  const res = await this.request(`/agents/${agentId}/knowledges`, {
293
296
  method: "POST",
294
- body: JSON.stringify({ knowledgeId, version, retrievalConfig })
297
+ body: JSON.stringify({ knowledgeId, version, retrievalConfig, kind })
295
298
  });
296
299
  if (!res.ok) {
297
300
  throw new Error(res.msg);
@@ -323,7 +326,7 @@ class ApiClient {
323
326
  }
324
327
 
325
328
  // src/lib/storage.ts
326
- import { writeFileSync, readFileSync, existsSync, mkdirSync } from "fs";
329
+ import { writeFileSync, readFileSync, existsSync, mkdirSync, chmodSync } from "fs";
327
330
  import { join } from "path";
328
331
  var CONFIG_DIR = join(process.env.HOME || "/root", ".arm");
329
332
  var CONFIG_FILE = join(CONFIG_DIR, "config.json");
@@ -334,7 +337,8 @@ function ensureConfigDir() {
334
337
  }
335
338
  function saveConfig(config) {
336
339
  ensureConfigDir();
337
- writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
340
+ writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 384 });
341
+ chmodSync(CONFIG_FILE, 384);
338
342
  }
339
343
  function loadConfig() {
340
344
  try {
@@ -527,18 +531,32 @@ async function register(name, email, password) {
527
531
  process.exit(1);
528
532
  }
529
533
  }
530
- async function login(serverUrl, apiKey) {
534
+ async function login() {
535
+ console.log("请在浏览器打开:" + (loadConfig()?.serverUrl || "http://localhost:3000") + "/settings/tokens");
536
+ console.log("生成一个 PAT(建议命名包含机器名),复制粘贴到此处:");
537
+ const { readline } = await import("readline");
538
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
539
+ const token = await new Promise((resolve) => rl.question("PAT> ", (a) => {
540
+ rl.close();
541
+ resolve(a);
542
+ }));
543
+ const trimmed = token.trim();
544
+ if (!trimmed.startsWith("arm_pat_")) {
545
+ error("格式错误:应以 arm_pat_ 开头");
546
+ process.exit(1);
547
+ }
548
+ const config = loadConfig() || { serverUrl: "http://localhost:3000" };
549
+ config.serverUrl = config.serverUrl || "http://localhost:3000";
550
+ config.token = trimmed;
551
+ saveConfig(config);
552
+ const client = new ApiClient(config.serverUrl, trimmed);
531
553
  try {
532
- const client = new ApiClient(serverUrl);
533
- const loginRes = await client.login(apiKey);
534
- saveConfig({
535
- serverUrl,
536
- token: loginRes.token,
537
- user: loginRes.user
538
- });
539
- success(`登录成功! 欢迎, ${loginRes.user.name}`);
540
- } catch (err) {
541
- error(`登录失败: ${err instanceof Error ? err.message : "未知错误"}`);
554
+ const me = await client.me();
555
+ config.user = { id: me.id, name: me.name, email: me.email };
556
+ saveConfig(config);
557
+ success(`登录成功! 欢迎, ${me.name}`);
558
+ } catch (e) {
559
+ error(`Token 无效:${e instanceof Error ? e.message : e}`);
542
560
  process.exit(1);
543
561
  }
544
562
  }
@@ -1352,7 +1370,7 @@ async function unbindSkill(id, skillId, version) {
1352
1370
  process.exit(1);
1353
1371
  }
1354
1372
  }
1355
- async function bindKnowledge(id, knowledgeId, version = "1.0.0", retrievalConfig) {
1373
+ async function bindKnowledge(id, knowledgeId, version = "1.0.0", retrievalConfig, kind) {
1356
1374
  const configStore = loadConfig();
1357
1375
  if (!configStore?.token) {
1358
1376
  if (shouldOutputJson()) {
@@ -1365,12 +1383,12 @@ async function bindKnowledge(id, knowledgeId, version = "1.0.0", retrievalConfig
1365
1383
  const client = new ApiClient(configStore.serverUrl, configStore.token);
1366
1384
  try {
1367
1385
  const parsedConfig = retrievalConfig ? JSON.parse(retrievalConfig) : undefined;
1368
- await client.bindKnowledgeToAgent(id, knowledgeId, version, parsedConfig);
1386
+ await client.bindKnowledgeToAgent(id, knowledgeId, version, parsedConfig, kind);
1369
1387
  if (shouldOutputJson()) {
1370
- outputJson({ success: true, data: { agentId: id, knowledgeId, version, retrievalConfig: parsedConfig } });
1388
+ outputJson({ success: true, data: { agentId: id, knowledgeId, version, kind: kind ?? "experience", retrievalConfig: parsedConfig } });
1371
1389
  return;
1372
1390
  }
1373
- success(`Knowledge "${knowledgeId}@${version}" 已绑定到 Agent "${id}"`);
1391
+ success(`Knowledge "${knowledgeId}@${version}"(${kind ?? "experience"})已绑定到 Agent "${id}"`);
1374
1392
  } catch (err) {
1375
1393
  if (shouldOutputJson()) {
1376
1394
  outputJson({ success: false, error: { code: "BIND_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
@@ -2227,6 +2245,67 @@ function setServer(url) {
2227
2245
  info(`已设置服务端: ${url}`);
2228
2246
  }
2229
2247
 
2248
+ // src/cmd/token.ts
2249
+ async function ensureClient() {
2250
+ const config = loadConfig();
2251
+ if (!config?.token) {
2252
+ error("未登录,请先运行 arm login");
2253
+ process.exit(1);
2254
+ }
2255
+ return { client: new ApiClient(config.serverUrl, config.token), serverUrl: config.serverUrl };
2256
+ }
2257
+ async function listTokens() {
2258
+ const { client, serverUrl } = await ensureClient();
2259
+ const headers = { Authorization: `Bearer ${client.getToken() ?? ""}` };
2260
+ const res = await fetch(`${serverUrl}/api/v1/tokens`, { headers });
2261
+ const j = await res.json();
2262
+ if (!j.ok) {
2263
+ error(j.msg);
2264
+ process.exit(1);
2265
+ }
2266
+ console.table(j.data.tokens.map((t) => ({
2267
+ id: t.id,
2268
+ name: t.name,
2269
+ created: t.createdAt,
2270
+ lastUsed: t.lastUsedAt ?? "(never)",
2271
+ expires: t.expiresAt ?? "(never)"
2272
+ })));
2273
+ success("完成");
2274
+ }
2275
+ async function createToken(name, expiresAt) {
2276
+ const { client, serverUrl } = await ensureClient();
2277
+ const headers = {
2278
+ "Content-Type": "application/json",
2279
+ Authorization: `Bearer ${client.getToken() ?? ""}`
2280
+ };
2281
+ const res = await fetch(`${serverUrl}/api/v1/tokens`, {
2282
+ method: "POST",
2283
+ headers,
2284
+ body: JSON.stringify({ name, expiresAt })
2285
+ });
2286
+ const j = await res.json();
2287
+ if (!j.ok) {
2288
+ error(j.msg);
2289
+ process.exit(1);
2290
+ }
2291
+ success("Token 已创建(仅此一次展示,请妥善保存):");
2292
+ console.log(j.data.token);
2293
+ }
2294
+ async function revokeToken(id) {
2295
+ const { client, serverUrl } = await ensureClient();
2296
+ const headers = { Authorization: `Bearer ${client.getToken() ?? ""}` };
2297
+ const res = await fetch(`${serverUrl}/api/v1/tokens/${id}`, {
2298
+ method: "DELETE",
2299
+ headers
2300
+ });
2301
+ const j = await res.json();
2302
+ if (!j.ok) {
2303
+ error(j.msg);
2304
+ process.exit(1);
2305
+ }
2306
+ success(`已撤销 ${id}`);
2307
+ }
2308
+
2230
2309
  // src/main.ts
2231
2310
  import { readFileSync as readFileSync4 } from "fs";
2232
2311
  import { join as join6 } from "path";
@@ -2257,11 +2336,7 @@ async function main() {
2257
2336
  }
2258
2337
  break;
2259
2338
  case "login":
2260
- if (!args[1] || !args[2]) {
2261
- console.error("用法: arm login <server-url> <api-key>");
2262
- process.exit(1);
2263
- }
2264
- await login(args[1], args[2]);
2339
+ await login();
2265
2340
  break;
2266
2341
  case "logout":
2267
2342
  await logout();
@@ -2326,7 +2401,7 @@ async function main() {
2326
2401
  default:
2327
2402
  console.log(`
2328
2403
  可用命令:
2329
- arm login <server-url> <api-key> 登录
2404
+ arm login 登录(粘贴 PAT)
2330
2405
  arm logout 登出
2331
2406
  arm skill ls 列出所有 Skill
2332
2407
  arm skill search <keyword> 搜索 Skill
@@ -2400,6 +2475,26 @@ async function main() {
2400
2475
  case "me":
2401
2476
  await getCurrentUser();
2402
2477
  break;
2478
+ case "token":
2479
+ if (subCommand === "list") {
2480
+ await listTokens();
2481
+ } else if (subCommand === "create") {
2482
+ if (!args[2]) {
2483
+ console.error("用法: arm token create <name> [expiresAt]");
2484
+ process.exit(1);
2485
+ }
2486
+ await createToken(args[2], args[3]);
2487
+ } else if (subCommand === "revoke") {
2488
+ if (!args[2]) {
2489
+ console.error("用法: arm token revoke <id>");
2490
+ process.exit(1);
2491
+ }
2492
+ await revokeToken(args[2]);
2493
+ } else {
2494
+ console.error("用法: arm token list|create <name> [expiresAt]|revoke <id>");
2495
+ process.exit(1);
2496
+ }
2497
+ break;
2403
2498
  case "output":
2404
2499
  if (subCommand === "json" || subCommand === "text") {
2405
2500
  setOutputMode(subCommand);
@@ -2535,6 +2630,7 @@ async function main() {
2535
2630
  let knowledgeId;
2536
2631
  let skillConfig;
2537
2632
  let knowledgeConfig;
2633
+ let knowledgeKind;
2538
2634
  for (let i = 3;i < args.length; i++) {
2539
2635
  const arg = args[i];
2540
2636
  if (arg.startsWith("--skill=")) {
@@ -2545,14 +2641,17 @@ async function main() {
2545
2641
  skillConfig = arg.split("=").slice(1).join("=");
2546
2642
  } else if (arg.startsWith("--knowledge-config=")) {
2547
2643
  knowledgeConfig = arg.split("=").slice(1).join("=");
2644
+ } else if (arg.startsWith("--kind=")) {
2645
+ knowledgeKind = arg.split("=").slice(1).join("=");
2548
2646
  }
2549
2647
  }
2550
2648
  if (skillId) {
2551
2649
  await bindSkill(id, skillId, undefined, skillConfig);
2552
2650
  } else if (knowledgeId) {
2553
- await bindKnowledge(id, knowledgeId, undefined, knowledgeConfig);
2651
+ const kind = knowledgeKind === "essential" || knowledgeKind === "experience" ? knowledgeKind : undefined;
2652
+ await bindKnowledge(id, knowledgeId, undefined, knowledgeConfig, kind);
2554
2653
  } else {
2555
- console.error("用法: arm agent bind <id> --skill=<skillId> 或 --knowledge=<knowledgeId>");
2654
+ console.error("用法: arm agent bind <id> --skill=<skillId> 或 --knowledge=<knowledgeId> [--kind=essential|experience]");
2556
2655
  process.exit(1);
2557
2656
  }
2558
2657
  }
@@ -2646,7 +2745,7 @@ Agent Resource Management (arm)
2646
2745
 
2647
2746
  用法:
2648
2747
  arm register [--name=<name>] [--email=<email>] [--password=<password>] 注册 (交互式或参数)
2649
- arm login <server-url> <api-key> 登录
2748
+ arm login 登录(粘贴 PAT)
2650
2749
  arm logout 登出
2651
2750
  arm output [json|text] 设置/查看输出模式 (默认json)
2652
2751
  arm skill ls 列出所有 Skill
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-resource-management",
3
- "version": "2.1.8",
3
+ "version": "2.1.9",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "arm": "./dist/main.js"
package/src/cmd/agent.ts CHANGED
@@ -217,7 +217,7 @@ export async function unbindSkill(id: string, skillId: string, version?: string)
217
217
  }
218
218
  }
219
219
 
220
- export async function bindKnowledge(id: string, knowledgeId: string, version: string = '1.0.0', retrievalConfig?: string): Promise<void> {
220
+ export async function bindKnowledge(id: string, knowledgeId: string, version: string = '1.0.0', retrievalConfig?: string, kind?: 'essential' | 'experience'): Promise<void> {
221
221
  const configStore = loadConfig();
222
222
  if (!configStore?.token) {
223
223
  if (shouldOutputJson()) {
@@ -231,13 +231,13 @@ export async function bindKnowledge(id: string, knowledgeId: string, version: st
231
231
  const client = new ApiClient(configStore.serverUrl, configStore.token);
232
232
  try {
233
233
  const parsedConfig = retrievalConfig ? JSON.parse(retrievalConfig) : undefined;
234
- await client.bindKnowledgeToAgent(id, knowledgeId, version, parsedConfig);
234
+ await client.bindKnowledgeToAgent(id, knowledgeId, version, parsedConfig, kind);
235
235
 
236
236
  if (shouldOutputJson()) {
237
- outputJson({ success: true, data: { agentId: id, knowledgeId, version, retrievalConfig: parsedConfig } });
237
+ outputJson({ success: true, data: { agentId: id, knowledgeId, version, kind: kind ?? 'experience', retrievalConfig: parsedConfig } });
238
238
  return;
239
239
  }
240
- success(`Knowledge "${knowledgeId}@${version}" 已绑定到 Agent "${id}"`);
240
+ success(`Knowledge "${knowledgeId}@${version}"(${kind ?? 'experience'})已绑定到 Agent "${id}"`);
241
241
  } catch (err) {
242
242
  if (shouldOutputJson()) {
243
243
  outputJson({ success: false, error: { code: 'BIND_FAILED', message: err instanceof Error ? err.message : '未知错误' } });
package/src/cmd/auth.ts CHANGED
@@ -52,20 +52,32 @@ export async function register(name?: string, email?: string, password?: string)
52
52
  }
53
53
  }
54
54
 
55
- export async function login(serverUrl: string, apiKey: string): Promise<void> {
56
- try {
57
- const client = new ApiClient(serverUrl);
58
- const loginRes = await client.login(apiKey);
55
+ export async function login(): Promise<void> {
56
+ console.log('请在浏览器打开:' + (loadConfig()?.serverUrl || 'http://localhost:3000') + '/settings/tokens');
57
+ console.log('生成一个 PAT(建议命名包含机器名),复制粘贴到此处:');
58
+ const { readline } = await import('readline');
59
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
60
+ const token = await new Promise<string>((resolve) => rl.question('PAT> ', (a) => { rl.close(); resolve(a); }));
61
+ const trimmed = token.trim();
62
+ if (!trimmed.startsWith('arm_pat_')) {
63
+ error('格式错误:应以 arm_pat_ 开头');
64
+ process.exit(1);
65
+ }
59
66
 
60
- saveConfig({
61
- serverUrl,
62
- token: loginRes.token,
63
- user: loginRes.user,
64
- });
67
+ const config = loadConfig() || { serverUrl: 'http://localhost:3000' };
68
+ config.serverUrl = config.serverUrl || 'http://localhost:3000';
69
+ config.token = trimmed;
70
+ saveConfig(config);
65
71
 
66
- success(`登录成功! 欢迎, ${loginRes.user.name}`);
67
- } catch (err) {
68
- error(`登录失败: ${err instanceof Error ? err.message : '未知错误'}`);
72
+ // 顺便用这个 token 拉一次用户信息
73
+ const client = new ApiClient(config.serverUrl, trimmed);
74
+ try {
75
+ const me = await client.me();
76
+ config.user = { id: me.id, name: me.name, email: me.email };
77
+ saveConfig(config);
78
+ success(`登录成功! 欢迎, ${me.name}`);
79
+ } catch (e) {
80
+ error(`Token 无效:${e instanceof Error ? e.message : e}`);
69
81
  process.exit(1);
70
82
  }
71
83
  }
@@ -97,4 +109,4 @@ export async function getCurrentUser(): Promise<void> {
97
109
  error(`获取用户信息失败: ${err instanceof Error ? err.message : '未知错误'}`);
98
110
  process.exit(1);
99
111
  }
100
- }
112
+ }
@@ -0,0 +1,57 @@
1
+ import { ApiClient } from '../lib/client';
2
+ import { loadConfig } from '../lib/storage';
3
+ import { success, error } from '../lib/formatter';
4
+
5
+ async function ensureClient(): Promise<{ client: ApiClient; serverUrl: string }> {
6
+ const config = loadConfig();
7
+ if (!config?.token) {
8
+ error('未登录,请先运行 arm login');
9
+ process.exit(1);
10
+ }
11
+ return { client: new ApiClient(config.serverUrl, config.token), serverUrl: config.serverUrl };
12
+ }
13
+
14
+ export async function listTokens(): Promise<void> {
15
+ const { client, serverUrl } = await ensureClient();
16
+ const headers = { Authorization: `Bearer ${client.getToken() ?? ''}` };
17
+ const res = await fetch(`${serverUrl}/api/v1/tokens`, { headers });
18
+ const j = await res.json();
19
+ if (!j.ok) { error(j.msg); process.exit(1); }
20
+ console.table(j.data.tokens.map((t: any) => ({
21
+ id: t.id,
22
+ name: t.name,
23
+ created: t.createdAt,
24
+ lastUsed: t.lastUsedAt ?? '(never)',
25
+ expires: t.expiresAt ?? '(never)',
26
+ })));
27
+ success('完成');
28
+ }
29
+
30
+ export async function createToken(name: string, expiresAt?: string): Promise<void> {
31
+ const { client, serverUrl } = await ensureClient();
32
+ const headers = {
33
+ 'Content-Type': 'application/json',
34
+ Authorization: `Bearer ${client.getToken() ?? ''}`,
35
+ };
36
+ const res = await fetch(`${serverUrl}/api/v1/tokens`, {
37
+ method: 'POST',
38
+ headers,
39
+ body: JSON.stringify({ name, expiresAt }),
40
+ });
41
+ const j = await res.json();
42
+ if (!j.ok) { error(j.msg); process.exit(1); }
43
+ success('Token 已创建(仅此一次展示,请妥善保存):');
44
+ console.log(j.data.token);
45
+ }
46
+
47
+ export async function revokeToken(id: string): Promise<void> {
48
+ const { client, serverUrl } = await ensureClient();
49
+ const headers = { Authorization: `Bearer ${client.getToken() ?? ''}` };
50
+ const res = await fetch(`${serverUrl}/api/v1/tokens/${id}`, {
51
+ method: 'DELETE',
52
+ headers,
53
+ });
54
+ const j = await res.json();
55
+ if (!j.ok) { error(j.msg); process.exit(1); }
56
+ success(`已撤销 ${id}`);
57
+ }
package/src/lib/client.ts CHANGED
@@ -17,6 +17,10 @@ export class ApiClient {
17
17
  this.token = null;
18
18
  }
19
19
 
20
+ getToken(): string | null {
21
+ return this.token;
22
+ }
23
+
20
24
  private async request<T>(
21
25
  path: string,
22
26
  options: RequestInit = {}
@@ -200,7 +204,7 @@ export class ApiClient {
200
204
  async listKnowledge(keyword?: string, page = 1, pageSize = 20): Promise<{ knowledges: any[]; total: number }> {
201
205
  let path = `/knowledges?page=${page}&pageSize=${pageSize}`;
202
206
  if (keyword) {
203
- path += `&keyword=${encodeURIComponent(keyword)}`;
207
+ path += `&search=${encodeURIComponent(keyword)}`;
204
208
  }
205
209
  const res = await this.request<{ knowledges: any[]; total: number }>(path);
206
210
  if (!res.ok) {
@@ -349,10 +353,10 @@ export class ApiClient {
349
353
  }
350
354
  }
351
355
 
352
- async bindKnowledgeToAgent(agentId: string, knowledgeId: string, version: string, retrievalConfig?: { topK?: number; similarityThreshold?: number }): Promise<void> {
356
+ async bindKnowledgeToAgent(agentId: string, knowledgeId: string, version: string, retrievalConfig?: { topK?: number; similarityThreshold?: number }, kind?: 'essential' | 'experience'): Promise<void> {
353
357
  const res = await this.request<null>(`/agents/${agentId}/knowledges`, {
354
358
  method: 'POST',
355
- body: JSON.stringify({ knowledgeId, version, retrievalConfig }),
359
+ body: JSON.stringify({ knowledgeId, version, retrievalConfig, kind }),
356
360
  });
357
361
  if (!res.ok) {
358
362
  throw new Error(res.msg);
@@ -1,4 +1,4 @@
1
- import { writeFileSync, readFileSync, existsSync, mkdirSync } from 'fs';
1
+ import { writeFileSync, readFileSync, existsSync, mkdirSync, chmodSync } from 'fs';
2
2
  import { join } from 'path';
3
3
 
4
4
  const CONFIG_DIR = join(process.env.HOME || '/root', '.arm');
@@ -23,7 +23,8 @@ function ensureConfigDir() {
23
23
 
24
24
  export function saveConfig(config: Config): void {
25
25
  ensureConfigDir();
26
- writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
26
+ writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
27
+ chmodSync(CONFIG_FILE, 0o600);
27
28
  }
28
29
 
29
30
  export function loadConfig(): Config | null {
package/src/main.ts CHANGED
@@ -3,6 +3,7 @@ import { listSkills, searchSkills, infoSkill, downloadSkill, uploadSkill, mySkil
3
3
  import { listAgents, searchAgents, infoAgent, downloadAgent, createAgent, updateAgent, deleteAgent, bindSkill, unbindSkill, bindKnowledge, unbindKnowledge, createAgentFromFolder, syncAgent } from './cmd/agent';
4
4
  import { listKnowledge, searchKnowledge, infoKnowledge, downloadKnowledge, uploadKnowledge, myKnowledge, deleteKnowledge } from './cmd/knowledge';
5
5
  import { showServer, setServer } from './cmd/server';
6
+ import { listTokens, createToken, revokeToken } from './cmd/token';
6
7
  import { getOutputMode, setOutputMode } from './lib/output';
7
8
 
8
9
  import { readFileSync } from 'fs';
@@ -38,11 +39,7 @@ async function main() {
38
39
  break;
39
40
 
40
41
  case 'login':
41
- if (!args[1] || !args[2]) {
42
- console.error('用法: arm login <server-url> <api-key>');
43
- process.exit(1);
44
- }
45
- await login(args[1], args[2]);
42
+ await login();
46
43
  break;
47
44
 
48
45
  case 'logout':
@@ -110,7 +107,7 @@ async function main() {
110
107
  default:
111
108
  console.log(`
112
109
  可用命令:
113
- arm login <server-url> <api-key> 登录
110
+ arm login 登录(粘贴 PAT)
114
111
  arm logout 登出
115
112
  arm skill ls 列出所有 Skill
116
113
  arm skill search <keyword> 搜索 Skill
@@ -187,6 +184,27 @@ async function main() {
187
184
  await getCurrentUser();
188
185
  break;
189
186
 
187
+ case 'token':
188
+ if (subCommand === 'list') {
189
+ await listTokens();
190
+ } else if (subCommand === 'create') {
191
+ if (!args[2]) {
192
+ console.error('用法: arm token create <name> [expiresAt]');
193
+ process.exit(1);
194
+ }
195
+ await createToken(args[2], args[3]);
196
+ } else if (subCommand === 'revoke') {
197
+ if (!args[2]) {
198
+ console.error('用法: arm token revoke <id>');
199
+ process.exit(1);
200
+ }
201
+ await revokeToken(args[2]);
202
+ } else {
203
+ console.error('用法: arm token list|create <name> [expiresAt]|revoke <id>');
204
+ process.exit(1);
205
+ }
206
+ break;
207
+
190
208
  case 'output':
191
209
  if (subCommand === 'json' || subCommand === 'text') {
192
210
  setOutputMode(subCommand);
@@ -328,6 +346,7 @@ async function main() {
328
346
  let knowledgeId: string | undefined;
329
347
  let skillConfig: string | undefined;
330
348
  let knowledgeConfig: string | undefined;
349
+ let knowledgeKind: string | undefined;
331
350
 
332
351
  for (let i = 3; i < args.length; i++) {
333
352
  const arg = args[i];
@@ -339,15 +358,18 @@ async function main() {
339
358
  skillConfig = arg.split('=').slice(1).join('=');
340
359
  } else if (arg.startsWith('--knowledge-config=')) {
341
360
  knowledgeConfig = arg.split('=').slice(1).join('=');
361
+ } else if (arg.startsWith('--kind=')) {
362
+ knowledgeKind = arg.split('=').slice(1).join('=');
342
363
  }
343
364
  }
344
365
 
345
366
  if (skillId) {
346
367
  await bindSkill(id, skillId, undefined, skillConfig);
347
368
  } else if (knowledgeId) {
348
- await bindKnowledge(id, knowledgeId, undefined, knowledgeConfig);
369
+ const kind = (knowledgeKind === 'essential' || knowledgeKind === 'experience') ? knowledgeKind : undefined;
370
+ await bindKnowledge(id, knowledgeId, undefined, knowledgeConfig, kind);
349
371
  } else {
350
- console.error('用法: arm agent bind <id> --skill=<skillId> 或 --knowledge=<knowledgeId>');
372
+ console.error('用法: arm agent bind <id> --skill=<skillId> 或 --knowledge=<knowledgeId> [--kind=essential|experience]');
351
373
  process.exit(1);
352
374
  }
353
375
  }
@@ -444,7 +466,7 @@ Agent Resource Management (arm)
444
466
 
445
467
  用法:
446
468
  arm register [--name=<name>] [--email=<email>] [--password=<password>] 注册 (交互式或参数)
447
- arm login <server-url> <api-key> 登录
469
+ arm login 登录(粘贴 PAT)
448
470
  arm logout 登出
449
471
  arm output [json|text] 设置/查看输出模式 (默认json)
450
472
  arm skill ls 列出所有 Skill