agent-resource-management 1.4.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/cmd/skill.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ApiClient } from '../lib/client';
2
2
  import { loadConfig } from '../lib/storage';
3
3
  import { formatSkill, formatSkillDetail, success, error, info } from '../lib/formatter';
4
+ import { shouldOutputJson, outputJson } from '../lib/output';
4
5
  import { validateZip, validateSkillDir } from '../lib/validate';
5
6
  import { writeFileSync, createWriteStream, existsSync, mkdirSync, statSync } from 'fs';
6
7
  import { join, basename, dirname } from 'path';
@@ -12,6 +13,10 @@ import { mkdtempSync, rmSync } from 'fs';
12
13
  export async function listSkills(): Promise<void> {
13
14
  const config = loadConfig();
14
15
  if (!config?.token) {
16
+ if (shouldOutputJson()) {
17
+ outputJson({ success: false, error: { code: 'NOT_LOGGED_IN', message: '未登录,请先运行 arm login' } });
18
+ process.exit(1);
19
+ }
15
20
  error('未登录,请先运行 arm login');
16
21
  process.exit(1);
17
22
  }
@@ -19,6 +24,10 @@ export async function listSkills(): Promise<void> {
19
24
  const client = new ApiClient(config.serverUrl, config.token);
20
25
  try {
21
26
  const result = await client.listSkills();
27
+ if (shouldOutputJson()) {
28
+ outputJson({ success: true, data: result });
29
+ return;
30
+ }
22
31
  if (result.skills.length === 0) {
23
32
  info('暂无 Skill');
24
33
  return;
@@ -29,6 +38,10 @@ export async function listSkills(): Promise<void> {
29
38
  console.log('');
30
39
  }
31
40
  } catch (err) {
41
+ if (shouldOutputJson()) {
42
+ outputJson({ success: false, error: { code: 'LIST_FAILED', message: err instanceof Error ? err.message : '未知错误' } });
43
+ process.exit(1);
44
+ }
32
45
  error(`获取列表失败: ${err instanceof Error ? err.message : '未知错误'}`);
33
46
  process.exit(1);
34
47
  }
@@ -37,6 +50,10 @@ export async function listSkills(): Promise<void> {
37
50
  export async function searchSkills(keyword: string): Promise<void> {
38
51
  const config = loadConfig();
39
52
  if (!config?.token) {
53
+ if (shouldOutputJson()) {
54
+ outputJson({ success: false, error: { code: 'NOT_LOGGED_IN', message: '未登录,请先运行 arm login' } });
55
+ process.exit(1);
56
+ }
40
57
  error('未登录,请先运行 arm login');
41
58
  process.exit(1);
42
59
  }
@@ -44,6 +61,10 @@ export async function searchSkills(keyword: string): Promise<void> {
44
61
  const client = new ApiClient(config.serverUrl, config.token);
45
62
  try {
46
63
  const result = await client.listSkills(keyword);
64
+ if (shouldOutputJson()) {
65
+ outputJson({ success: true, data: result });
66
+ return;
67
+ }
47
68
  if (result.skills.length === 0) {
48
69
  info(`没有找到包含 "${keyword}" 的 Skill`);
49
70
  return;
@@ -54,6 +75,10 @@ export async function searchSkills(keyword: string): Promise<void> {
54
75
  console.log('');
55
76
  }
56
77
  } catch (err) {
78
+ if (shouldOutputJson()) {
79
+ outputJson({ success: false, error: { code: 'SEARCH_FAILED', message: err instanceof Error ? err.message : '未知错误' } });
80
+ process.exit(1);
81
+ }
57
82
  error(`搜索失败: ${err instanceof Error ? err.message : '未知错误'}`);
58
83
  process.exit(1);
59
84
  }
@@ -62,6 +87,10 @@ export async function searchSkills(keyword: string): Promise<void> {
62
87
  export async function infoSkill(name: string): Promise<void> {
63
88
  const config = loadConfig();
64
89
  if (!config?.token) {
90
+ if (shouldOutputJson()) {
91
+ outputJson({ success: false, error: { code: 'NOT_LOGGED_IN', message: '未登录,请先运行 arm login' } });
92
+ process.exit(1);
93
+ }
65
94
  error('未登录,请先运行 arm login');
66
95
  process.exit(1);
67
96
  }
@@ -69,8 +98,16 @@ export async function infoSkill(name: string): Promise<void> {
69
98
  const client = new ApiClient(config.serverUrl, config.token);
70
99
  try {
71
100
  const skill = await client.getSkill(name);
101
+ if (shouldOutputJson()) {
102
+ outputJson({ success: true, data: skill });
103
+ return;
104
+ }
72
105
  console.log(formatSkillDetail(skill));
73
106
  } catch (err) {
107
+ if (shouldOutputJson()) {
108
+ outputJson({ success: false, error: { code: 'INFO_FAILED', message: err instanceof Error ? err.message : '未知错误' } });
109
+ process.exit(1);
110
+ }
74
111
  error(`获取详情失败: ${err instanceof Error ? err.message : '未知错误'}`);
75
112
  process.exit(1);
76
113
  }
@@ -79,18 +116,32 @@ export async function infoSkill(name: string): Promise<void> {
79
116
  export async function downloadSkill(name: string, outputDir?: string): Promise<void> {
80
117
  const config = loadConfig();
81
118
  if (!config?.token) {
119
+ if (shouldOutputJson()) {
120
+ outputJson({ success: false, error: { code: 'NOT_LOGGED_IN', message: '未登录,请先运行 arm login' } });
121
+ process.exit(1);
122
+ }
82
123
  error('未登录,请先运行 arm login');
83
124
  process.exit(1);
84
125
  }
85
126
 
86
127
  const client = new ApiClient(config.serverUrl, config.token);
87
128
  try {
88
- info(`正在下载 ${name}...`);
129
+ if (shouldOutputJson()) {
130
+ info(`正在下载 ${name}...`);
131
+ }
89
132
  const buffer = await client.downloadSkill(name);
90
133
  const outputPath = join(outputDir || '.', `${name}.zip`);
91
134
  writeFileSync(outputPath, Buffer.from(buffer));
135
+ if (shouldOutputJson()) {
136
+ outputJson({ success: true, data: { path: outputPath } });
137
+ return;
138
+ }
92
139
  success(`已下载到 ${outputPath}`);
93
140
  } catch (err) {
141
+ if (shouldOutputJson()) {
142
+ outputJson({ success: false, error: { code: 'DOWNLOAD_FAILED', message: err instanceof Error ? err.message : '未知错误' } });
143
+ process.exit(1);
144
+ }
94
145
  error(`下载失败: ${err instanceof Error ? err.message : '未知错误'}`);
95
146
  process.exit(1);
96
147
  }
@@ -99,11 +150,19 @@ export async function downloadSkill(name: string, outputDir?: string): Promise<v
99
150
  export async function uploadSkill(filePath: string): Promise<void> {
100
151
  const config = loadConfig();
101
152
  if (!config?.token) {
153
+ if (shouldOutputJson()) {
154
+ outputJson({ success: false, error: { code: 'NOT_LOGGED_IN', message: '未登录,请先运行 arm login' } });
155
+ process.exit(1);
156
+ }
102
157
  error('未登录,请先运行 arm login');
103
158
  process.exit(1);
104
159
  }
105
160
 
106
161
  if (!existsSync(filePath)) {
162
+ if (shouldOutputJson()) {
163
+ outputJson({ success: false, error: { code: 'FILE_NOT_FOUND', message: `上传失败: 目录不存在: ${filePath}` } });
164
+ process.exit(1);
165
+ }
107
166
  error(`上传失败: 目录不存在: ${filePath}`);
108
167
  process.exit(1);
109
168
  }
@@ -111,6 +170,10 @@ export async function uploadSkill(filePath: string): Promise<void> {
111
170
  const isZip = filePath.toLowerCase().endsWith('.zip');
112
171
  const validation = isZip ? validateZip(filePath) : validateSkillDir(filePath);
113
172
  if (!validation.valid) {
173
+ if (shouldOutputJson()) {
174
+ outputJson({ success: false, error: { code: 'VALIDATION_FAILED', message: validation.errors.join(', ') } });
175
+ process.exit(1);
176
+ }
114
177
  error(`上传失败: ${validation.errors.join(', ')}`);
115
178
  process.exit(1);
116
179
  }
@@ -127,11 +190,21 @@ export async function uploadSkill(filePath: string): Promise<void> {
127
190
  }
128
191
 
129
192
  const client = new ApiClient(config.serverUrl, config.token);
130
- info(`正在上传 ${filePath}...`);
193
+ if (shouldOutputJson()) {
194
+ info(`正在上传 ${filePath}...`);
195
+ }
131
196
  const skill = await client.uploadSkill(zipPath);
197
+ if (shouldOutputJson()) {
198
+ outputJson({ success: true, data: skill });
199
+ return;
200
+ }
132
201
  success(`上传成功! Skill: ${skill.name}`);
133
202
  } catch (err) {
134
203
  console.error('DEBUG upload error:', err);
204
+ if (shouldOutputJson()) {
205
+ outputJson({ success: false, error: { code: 'UPLOAD_FAILED', message: err instanceof Error ? err.message : '未知错误' } });
206
+ process.exit(1);
207
+ }
135
208
  error(`上传失败: ${err instanceof Error ? err.message : '未知错误'}`);
136
209
  process.exit(1);
137
210
  } finally {
@@ -142,6 +215,10 @@ export async function uploadSkill(filePath: string): Promise<void> {
142
215
  export async function mySkills(): Promise<void> {
143
216
  const config = loadConfig();
144
217
  if (!config?.token) {
218
+ if (shouldOutputJson()) {
219
+ outputJson({ success: false, error: { code: 'NOT_LOGGED_IN', message: '未登录,请先运行 arm login' } });
220
+ process.exit(1);
221
+ }
145
222
  error('未登录,请先运行 arm login');
146
223
  process.exit(1);
147
224
  }
@@ -149,6 +226,10 @@ export async function mySkills(): Promise<void> {
149
226
  const client = new ApiClient(config.serverUrl, config.token);
150
227
  try {
151
228
  const skills = await client.getMySkills();
229
+ if (shouldOutputJson()) {
230
+ outputJson({ success: true, data: skills });
231
+ return;
232
+ }
152
233
  if (skills.length === 0) {
153
234
  info('您还没有发布任何 Skill');
154
235
  return;
@@ -159,6 +240,10 @@ export async function mySkills(): Promise<void> {
159
240
  console.log('');
160
241
  }
161
242
  } catch (err) {
243
+ if (shouldOutputJson()) {
244
+ outputJson({ success: false, error: { code: 'LIST_FAILED', message: err instanceof Error ? err.message : '未知错误' } });
245
+ process.exit(1);
246
+ }
162
247
  error(`获取列表失败: ${err instanceof Error ? err.message : '未知错误'}`);
163
248
  process.exit(1);
164
249
  }
@@ -167,6 +252,10 @@ export async function mySkills(): Promise<void> {
167
252
  export async function deleteSkill(name: string): Promise<void> {
168
253
  const config = loadConfig();
169
254
  if (!config?.token) {
255
+ if (shouldOutputJson()) {
256
+ outputJson({ success: false, error: { code: 'NOT_LOGGED_IN', message: '未登录,请先运行 arm login' } });
257
+ process.exit(1);
258
+ }
170
259
  error('未登录,请先运行 arm login');
171
260
  process.exit(1);
172
261
  }
@@ -174,8 +263,16 @@ export async function deleteSkill(name: string): Promise<void> {
174
263
  const client = new ApiClient(config.serverUrl, config.token);
175
264
  try {
176
265
  await client.deleteSkill(name);
266
+ if (shouldOutputJson()) {
267
+ outputJson({ success: true, data: { name } });
268
+ return;
269
+ }
177
270
  success(`已删除 ${name}`);
178
271
  } catch (err) {
272
+ if (shouldOutputJson()) {
273
+ outputJson({ success: false, error: { code: 'DELETE_FAILED', message: err instanceof Error ? err.message : '未知错误' } });
274
+ process.exit(1);
275
+ }
179
276
  error(`删除失败: ${err instanceof Error ? err.message : '未知错误'}`);
180
277
  process.exit(1);
181
278
  }
@@ -185,6 +282,22 @@ export async function validateSkill(filePath: string): Promise<void> {
185
282
  const isDir = existsSync(filePath) && statSync(filePath).isDirectory();
186
283
  const result = isDir ? validateSkillDir(filePath) : validateZip(filePath);
187
284
 
285
+ if (shouldOutputJson()) {
286
+ outputJson({
287
+ success: result.valid,
288
+ data: {
289
+ valid: result.valid,
290
+ errors: result.errors,
291
+ warnings: result.warnings,
292
+ metadata: result.metadata,
293
+ },
294
+ });
295
+ if (!result.valid) {
296
+ process.exit(1);
297
+ }
298
+ return;
299
+ }
300
+
188
301
  if (result.valid) {
189
302
  success('验证通过!');
190
303
  } else {
@@ -0,0 +1,35 @@
1
+ import { loadConfig, saveConfig } from './storage';
2
+
3
+ export type OutputMode = 'json' | 'text';
4
+
5
+ export interface JsonResult<T = unknown> {
6
+ success: boolean;
7
+ data?: T;
8
+ error?: {
9
+ code: string;
10
+ message: string;
11
+ };
12
+ }
13
+
14
+ export function outputJson<T>(result: JsonResult<T>): void {
15
+ console.log(JSON.stringify(result, null, 2));
16
+ }
17
+
18
+ export function shouldOutputJson(): boolean {
19
+ if (process.argv.includes('--json') || process.argv.includes('-j')) {
20
+ return true;
21
+ }
22
+ const config = loadConfig();
23
+ return config.outputMode !== 'text';
24
+ }
25
+
26
+ export function getOutputMode(): OutputMode {
27
+ const config = loadConfig();
28
+ return config.outputMode || 'json';
29
+ }
30
+
31
+ export function setOutputMode(mode: OutputMode): void {
32
+ const config = loadConfig() || {};
33
+ config.outputMode = mode;
34
+ saveConfig(config);
35
+ }
@@ -12,6 +12,7 @@ interface Config {
12
12
  name: string;
13
13
  email: string;
14
14
  };
15
+ outputMode?: 'json' | 'text';
15
16
  }
16
17
 
17
18
  function ensureConfigDir() {
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 } 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 { getOutputMode, setOutputMode } from './lib/output';
6
7
 
7
8
  const args = process.argv.slice(2);
8
9
  const command = args[0];
@@ -160,6 +161,16 @@ async function main() {
160
161
  await getCurrentUser();
161
162
  break;
162
163
 
164
+ case 'output':
165
+ if (subCommand === 'json' || subCommand === 'text') {
166
+ setOutputMode(subCommand);
167
+ console.log(`输出模式已设置为: ${subCommand}`);
168
+ } else {
169
+ const mode = getOutputMode();
170
+ console.log(`当前输出模式: ${mode}`);
171
+ }
172
+ break;
173
+
163
174
  case 'agent':
164
175
  switch (subCommand) {
165
176
  case 'ls':
@@ -359,6 +370,7 @@ Agent Resource Management (arm)
359
370
  用法:
360
371
  arm login <server-url> <api-key> 登录
361
372
  arm logout 登出
373
+ arm output [json|text] 设置/查看输出模式 (默认json)
362
374
  arm skill ls 列出所有 Skill
363
375
  arm skill search <keyword> 搜索 Skill
364
376
  arm skill info <name> 查看 Skill 详情
@@ -1,6 +1,6 @@
1
1
  #!/bin/bash
2
2
 
3
- CLI_DIR="/Users/lk/Documents/Dev/aims/xuanwu/xuanwu-agents/agent-sdk/agent-skill-system/cli"
3
+ CLI_DIR="/Users/lk/Documents/Dev/aims/xuanwu/xuanwu-agents/agent-sdk/agent-resource-management/cli"
4
4
  DATA_DIR="$CLI_DIR/data/skills"
5
5
  SERVER_URL="http://localhost:3000"
6
6
  API_KEY="4567c9e607564e91b3898c46d89cb68dc4e40ec4a52b456699b695cf800fd446"