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/dist/main.js CHANGED
@@ -504,6 +504,27 @@ async function getCurrentUser() {
504
504
  }
505
505
  }
506
506
 
507
+ // src/lib/output.ts
508
+ function outputJson(result) {
509
+ console.log(JSON.stringify(result, null, 2));
510
+ }
511
+ function shouldOutputJson() {
512
+ if (process.argv.includes("--json") || process.argv.includes("-j")) {
513
+ return true;
514
+ }
515
+ const config = loadConfig();
516
+ return config.outputMode !== "text";
517
+ }
518
+ function getOutputMode() {
519
+ const config = loadConfig();
520
+ return config.outputMode || "json";
521
+ }
522
+ function setOutputMode(mode) {
523
+ const config = loadConfig() || {};
524
+ config.outputMode = mode;
525
+ saveConfig(config);
526
+ }
527
+
507
528
  // src/lib/validate.ts
508
529
  import { readFileSync as readFileSync2, existsSync as existsSync2, statSync } from "fs";
509
530
  import { execSync } from "child_process";
@@ -684,12 +705,20 @@ import { mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "fs";
684
705
  async function listSkills() {
685
706
  const config = loadConfig();
686
707
  if (!config?.token) {
708
+ if (shouldOutputJson()) {
709
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
710
+ process.exit(1);
711
+ }
687
712
  error("未登录,请先运行 arm login");
688
713
  process.exit(1);
689
714
  }
690
715
  const client = new ApiClient(config.serverUrl, config.token);
691
716
  try {
692
717
  const result = await client.listSkills();
718
+ if (shouldOutputJson()) {
719
+ outputJson({ success: true, data: result });
720
+ return;
721
+ }
693
722
  if (result.skills.length === 0) {
694
723
  info("暂无 Skill");
695
724
  return;
@@ -702,6 +731,10 @@ async function listSkills() {
702
731
  console.log("");
703
732
  }
704
733
  } catch (err) {
734
+ if (shouldOutputJson()) {
735
+ outputJson({ success: false, error: { code: "LIST_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
736
+ process.exit(1);
737
+ }
705
738
  error(`获取列表失败: ${err instanceof Error ? err.message : "未知错误"}`);
706
739
  process.exit(1);
707
740
  }
@@ -709,12 +742,20 @@ async function listSkills() {
709
742
  async function searchSkills(keyword) {
710
743
  const config = loadConfig();
711
744
  if (!config?.token) {
745
+ if (shouldOutputJson()) {
746
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
747
+ process.exit(1);
748
+ }
712
749
  error("未登录,请先运行 arm login");
713
750
  process.exit(1);
714
751
  }
715
752
  const client = new ApiClient(config.serverUrl, config.token);
716
753
  try {
717
754
  const result = await client.listSkills(keyword);
755
+ if (shouldOutputJson()) {
756
+ outputJson({ success: true, data: result });
757
+ return;
758
+ }
718
759
  if (result.skills.length === 0) {
719
760
  info(`没有找到包含 "${keyword}" 的 Skill`);
720
761
  return;
@@ -727,6 +768,10 @@ async function searchSkills(keyword) {
727
768
  console.log("");
728
769
  }
729
770
  } catch (err) {
771
+ if (shouldOutputJson()) {
772
+ outputJson({ success: false, error: { code: "SEARCH_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
773
+ process.exit(1);
774
+ }
730
775
  error(`搜索失败: ${err instanceof Error ? err.message : "未知错误"}`);
731
776
  process.exit(1);
732
777
  }
@@ -734,14 +779,26 @@ async function searchSkills(keyword) {
734
779
  async function infoSkill(name) {
735
780
  const config = loadConfig();
736
781
  if (!config?.token) {
782
+ if (shouldOutputJson()) {
783
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
784
+ process.exit(1);
785
+ }
737
786
  error("未登录,请先运行 arm login");
738
787
  process.exit(1);
739
788
  }
740
789
  const client = new ApiClient(config.serverUrl, config.token);
741
790
  try {
742
791
  const skill = await client.getSkill(name);
792
+ if (shouldOutputJson()) {
793
+ outputJson({ success: true, data: skill });
794
+ return;
795
+ }
743
796
  console.log(formatSkillDetail(skill));
744
797
  } catch (err) {
798
+ if (shouldOutputJson()) {
799
+ outputJson({ success: false, error: { code: "INFO_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
800
+ process.exit(1);
801
+ }
745
802
  error(`获取详情失败: ${err instanceof Error ? err.message : "未知错误"}`);
746
803
  process.exit(1);
747
804
  }
@@ -749,17 +806,31 @@ async function infoSkill(name) {
749
806
  async function downloadSkill(name, outputDir) {
750
807
  const config = loadConfig();
751
808
  if (!config?.token) {
809
+ if (shouldOutputJson()) {
810
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
811
+ process.exit(1);
812
+ }
752
813
  error("未登录,请先运行 arm login");
753
814
  process.exit(1);
754
815
  }
755
816
  const client = new ApiClient(config.serverUrl, config.token);
756
817
  try {
757
- info(`正在下载 ${name}...`);
818
+ if (shouldOutputJson()) {
819
+ info(`正在下载 ${name}...`);
820
+ }
758
821
  const buffer = await client.downloadSkill(name);
759
822
  const outputPath = join3(outputDir || ".", `${name}.zip`);
760
823
  writeFileSync2(outputPath, Buffer.from(buffer));
824
+ if (shouldOutputJson()) {
825
+ outputJson({ success: true, data: { path: outputPath } });
826
+ return;
827
+ }
761
828
  success(`已下载到 ${outputPath}`);
762
829
  } catch (err) {
830
+ if (shouldOutputJson()) {
831
+ outputJson({ success: false, error: { code: "DOWNLOAD_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
832
+ process.exit(1);
833
+ }
763
834
  error(`下载失败: ${err instanceof Error ? err.message : "未知错误"}`);
764
835
  process.exit(1);
765
836
  }
@@ -767,16 +838,28 @@ async function downloadSkill(name, outputDir) {
767
838
  async function uploadSkill(filePath) {
768
839
  const config = loadConfig();
769
840
  if (!config?.token) {
841
+ if (shouldOutputJson()) {
842
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
843
+ process.exit(1);
844
+ }
770
845
  error("未登录,请先运行 arm login");
771
846
  process.exit(1);
772
847
  }
773
848
  if (!existsSync3(filePath)) {
849
+ if (shouldOutputJson()) {
850
+ outputJson({ success: false, error: { code: "FILE_NOT_FOUND", message: `上传失败: 目录不存在: ${filePath}` } });
851
+ process.exit(1);
852
+ }
774
853
  error(`上传失败: 目录不存在: ${filePath}`);
775
854
  process.exit(1);
776
855
  }
777
856
  const isZip = filePath.toLowerCase().endsWith(".zip");
778
857
  const validation = isZip ? validateZip(filePath) : validateSkillDir(filePath);
779
858
  if (!validation.valid) {
859
+ if (shouldOutputJson()) {
860
+ outputJson({ success: false, error: { code: "VALIDATION_FAILED", message: validation.errors.join(", ") } });
861
+ process.exit(1);
862
+ }
780
863
  error(`上传失败: ${validation.errors.join(", ")}`);
781
864
  process.exit(1);
782
865
  }
@@ -790,11 +873,21 @@ async function uploadSkill(filePath) {
790
873
  execSync2(`cd "${dirname(filePath)}" && zip -r "${zipPath}" "${basename(filePath)}" -x ".*"`, { stdio: "pipe" });
791
874
  }
792
875
  const client = new ApiClient(config.serverUrl, config.token);
793
- info(`正在上传 ${filePath}...`);
876
+ if (shouldOutputJson()) {
877
+ info(`正在上传 ${filePath}...`);
878
+ }
794
879
  const skill = await client.uploadSkill(zipPath);
880
+ if (shouldOutputJson()) {
881
+ outputJson({ success: true, data: skill });
882
+ return;
883
+ }
795
884
  success(`上传成功! Skill: ${skill.name}`);
796
885
  } catch (err) {
797
886
  console.error("DEBUG upload error:", err);
887
+ if (shouldOutputJson()) {
888
+ outputJson({ success: false, error: { code: "UPLOAD_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
889
+ process.exit(1);
890
+ }
798
891
  error(`上传失败: ${err instanceof Error ? err.message : "未知错误"}`);
799
892
  process.exit(1);
800
893
  } finally {
@@ -804,12 +897,20 @@ async function uploadSkill(filePath) {
804
897
  async function mySkills() {
805
898
  const config = loadConfig();
806
899
  if (!config?.token) {
900
+ if (shouldOutputJson()) {
901
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
902
+ process.exit(1);
903
+ }
807
904
  error("未登录,请先运行 arm login");
808
905
  process.exit(1);
809
906
  }
810
907
  const client = new ApiClient(config.serverUrl, config.token);
811
908
  try {
812
909
  const skills = await client.getMySkills();
910
+ if (shouldOutputJson()) {
911
+ outputJson({ success: true, data: skills });
912
+ return;
913
+ }
813
914
  if (skills.length === 0) {
814
915
  info("您还没有发布任何 Skill");
815
916
  return;
@@ -822,6 +923,10 @@ async function mySkills() {
822
923
  console.log("");
823
924
  }
824
925
  } catch (err) {
926
+ if (shouldOutputJson()) {
927
+ outputJson({ success: false, error: { code: "LIST_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
928
+ process.exit(1);
929
+ }
825
930
  error(`获取列表失败: ${err instanceof Error ? err.message : "未知错误"}`);
826
931
  process.exit(1);
827
932
  }
@@ -829,14 +934,26 @@ async function mySkills() {
829
934
  async function deleteSkill(name) {
830
935
  const config = loadConfig();
831
936
  if (!config?.token) {
937
+ if (shouldOutputJson()) {
938
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
939
+ process.exit(1);
940
+ }
832
941
  error("未登录,请先运行 arm login");
833
942
  process.exit(1);
834
943
  }
835
944
  const client = new ApiClient(config.serverUrl, config.token);
836
945
  try {
837
946
  await client.deleteSkill(name);
947
+ if (shouldOutputJson()) {
948
+ outputJson({ success: true, data: { name } });
949
+ return;
950
+ }
838
951
  success(`已删除 ${name}`);
839
952
  } catch (err) {
953
+ if (shouldOutputJson()) {
954
+ outputJson({ success: false, error: { code: "DELETE_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
955
+ process.exit(1);
956
+ }
840
957
  error(`删除失败: ${err instanceof Error ? err.message : "未知错误"}`);
841
958
  process.exit(1);
842
959
  }
@@ -844,6 +961,21 @@ async function deleteSkill(name) {
844
961
  async function validateSkill(filePath) {
845
962
  const isDir = existsSync3(filePath) && statSync2(filePath).isDirectory();
846
963
  const result = isDir ? validateSkillDir(filePath) : validateZip(filePath);
964
+ if (shouldOutputJson()) {
965
+ outputJson({
966
+ success: result.valid,
967
+ data: {
968
+ valid: result.valid,
969
+ errors: result.errors,
970
+ warnings: result.warnings,
971
+ metadata: result.metadata
972
+ }
973
+ });
974
+ if (!result.valid) {
975
+ process.exit(1);
976
+ }
977
+ return;
978
+ }
847
979
  if (result.valid) {
848
980
  success("验证通过!");
849
981
  } else {
@@ -887,16 +1019,10 @@ import { writeFileSync as writeFileSync3, existsSync as existsSync4 } from "fs";
887
1019
  import { join as join4 } from "path";
888
1020
  import { execSync as execSync3 } from "child_process";
889
1021
  import { mkdtempSync as mkdtempSync3, rmSync as rmSync3 } from "fs";
890
- function outputJson(result) {
891
- console.log(JSON.stringify(result, null, 2));
892
- }
893
- function getJsonFlag() {
894
- return process.argv.includes("--json") || process.argv.includes("-j");
895
- }
896
1022
  async function createAgent(name, options = {}) {
897
1023
  const config = loadConfig();
898
1024
  if (!config?.token) {
899
- if (getJsonFlag()) {
1025
+ if (shouldOutputJson()) {
900
1026
  outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
901
1027
  process.exit(1);
902
1028
  }
@@ -921,13 +1047,13 @@ async function createAgent(name, options = {}) {
921
1047
  skills,
922
1048
  knowledges
923
1049
  });
924
- if (getJsonFlag()) {
1050
+ if (shouldOutputJson()) {
925
1051
  outputJson({ success: true, data: result });
926
1052
  return;
927
1053
  }
928
1054
  success(`Agent "${name}" 创建成功 (ID: ${result.id})`);
929
1055
  } catch (err) {
930
- if (getJsonFlag()) {
1056
+ if (shouldOutputJson()) {
931
1057
  outputJson({ success: false, error: { code: "CREATE_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
932
1058
  process.exit(1);
933
1059
  }
@@ -938,7 +1064,7 @@ async function createAgent(name, options = {}) {
938
1064
  async function updateAgent(id, options = {}) {
939
1065
  const config = loadConfig();
940
1066
  if (!config?.token) {
941
- if (getJsonFlag()) {
1067
+ if (shouldOutputJson()) {
942
1068
  outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
943
1069
  process.exit(1);
944
1070
  }
@@ -959,13 +1085,13 @@ async function updateAgent(id, options = {}) {
959
1085
  if (options.status !== undefined)
960
1086
  updateData.status = options.status;
961
1087
  const result = await client.updateAgent(id, updateData);
962
- if (getJsonFlag()) {
1088
+ if (shouldOutputJson()) {
963
1089
  outputJson({ success: true, data: result });
964
1090
  return;
965
1091
  }
966
1092
  success(`Agent "${id}" 更新成功`);
967
1093
  } catch (err) {
968
- if (getJsonFlag()) {
1094
+ if (shouldOutputJson()) {
969
1095
  outputJson({ success: false, error: { code: "UPDATE_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
970
1096
  process.exit(1);
971
1097
  }
@@ -976,7 +1102,7 @@ async function updateAgent(id, options = {}) {
976
1102
  async function deleteAgent(id) {
977
1103
  const config = loadConfig();
978
1104
  if (!config?.token) {
979
- if (getJsonFlag()) {
1105
+ if (shouldOutputJson()) {
980
1106
  outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
981
1107
  process.exit(1);
982
1108
  }
@@ -986,13 +1112,13 @@ async function deleteAgent(id) {
986
1112
  const client = new ApiClient(config.serverUrl, config.token);
987
1113
  try {
988
1114
  await client.deleteAgent(id);
989
- if (getJsonFlag()) {
1115
+ if (shouldOutputJson()) {
990
1116
  outputJson({ success: true, data: { id } });
991
1117
  return;
992
1118
  }
993
1119
  success(`Agent "${id}" 删除成功`);
994
1120
  } catch (err) {
995
- if (getJsonFlag()) {
1121
+ if (shouldOutputJson()) {
996
1122
  outputJson({ success: false, error: { code: "DELETE_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
997
1123
  process.exit(1);
998
1124
  }
@@ -1003,7 +1129,7 @@ async function deleteAgent(id) {
1003
1129
  async function bindSkill(id, skillId, config) {
1004
1130
  const configStore = loadConfig();
1005
1131
  if (!configStore?.token) {
1006
- if (getJsonFlag()) {
1132
+ if (shouldOutputJson()) {
1007
1133
  outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1008
1134
  process.exit(1);
1009
1135
  }
@@ -1014,13 +1140,13 @@ async function bindSkill(id, skillId, config) {
1014
1140
  try {
1015
1141
  const parsedConfig = config ? JSON.parse(config) : undefined;
1016
1142
  await client.bindSkillToAgent(id, skillId, parsedConfig);
1017
- if (getJsonFlag()) {
1143
+ if (shouldOutputJson()) {
1018
1144
  outputJson({ success: true, data: { agentId: id, skillId, config: parsedConfig } });
1019
1145
  return;
1020
1146
  }
1021
1147
  success(`Skill "${skillId}" 已绑定到 Agent "${id}"`);
1022
1148
  } catch (err) {
1023
- if (getJsonFlag()) {
1149
+ if (shouldOutputJson()) {
1024
1150
  outputJson({ success: false, error: { code: "BIND_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1025
1151
  process.exit(1);
1026
1152
  }
@@ -1031,7 +1157,7 @@ async function bindSkill(id, skillId, config) {
1031
1157
  async function unbindSkill(id, skillId) {
1032
1158
  const config = loadConfig();
1033
1159
  if (!config?.token) {
1034
- if (getJsonFlag()) {
1160
+ if (shouldOutputJson()) {
1035
1161
  outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1036
1162
  process.exit(1);
1037
1163
  }
@@ -1041,13 +1167,13 @@ async function unbindSkill(id, skillId) {
1041
1167
  const client = new ApiClient(config.serverUrl, config.token);
1042
1168
  try {
1043
1169
  await client.unbindSkillFromAgent(id, skillId);
1044
- if (getJsonFlag()) {
1170
+ if (shouldOutputJson()) {
1045
1171
  outputJson({ success: true, data: { agentId: id, skillId } });
1046
1172
  return;
1047
1173
  }
1048
1174
  success(`Skill "${skillId}" 已从 Agent "${id}" 解绑`);
1049
1175
  } catch (err) {
1050
- if (getJsonFlag()) {
1176
+ if (shouldOutputJson()) {
1051
1177
  outputJson({ success: false, error: { code: "UNBIND_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1052
1178
  process.exit(1);
1053
1179
  }
@@ -1058,7 +1184,7 @@ async function unbindSkill(id, skillId) {
1058
1184
  async function bindKnowledge(id, knowledgeId, retrievalConfig) {
1059
1185
  const configStore = loadConfig();
1060
1186
  if (!configStore?.token) {
1061
- if (getJsonFlag()) {
1187
+ if (shouldOutputJson()) {
1062
1188
  outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1063
1189
  process.exit(1);
1064
1190
  }
@@ -1069,13 +1195,13 @@ async function bindKnowledge(id, knowledgeId, retrievalConfig) {
1069
1195
  try {
1070
1196
  const parsedConfig = retrievalConfig ? JSON.parse(retrievalConfig) : undefined;
1071
1197
  await client.bindKnowledgeToAgent(id, knowledgeId, parsedConfig);
1072
- if (getJsonFlag()) {
1198
+ if (shouldOutputJson()) {
1073
1199
  outputJson({ success: true, data: { agentId: id, knowledgeId, retrievalConfig: parsedConfig } });
1074
1200
  return;
1075
1201
  }
1076
1202
  success(`Knowledge "${knowledgeId}" 已绑定到 Agent "${id}"`);
1077
1203
  } catch (err) {
1078
- if (getJsonFlag()) {
1204
+ if (shouldOutputJson()) {
1079
1205
  outputJson({ success: false, error: { code: "BIND_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1080
1206
  process.exit(1);
1081
1207
  }
@@ -1086,7 +1212,7 @@ async function bindKnowledge(id, knowledgeId, retrievalConfig) {
1086
1212
  async function unbindKnowledge(id, knowledgeId) {
1087
1213
  const config = loadConfig();
1088
1214
  if (!config?.token) {
1089
- if (getJsonFlag()) {
1215
+ if (shouldOutputJson()) {
1090
1216
  outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1091
1217
  process.exit(1);
1092
1218
  }
@@ -1096,13 +1222,13 @@ async function unbindKnowledge(id, knowledgeId) {
1096
1222
  const client = new ApiClient(config.serverUrl, config.token);
1097
1223
  try {
1098
1224
  await client.unbindKnowledgeFromAgent(id, knowledgeId);
1099
- if (getJsonFlag()) {
1225
+ if (shouldOutputJson()) {
1100
1226
  outputJson({ success: true, data: { agentId: id, knowledgeId } });
1101
1227
  return;
1102
1228
  }
1103
1229
  success(`Knowledge "${knowledgeId}" 已从 Agent "${id}" 解绑`);
1104
1230
  } catch (err) {
1105
- if (getJsonFlag()) {
1231
+ if (shouldOutputJson()) {
1106
1232
  outputJson({ success: false, error: { code: "UNBIND_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1107
1233
  process.exit(1);
1108
1234
  }
@@ -1113,12 +1239,20 @@ async function unbindKnowledge(id, knowledgeId) {
1113
1239
  async function listAgents() {
1114
1240
  const config = loadConfig();
1115
1241
  if (!config?.token) {
1242
+ if (shouldOutputJson()) {
1243
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1244
+ process.exit(1);
1245
+ }
1116
1246
  error("未登录,请先运行 arm login");
1117
1247
  process.exit(1);
1118
1248
  }
1119
1249
  const client = new ApiClient(config.serverUrl, config.token);
1120
1250
  try {
1121
1251
  const result = await client.listAgents();
1252
+ if (shouldOutputJson()) {
1253
+ outputJson({ success: true, data: result });
1254
+ return;
1255
+ }
1122
1256
  if (result.agents.length === 0) {
1123
1257
  info("暂无 Agent");
1124
1258
  return;
@@ -1131,6 +1265,10 @@ async function listAgents() {
1131
1265
  console.log("");
1132
1266
  }
1133
1267
  } catch (err) {
1268
+ if (shouldOutputJson()) {
1269
+ outputJson({ success: false, error: { code: "LIST_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1270
+ process.exit(1);
1271
+ }
1134
1272
  error(`获取列表失败: ${err instanceof Error ? err.message : "未知错误"}`);
1135
1273
  process.exit(1);
1136
1274
  }
@@ -1138,12 +1276,20 @@ async function listAgents() {
1138
1276
  async function searchAgents(keyword) {
1139
1277
  const config = loadConfig();
1140
1278
  if (!config?.token) {
1279
+ if (shouldOutputJson()) {
1280
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1281
+ process.exit(1);
1282
+ }
1141
1283
  error("未登录,请先运行 arm login");
1142
1284
  process.exit(1);
1143
1285
  }
1144
1286
  const client = new ApiClient(config.serverUrl, config.token);
1145
1287
  try {
1146
1288
  const result = await client.listAgents(keyword);
1289
+ if (shouldOutputJson()) {
1290
+ outputJson({ success: true, data: result });
1291
+ return;
1292
+ }
1147
1293
  if (result.agents.length === 0) {
1148
1294
  info(`没有找到包含 "${keyword}" 的 Agent`);
1149
1295
  return;
@@ -1156,6 +1302,10 @@ async function searchAgents(keyword) {
1156
1302
  console.log("");
1157
1303
  }
1158
1304
  } catch (err) {
1305
+ if (shouldOutputJson()) {
1306
+ outputJson({ success: false, error: { code: "SEARCH_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1307
+ process.exit(1);
1308
+ }
1159
1309
  error(`搜索失败: ${err instanceof Error ? err.message : "未知错误"}`);
1160
1310
  process.exit(1);
1161
1311
  }
@@ -1163,6 +1313,10 @@ async function searchAgents(keyword) {
1163
1313
  async function infoAgent(name) {
1164
1314
  const config = loadConfig();
1165
1315
  if (!config?.token) {
1316
+ if (shouldOutputJson()) {
1317
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1318
+ process.exit(1);
1319
+ }
1166
1320
  error("未登录,请先运行 arm login");
1167
1321
  process.exit(1);
1168
1322
  }
@@ -1171,6 +1325,10 @@ async function infoAgent(name) {
1171
1325
  const result = await client.listAgents(name);
1172
1326
  const agent = result.agents.find((a) => a.name === name);
1173
1327
  if (!agent) {
1328
+ if (shouldOutputJson()) {
1329
+ outputJson({ success: false, error: { code: "NOT_FOUND", message: `Agent "${name}" 不存在` } });
1330
+ process.exit(1);
1331
+ }
1174
1332
  error(`Agent "${name}" 不存在`);
1175
1333
  process.exit(1);
1176
1334
  }
@@ -1186,8 +1344,16 @@ async function infoAgent(name) {
1186
1344
  });
1187
1345
  fullAgent.knowledges = await Promise.all(knowledgeNamePromises);
1188
1346
  }
1347
+ if (shouldOutputJson()) {
1348
+ outputJson({ success: true, data: fullAgent });
1349
+ return;
1350
+ }
1189
1351
  console.log(formatAgentDetail(fullAgent));
1190
1352
  } catch (err) {
1353
+ if (shouldOutputJson()) {
1354
+ outputJson({ success: false, error: { code: "INFO_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1355
+ process.exit(1);
1356
+ }
1191
1357
  error(`获取详情失败: ${err instanceof Error ? err.message : "未知错误"}`);
1192
1358
  process.exit(1);
1193
1359
  }
@@ -1195,6 +1361,10 @@ async function infoAgent(name) {
1195
1361
  async function downloadAgent(name, outputDir) {
1196
1362
  const config = loadConfig();
1197
1363
  if (!config?.token) {
1364
+ if (shouldOutputJson()) {
1365
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1366
+ process.exit(1);
1367
+ }
1198
1368
  error("未登录,请先运行 arm login");
1199
1369
  process.exit(1);
1200
1370
  }
@@ -1203,10 +1373,16 @@ async function downloadAgent(name, outputDir) {
1203
1373
  const result = await client.listAgents(name);
1204
1374
  const agent = result.agents.find((a) => a.name === name);
1205
1375
  if (!agent) {
1376
+ if (shouldOutputJson()) {
1377
+ outputJson({ success: false, error: { code: "NOT_FOUND", message: `Agent "${name}" 不存在` } });
1378
+ process.exit(1);
1379
+ }
1206
1380
  error(`Agent "${name}" 不存在`);
1207
1381
  process.exit(1);
1208
1382
  }
1209
- info(`正在下载 ${name}...`);
1383
+ if (shouldOutputJson()) {
1384
+ info(`正在下载 ${name}...`);
1385
+ }
1210
1386
  const { buffer, version } = await client.downloadAgent(agent.id);
1211
1387
  const tempDir = mkdtempSync3("/tmp/agent-download-");
1212
1388
  const zipPath = join4(tempDir, `${name}.zip`);
@@ -1221,8 +1397,16 @@ async function downloadAgent(name, outputDir) {
1221
1397
  execSync3(`cp -r "${tempDir}"/* "${targetDir}/"`, { stdio: "pipe" });
1222
1398
  }
1223
1399
  rmSync3(tempDir, { recursive: true, force: true });
1400
+ if (shouldOutputJson()) {
1401
+ outputJson({ success: true, data: { path: targetDir, version } });
1402
+ return;
1403
+ }
1224
1404
  success(`已下载到 ${targetDir} (版本: ${version})`);
1225
1405
  } catch (err) {
1406
+ if (shouldOutputJson()) {
1407
+ outputJson({ success: false, error: { code: "DOWNLOAD_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1408
+ process.exit(1);
1409
+ }
1226
1410
  error(`下载失败: ${err instanceof Error ? err.message : "未知错误"}`);
1227
1411
  process.exit(1);
1228
1412
  }
@@ -1236,12 +1420,20 @@ import { mkdtempSync as mkdtempSync4, rmSync as rmSync4 } from "fs";
1236
1420
  async function listKnowledge() {
1237
1421
  const config = loadConfig();
1238
1422
  if (!config?.token) {
1423
+ if (shouldOutputJson()) {
1424
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1425
+ process.exit(1);
1426
+ }
1239
1427
  error("未登录,请先运行 arm login");
1240
1428
  process.exit(1);
1241
1429
  }
1242
1430
  const client = new ApiClient(config.serverUrl, config.token);
1243
1431
  try {
1244
1432
  const result = await client.listKnowledge();
1433
+ if (shouldOutputJson()) {
1434
+ outputJson({ success: true, data: result });
1435
+ return;
1436
+ }
1245
1437
  if (result.knowledges.length === 0) {
1246
1438
  info("暂无 Knowledge");
1247
1439
  return;
@@ -1254,6 +1446,10 @@ async function listKnowledge() {
1254
1446
  console.log("");
1255
1447
  }
1256
1448
  } catch (err) {
1449
+ if (shouldOutputJson()) {
1450
+ outputJson({ success: false, error: { code: "LIST_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1451
+ process.exit(1);
1452
+ }
1257
1453
  error(`获取列表失败: ${err instanceof Error ? err.message : "未知错误"}`);
1258
1454
  process.exit(1);
1259
1455
  }
@@ -1261,12 +1457,20 @@ async function listKnowledge() {
1261
1457
  async function searchKnowledge(keyword) {
1262
1458
  const config = loadConfig();
1263
1459
  if (!config?.token) {
1460
+ if (shouldOutputJson()) {
1461
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1462
+ process.exit(1);
1463
+ }
1264
1464
  error("未登录,请先运行 arm login");
1265
1465
  process.exit(1);
1266
1466
  }
1267
1467
  const client = new ApiClient(config.serverUrl, config.token);
1268
1468
  try {
1269
1469
  const result = await client.listKnowledge(keyword);
1470
+ if (shouldOutputJson()) {
1471
+ outputJson({ success: true, data: result });
1472
+ return;
1473
+ }
1270
1474
  if (result.knowledges.length === 0) {
1271
1475
  info(`没有找到包含 "${keyword}" 的 Knowledge`);
1272
1476
  return;
@@ -1279,6 +1483,10 @@ async function searchKnowledge(keyword) {
1279
1483
  console.log("");
1280
1484
  }
1281
1485
  } catch (err) {
1486
+ if (shouldOutputJson()) {
1487
+ outputJson({ success: false, error: { code: "SEARCH_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1488
+ process.exit(1);
1489
+ }
1282
1490
  error(`搜索失败: ${err instanceof Error ? err.message : "未知错误"}`);
1283
1491
  process.exit(1);
1284
1492
  }
@@ -1286,14 +1494,26 @@ async function searchKnowledge(keyword) {
1286
1494
  async function infoKnowledge(name) {
1287
1495
  const config = loadConfig();
1288
1496
  if (!config?.token) {
1497
+ if (shouldOutputJson()) {
1498
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1499
+ process.exit(1);
1500
+ }
1289
1501
  error("未登录,请先运行 arm login");
1290
1502
  process.exit(1);
1291
1503
  }
1292
1504
  const client = new ApiClient(config.serverUrl, config.token);
1293
1505
  try {
1294
1506
  const knowledge = await client.getKnowledge(name);
1507
+ if (shouldOutputJson()) {
1508
+ outputJson({ success: true, data: knowledge });
1509
+ return;
1510
+ }
1295
1511
  console.log(formatKnowledgeDetail(knowledge));
1296
1512
  } catch (err) {
1513
+ if (shouldOutputJson()) {
1514
+ outputJson({ success: false, error: { code: "INFO_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1515
+ process.exit(1);
1516
+ }
1297
1517
  error(`获取详情失败: ${err instanceof Error ? err.message : "未知错误"}`);
1298
1518
  process.exit(1);
1299
1519
  }
@@ -1301,17 +1521,31 @@ async function infoKnowledge(name) {
1301
1521
  async function downloadKnowledge(name, outputDir) {
1302
1522
  const config = loadConfig();
1303
1523
  if (!config?.token) {
1524
+ if (shouldOutputJson()) {
1525
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1526
+ process.exit(1);
1527
+ }
1304
1528
  error("未登录,请先运行 arm login");
1305
1529
  process.exit(1);
1306
1530
  }
1307
1531
  const client = new ApiClient(config.serverUrl, config.token);
1308
1532
  try {
1309
- info(`正在下载 ${name}...`);
1533
+ if (shouldOutputJson()) {
1534
+ info(`正在下载 ${name}...`);
1535
+ }
1310
1536
  const buffer = await client.downloadKnowledge(name);
1311
1537
  const outputPath = join5(outputDir || ".", `${name}.zip`);
1312
1538
  writeFileSync4(outputPath, Buffer.from(buffer));
1539
+ if (shouldOutputJson()) {
1540
+ outputJson({ success: true, data: { path: outputPath } });
1541
+ return;
1542
+ }
1313
1543
  success(`已下载到 ${outputPath}`);
1314
1544
  } catch (err) {
1545
+ if (shouldOutputJson()) {
1546
+ outputJson({ success: false, error: { code: "DOWNLOAD_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1547
+ process.exit(1);
1548
+ }
1315
1549
  error(`下载失败: ${err instanceof Error ? err.message : "未知错误"}`);
1316
1550
  process.exit(1);
1317
1551
  }
@@ -1319,10 +1553,18 @@ async function downloadKnowledge(name, outputDir) {
1319
1553
  async function uploadKnowledge(filePath) {
1320
1554
  const config = loadConfig();
1321
1555
  if (!config?.token) {
1556
+ if (shouldOutputJson()) {
1557
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1558
+ process.exit(1);
1559
+ }
1322
1560
  error("未登录,请先运行 arm login");
1323
1561
  process.exit(1);
1324
1562
  }
1325
1563
  if (!existsSync5(filePath)) {
1564
+ if (shouldOutputJson()) {
1565
+ outputJson({ success: false, error: { code: "FILE_NOT_FOUND", message: `上传失败: 目录不存在: ${filePath}` } });
1566
+ process.exit(1);
1567
+ }
1326
1568
  error(`上传失败: 目录不存在: ${filePath}`);
1327
1569
  process.exit(1);
1328
1570
  }
@@ -1336,10 +1578,20 @@ async function uploadKnowledge(filePath) {
1336
1578
  execSync4(`cp "${filePath}" "${zipPath}"`, { stdio: "pipe" });
1337
1579
  }
1338
1580
  const client = new ApiClient(config.serverUrl, config.token);
1339
- info(`正在上传 ${filePath}...`);
1581
+ if (shouldOutputJson()) {
1582
+ info(`正在上传 ${filePath}...`);
1583
+ }
1340
1584
  const knowledge = await client.uploadKnowledge(zipPath);
1585
+ if (shouldOutputJson()) {
1586
+ outputJson({ success: true, data: knowledge });
1587
+ return;
1588
+ }
1341
1589
  success(`上传成功! Knowledge: ${knowledge.name}`);
1342
1590
  } catch (err) {
1591
+ if (shouldOutputJson()) {
1592
+ outputJson({ success: false, error: { code: "UPLOAD_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1593
+ process.exit(1);
1594
+ }
1343
1595
  error(`上传失败: ${err instanceof Error ? err.message : "未知错误"}`);
1344
1596
  process.exit(1);
1345
1597
  } finally {
@@ -1349,12 +1601,20 @@ async function uploadKnowledge(filePath) {
1349
1601
  async function myKnowledge() {
1350
1602
  const config = loadConfig();
1351
1603
  if (!config?.token) {
1604
+ if (shouldOutputJson()) {
1605
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1606
+ process.exit(1);
1607
+ }
1352
1608
  error("未登录,请先运行 arm login");
1353
1609
  process.exit(1);
1354
1610
  }
1355
1611
  const client = new ApiClient(config.serverUrl, config.token);
1356
1612
  try {
1357
1613
  const knowledges = await client.getMyKnowledge();
1614
+ if (shouldOutputJson()) {
1615
+ outputJson({ success: true, data: knowledges });
1616
+ return;
1617
+ }
1358
1618
  if (knowledges.length === 0) {
1359
1619
  info("您还没有发布任何 Knowledge");
1360
1620
  return;
@@ -1367,6 +1627,10 @@ async function myKnowledge() {
1367
1627
  console.log("");
1368
1628
  }
1369
1629
  } catch (err) {
1630
+ if (shouldOutputJson()) {
1631
+ outputJson({ success: false, error: { code: "LIST_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1632
+ process.exit(1);
1633
+ }
1370
1634
  error(`获取列表失败: ${err instanceof Error ? err.message : "未知错误"}`);
1371
1635
  process.exit(1);
1372
1636
  }
@@ -1374,14 +1638,26 @@ async function myKnowledge() {
1374
1638
  async function deleteKnowledge(name) {
1375
1639
  const config = loadConfig();
1376
1640
  if (!config?.token) {
1641
+ if (shouldOutputJson()) {
1642
+ outputJson({ success: false, error: { code: "NOT_LOGGED_IN", message: "未登录,请先运行 arm login" } });
1643
+ process.exit(1);
1644
+ }
1377
1645
  error("未登录,请先运行 arm login");
1378
1646
  process.exit(1);
1379
1647
  }
1380
1648
  const client = new ApiClient(config.serverUrl, config.token);
1381
1649
  try {
1382
1650
  await client.deleteKnowledge(name);
1651
+ if (shouldOutputJson()) {
1652
+ outputJson({ success: true, data: { name } });
1653
+ return;
1654
+ }
1383
1655
  success(`已删除 ${name}`);
1384
1656
  } catch (err) {
1657
+ if (shouldOutputJson()) {
1658
+ outputJson({ success: false, error: { code: "DELETE_FAILED", message: err instanceof Error ? err.message : "未知错误" } });
1659
+ process.exit(1);
1660
+ }
1385
1661
  error(`删除失败: ${err instanceof Error ? err.message : "未知错误"}`);
1386
1662
  process.exit(1);
1387
1663
  }
@@ -1546,6 +1822,15 @@ async function main() {
1546
1822
  case "me":
1547
1823
  await getCurrentUser();
1548
1824
  break;
1825
+ case "output":
1826
+ if (subCommand === "json" || subCommand === "text") {
1827
+ setOutputMode(subCommand);
1828
+ console.log(`输出模式已设置为: ${subCommand}`);
1829
+ } else {
1830
+ const mode = getOutputMode();
1831
+ console.log(`当前输出模式: ${mode}`);
1832
+ }
1833
+ break;
1549
1834
  case "agent":
1550
1835
  switch (subCommand) {
1551
1836
  case "ls":
@@ -1736,6 +2021,7 @@ Agent Resource Management (arm)
1736
2021
  用法:
1737
2022
  arm login <server-url> <api-key> 登录
1738
2023
  arm logout 登出
2024
+ arm output [json|text] 设置/查看输出模式 (默认json)
1739
2025
  arm skill ls 列出所有 Skill
1740
2026
  arm skill search <keyword> 搜索 Skill
1741
2027
  arm skill info <name> 查看 Skill 详情