focalapi-cli 0.2.1 → 0.2.2
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/CHANGELOG.md +24 -17
- package/LICENSE +202 -202
- package/README.md +141 -139
- package/dist/cli.js +228 -44
- package/package.json +57 -57
- package/scripts/postinstall.cjs +41 -41
- package/skills/focalapi/SKILL.md +47 -47
- package/skills/focalapi-auth/SKILL.md +28 -28
- package/skills/focalapi-chat/SKILL.md +29 -29
- package/skills/focalapi-gen/SKILL.md +50 -48
- package/skills/focalapi-models/SKILL.md +55 -49
- package/skills/focalapi-task/SKILL.md +25 -25
- package/skills/focalapi-usage/SKILL.md +26 -26
package/dist/cli.js
CHANGED
|
@@ -155,7 +155,7 @@ function displayWidth(s) {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
// src/lib/version.ts
|
|
158
|
-
var VERSION = true ? "0.2.
|
|
158
|
+
var VERSION = true ? "0.2.2" : "0.0.0-dev";
|
|
159
159
|
|
|
160
160
|
// src/commands/auth.ts
|
|
161
161
|
import { createInterface } from "readline/promises";
|
|
@@ -471,15 +471,22 @@ var RECOMMENDED_MODELS = {
|
|
|
471
471
|
"seedream-5-0-260128",
|
|
472
472
|
"gpt-image-2",
|
|
473
473
|
"gemini-3.1-flash-image",
|
|
474
|
-
"grok-imagine-image-
|
|
474
|
+
"grok-imagine-image-2.0",
|
|
475
|
+
"kling-v3",
|
|
476
|
+
"qwen-image-3.0-pro",
|
|
477
|
+
"krea-2-large",
|
|
475
478
|
"seedream-4-5-251128"
|
|
476
479
|
],
|
|
477
480
|
video: [
|
|
478
481
|
"dreamina-seedance-2-5-260628",
|
|
479
|
-
"
|
|
482
|
+
"kling-3.0",
|
|
483
|
+
"viduq3-pro",
|
|
484
|
+
"gemini-omni-flash-preview",
|
|
480
485
|
"grok-imagine-video-1.5",
|
|
481
|
-
"
|
|
482
|
-
"
|
|
486
|
+
"ltx-2-5-fast",
|
|
487
|
+
"flux-3",
|
|
488
|
+
"MiniMax-H3",
|
|
489
|
+
"dreamina-seedance-2-0-260128"
|
|
483
490
|
]
|
|
484
491
|
};
|
|
485
492
|
function parseCreativeCapability(value) {
|
|
@@ -906,6 +913,24 @@ var GROK_IMAGE_ASPECT_RATIOS = [
|
|
|
906
913
|
"1:3",
|
|
907
914
|
"3:1"
|
|
908
915
|
];
|
|
916
|
+
var GROK_IMAGE_20_ASPECT_RATIOS = [
|
|
917
|
+
"auto",
|
|
918
|
+
"1:1",
|
|
919
|
+
"2:3",
|
|
920
|
+
"3:2",
|
|
921
|
+
"3:4",
|
|
922
|
+
"4:3",
|
|
923
|
+
"9:16",
|
|
924
|
+
"16:9",
|
|
925
|
+
"9:19.5",
|
|
926
|
+
"19.5:9",
|
|
927
|
+
"9:20",
|
|
928
|
+
"20:9",
|
|
929
|
+
"1:2",
|
|
930
|
+
"2:1"
|
|
931
|
+
];
|
|
932
|
+
var KLING_IMAGE_ASPECT_RATIOS = ["16:9", "9:16", "1:1", "4:3", "3:4", "3:2", "2:3", "21:9"];
|
|
933
|
+
var KREA_IMAGE_ASPECT_RATIOS = ["1:1", "4:3", "3:2", "16:9", "2.35:1", "4:5", "2:3", "9:16"];
|
|
909
934
|
var IMAGE_CONSTRAINTS = {
|
|
910
935
|
"gpt-image-2": {
|
|
911
936
|
defaultSize: "1024x1024",
|
|
@@ -968,52 +993,103 @@ var IMAGE_CONSTRAINTS = {
|
|
|
968
993
|
optimizePromptModes: SEEDREAM_OPTIMIZE_PROMPT_MODES
|
|
969
994
|
},
|
|
970
995
|
"grok-imagine-image-quality": {
|
|
971
|
-
defaultSize: "1024x1024",
|
|
972
996
|
maxN: 10,
|
|
973
997
|
maxReferenceImages: 3,
|
|
974
998
|
aspectRatios: GROK_IMAGE_ASPECT_RATIOS,
|
|
975
999
|
resolutions: ["1k", "2k"],
|
|
976
|
-
supportsSeed: true
|
|
1000
|
+
supportsSeed: true,
|
|
1001
|
+
maxSeed: 2147483647
|
|
977
1002
|
},
|
|
978
1003
|
"grok-imagine-image": {
|
|
979
|
-
defaultSize: "1024x1024",
|
|
980
1004
|
maxN: 10,
|
|
981
1005
|
maxReferenceImages: 3,
|
|
982
1006
|
aspectRatios: GROK_IMAGE_ASPECT_RATIOS,
|
|
983
1007
|
resolutions: ["1k", "2k"],
|
|
984
|
-
supportsSeed: true
|
|
1008
|
+
supportsSeed: true,
|
|
1009
|
+
maxSeed: 2147483647
|
|
1010
|
+
},
|
|
1011
|
+
"grok-imagine-image-2.0": {
|
|
1012
|
+
maxN: 10,
|
|
1013
|
+
maxReferenceImages: 3,
|
|
1014
|
+
aspectRatios: GROK_IMAGE_20_ASPECT_RATIOS,
|
|
1015
|
+
resolutions: ["1k", "2k"],
|
|
1016
|
+
qualities: ["low", "medium"],
|
|
1017
|
+
supportsSeed: true,
|
|
1018
|
+
maxSeed: 2147483647
|
|
1019
|
+
},
|
|
1020
|
+
"kling-v3": {
|
|
1021
|
+
maxN: 9,
|
|
1022
|
+
maxReferenceImages: 1,
|
|
1023
|
+
aspectRatios: KLING_IMAGE_ASPECT_RATIOS,
|
|
1024
|
+
supportsNegativePrompt: true
|
|
1025
|
+
},
|
|
1026
|
+
"krea-2-medium": {
|
|
1027
|
+
maxN: 1,
|
|
1028
|
+
maxReferenceImages: 0,
|
|
1029
|
+
aspectRatios: KREA_IMAGE_ASPECT_RATIOS,
|
|
1030
|
+
resolutions: ["1k"],
|
|
1031
|
+
supportsSeed: true,
|
|
1032
|
+
maxSeed: 2147483647,
|
|
1033
|
+
creativityModes: ["raw", "low", "medium", "high"],
|
|
1034
|
+
maxStyleReferences: 10,
|
|
1035
|
+
maxMoodboards: 1
|
|
1036
|
+
},
|
|
1037
|
+
"krea-2-medium-turbo": {
|
|
1038
|
+
maxN: 1,
|
|
1039
|
+
maxReferenceImages: 0,
|
|
1040
|
+
aspectRatios: KREA_IMAGE_ASPECT_RATIOS,
|
|
1041
|
+
resolutions: ["1k"],
|
|
1042
|
+
supportsSeed: true,
|
|
1043
|
+
maxSeed: 2147483647,
|
|
1044
|
+
creativityModes: ["raw", "low", "medium", "high"],
|
|
1045
|
+
maxStyleReferences: 10,
|
|
1046
|
+
maxMoodboards: 1
|
|
1047
|
+
},
|
|
1048
|
+
"krea-2-large": {
|
|
1049
|
+
maxN: 1,
|
|
1050
|
+
maxReferenceImages: 0,
|
|
1051
|
+
aspectRatios: KREA_IMAGE_ASPECT_RATIOS,
|
|
1052
|
+
resolutions: ["1k"],
|
|
1053
|
+
supportsSeed: true,
|
|
1054
|
+
maxSeed: 2147483647,
|
|
1055
|
+
creativityModes: ["raw", "low", "medium", "high"],
|
|
1056
|
+
maxStyleReferences: 10,
|
|
1057
|
+
maxMoodboards: 1
|
|
1058
|
+
},
|
|
1059
|
+
"qwen-image-3.0": {
|
|
1060
|
+
defaultSize: "1024x1024",
|
|
1061
|
+
maxN: 6,
|
|
1062
|
+
maxReferenceImages: 3,
|
|
1063
|
+
minMegapixels: 0.262144,
|
|
1064
|
+
maxMegapixels: 4.194304,
|
|
1065
|
+
maxAspectRatio: 8,
|
|
1066
|
+
supportsSeed: true,
|
|
1067
|
+
maxSeed: 2147483647,
|
|
1068
|
+
supportsNegativePrompt: true,
|
|
1069
|
+
supportsPromptExtend: true,
|
|
1070
|
+
supportsWatermark: true
|
|
1071
|
+
},
|
|
1072
|
+
"qwen-image-3.0-pro": {
|
|
1073
|
+
defaultSize: "1024x1024",
|
|
1074
|
+
maxN: 6,
|
|
1075
|
+
maxReferenceImages: 3,
|
|
1076
|
+
minMegapixels: 0.262144,
|
|
1077
|
+
maxMegapixels: 4.194304,
|
|
1078
|
+
maxAspectRatio: 8,
|
|
1079
|
+
supportsSeed: true,
|
|
1080
|
+
maxSeed: 2147483647,
|
|
1081
|
+
supportsNegativePrompt: true,
|
|
1082
|
+
supportsPromptExtend: true,
|
|
1083
|
+
supportsWatermark: true
|
|
985
1084
|
}
|
|
986
1085
|
};
|
|
987
1086
|
var SEEDANCE_RATIOS = ["adaptive", "16:9", "4:3", "1:1", "3:4", "9:16", "21:9"];
|
|
988
1087
|
var GROK_VIDEO_ASPECT_RATIOS = ["auto", "16:9", "4:3", "3:2", "1:1", "2:3", "3:4", "9:16"];
|
|
1088
|
+
var KLING_VIDEO_ASPECT_RATIOS = ["16:9", "9:16", "1:1"];
|
|
1089
|
+
var VIDU_VIDEO_ASPECT_RATIOS = ["16:9", "9:16", "3:4", "4:3", "1:1"];
|
|
1090
|
+
var MINIMAX_VIDEO_RATIOS = ["16:9", "4:3", "1:1", "3:4", "9:16", "21:9", "adaptive"];
|
|
1091
|
+
var FLUX_VIDEO_RATIOS = ["auto", "21:9", "2:1", "16:9", "4:3", "1:1", "3:4", "9:16"];
|
|
989
1092
|
var VIDEO_CONSTRAINTS = {
|
|
990
|
-
"veo-3.1-generate-preview": {
|
|
991
|
-
resolutions: ["720p", "1080p", "4k"],
|
|
992
|
-
ratios: ["16:9", "9:16"],
|
|
993
|
-
minSeconds: 4,
|
|
994
|
-
maxSeconds: 8,
|
|
995
|
-
allowedSeconds: [4, 6, 8],
|
|
996
|
-
requiredSecondsByResolution: { "1080p": 8, "4k": 8 },
|
|
997
|
-
supportsSeed: true
|
|
998
|
-
},
|
|
999
|
-
"veo-3.1-fast-generate-preview": {
|
|
1000
|
-
resolutions: ["720p", "1080p", "4k"],
|
|
1001
|
-
ratios: ["16:9", "9:16"],
|
|
1002
|
-
minSeconds: 4,
|
|
1003
|
-
maxSeconds: 8,
|
|
1004
|
-
allowedSeconds: [4, 6, 8],
|
|
1005
|
-
requiredSecondsByResolution: { "1080p": 8, "4k": 8 },
|
|
1006
|
-
supportsSeed: true
|
|
1007
|
-
},
|
|
1008
|
-
"veo-3.1-lite-generate-preview": {
|
|
1009
|
-
resolutions: ["720p", "1080p"],
|
|
1010
|
-
ratios: ["16:9", "9:16"],
|
|
1011
|
-
minSeconds: 4,
|
|
1012
|
-
maxSeconds: 8,
|
|
1013
|
-
allowedSeconds: [4, 6, 8],
|
|
1014
|
-
requiredSecondsByResolution: { "1080p": 8 },
|
|
1015
|
-
supportsSeed: true
|
|
1016
|
-
},
|
|
1017
1093
|
"dreamina-seedance-2-0-260128": {
|
|
1018
1094
|
resolutions: ["480p", "720p", "1080p", "4k"],
|
|
1019
1095
|
ratios: SEEDANCE_RATIOS,
|
|
@@ -1041,19 +1117,80 @@ var VIDEO_CONSTRAINTS = {
|
|
|
1041
1117
|
minSeconds: 4,
|
|
1042
1118
|
maxSeconds: 30
|
|
1043
1119
|
},
|
|
1120
|
+
"gemini-omni-flash-preview": {
|
|
1121
|
+
resolutions: [],
|
|
1122
|
+
ratios: ["16:9", "9:16"],
|
|
1123
|
+
minSeconds: 3,
|
|
1124
|
+
maxSeconds: 10
|
|
1125
|
+
},
|
|
1044
1126
|
"grok-imagine-video": {
|
|
1045
1127
|
resolutions: ["480p", "720p", "1080p"],
|
|
1046
1128
|
aspectRatios: GROK_VIDEO_ASPECT_RATIOS,
|
|
1047
1129
|
minSeconds: 1,
|
|
1048
1130
|
maxSeconds: 15,
|
|
1049
|
-
supportsSeed: true
|
|
1131
|
+
supportsSeed: true,
|
|
1132
|
+
maxSeed: 2147483647
|
|
1050
1133
|
},
|
|
1051
1134
|
"grok-imagine-video-1.5": {
|
|
1052
1135
|
resolutions: ["480p", "720p", "1080p"],
|
|
1053
1136
|
aspectRatios: GROK_VIDEO_ASPECT_RATIOS,
|
|
1054
1137
|
minSeconds: 1,
|
|
1055
1138
|
maxSeconds: 15,
|
|
1056
|
-
supportsSeed: true
|
|
1139
|
+
supportsSeed: true,
|
|
1140
|
+
maxSeed: 2147483647
|
|
1141
|
+
},
|
|
1142
|
+
"kling-3.0": {
|
|
1143
|
+
resolutions: ["720p", "1080p", "4k"],
|
|
1144
|
+
aspectRatios: KLING_VIDEO_ASPECT_RATIOS,
|
|
1145
|
+
minSeconds: 3,
|
|
1146
|
+
maxSeconds: 15
|
|
1147
|
+
},
|
|
1148
|
+
"viduq3-pro": {
|
|
1149
|
+
resolutions: ["720p", "1080p"],
|
|
1150
|
+
aspectRatios: VIDU_VIDEO_ASPECT_RATIOS,
|
|
1151
|
+
minSeconds: 1,
|
|
1152
|
+
maxSeconds: 16,
|
|
1153
|
+
supportsSeed: true,
|
|
1154
|
+
maxSeed: 2147483647
|
|
1155
|
+
},
|
|
1156
|
+
"viduq3-turbo": {
|
|
1157
|
+
resolutions: ["720p", "1080p"],
|
|
1158
|
+
aspectRatios: VIDU_VIDEO_ASPECT_RATIOS,
|
|
1159
|
+
minSeconds: 1,
|
|
1160
|
+
maxSeconds: 16,
|
|
1161
|
+
supportsSeed: true,
|
|
1162
|
+
maxSeed: 2147483647
|
|
1163
|
+
},
|
|
1164
|
+
"MiniMax-H3": {
|
|
1165
|
+
resolutions: ["768p", "2k"],
|
|
1166
|
+
ratios: MINIMAX_VIDEO_RATIOS,
|
|
1167
|
+
minSeconds: 5,
|
|
1168
|
+
maxSeconds: 15
|
|
1169
|
+
},
|
|
1170
|
+
"ltx-2-5-fast": {
|
|
1171
|
+
resolutions: ["1280x720", "720x1280", "1920x1080", "1080x1920", "2560x1440", "1440x2560", "3840x2160", "2160x3840"],
|
|
1172
|
+
minSeconds: 2,
|
|
1173
|
+
maxSeconds: 20,
|
|
1174
|
+
allowedSeconds: [2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18, 20],
|
|
1175
|
+
supportsSeed: true,
|
|
1176
|
+
maxSeed: 4294967295,
|
|
1177
|
+
allowedFps: [24, 25, 48, 50]
|
|
1178
|
+
},
|
|
1179
|
+
"ltx-2-5-pro": {
|
|
1180
|
+
resolutions: ["1280x720", "720x1280", "1920x1080", "1080x1920"],
|
|
1181
|
+
minSeconds: 2,
|
|
1182
|
+
maxSeconds: 10,
|
|
1183
|
+
allowedSeconds: [2, 3, 4, 5, 6, 8, 10],
|
|
1184
|
+
supportsSeed: true,
|
|
1185
|
+
maxSeed: 4294967295,
|
|
1186
|
+
allowedFps: [24, 25, 50]
|
|
1187
|
+
},
|
|
1188
|
+
"flux-3": {
|
|
1189
|
+
resolutions: ["hd", "fhd"],
|
|
1190
|
+
ratios: FLUX_VIDEO_RATIOS,
|
|
1191
|
+
minSeconds: 5,
|
|
1192
|
+
maxSeconds: 20,
|
|
1193
|
+
safetyTolerance: { minimum: 0, maximum: 4 }
|
|
1057
1194
|
}
|
|
1058
1195
|
};
|
|
1059
1196
|
var COMMON_GEMINI_RATIOS = ["auto", "1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"];
|
|
@@ -1113,17 +1250,40 @@ function validateImageGeneration(model, input) {
|
|
|
1113
1250
|
validateOptionalChoice(model, "resolution", input.resolution, constraint.resolutions);
|
|
1114
1251
|
validateOptionalChoice(model, "output_format", input.outputFormat, constraint.outputFormats);
|
|
1115
1252
|
validateOptionalChoice(model, "optimize_prompt", input.optimizePrompt, constraint.optimizePromptModes);
|
|
1253
|
+
validateOptionalChoice(model, "creativity", input.creativity, constraint.creativityModes);
|
|
1254
|
+
if (input.negativePrompt !== void 0 && !constraint.supportsNegativePrompt) {
|
|
1255
|
+
throw new ApiError("invalid_request", `${model} does not support negative_prompt`);
|
|
1256
|
+
}
|
|
1257
|
+
if (input.negativePrompt !== void 0 && model === "kling-v3" && (input.imageCount ?? 0) > 0) {
|
|
1258
|
+
throw new ApiError("invalid_request", "kling-v3 negative_prompt cannot be combined with an image input");
|
|
1259
|
+
}
|
|
1260
|
+
if (input.promptExtend !== void 0 && !constraint.supportsPromptExtend) {
|
|
1261
|
+
throw new ApiError("invalid_request", `${model} does not support prompt_extend`);
|
|
1262
|
+
}
|
|
1263
|
+
if (input.styleReferenceCount !== void 0 && (constraint.maxStyleReferences === void 0 || input.styleReferenceCount > constraint.maxStyleReferences)) {
|
|
1264
|
+
throw new ApiError("invalid_request", `${model} supports at most ${constraint.maxStyleReferences ?? 0} image style references`);
|
|
1265
|
+
}
|
|
1266
|
+
if (input.moodboardCount !== void 0 && (constraint.maxMoodboards === void 0 || input.moodboardCount > constraint.maxMoodboards)) {
|
|
1267
|
+
throw new ApiError("invalid_request", `${model} supports at most ${constraint.maxMoodboards ?? 0} moodboards`);
|
|
1268
|
+
}
|
|
1116
1269
|
if (input.seed !== void 0) {
|
|
1117
1270
|
if (!constraint.supportsSeed) {
|
|
1118
1271
|
throw new ApiError("invalid_request", `${model} does not support seed`);
|
|
1119
1272
|
}
|
|
1120
|
-
if (!Number.isInteger(input.seed) || input.seed < 0) {
|
|
1121
|
-
|
|
1273
|
+
if (!Number.isInteger(input.seed) || input.seed < 0 || constraint.maxSeed !== void 0 && input.seed > constraint.maxSeed) {
|
|
1274
|
+
const maximum = constraint.maxSeed === void 0 ? "" : ` no greater than ${constraint.maxSeed}`;
|
|
1275
|
+
throw new ApiError("invalid_request", `seed must be a non-negative integer${maximum}`);
|
|
1122
1276
|
}
|
|
1123
1277
|
}
|
|
1124
1278
|
if (input.watermark !== void 0 && !constraint.supportsWatermark) {
|
|
1125
1279
|
throw new ApiError("invalid_request", `${model} does not support watermark`);
|
|
1126
1280
|
}
|
|
1281
|
+
if (!constraint.defaultSize) {
|
|
1282
|
+
if (input.size) {
|
|
1283
|
+
throw new ApiError("invalid_request", `${model} does not support size; use its aspect_ratio or resolution parameter`);
|
|
1284
|
+
}
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1127
1287
|
const suppliedSize = input.size ?? constraint.defaultSize;
|
|
1128
1288
|
if (constraint.sizeTiers?.includes(suppliedSize.toLowerCase())) return;
|
|
1129
1289
|
if (constraint.sizeTiers && !/^\d+x\d+$/i.test(suppliedSize)) {
|
|
@@ -1210,10 +1370,18 @@ function validateVideoGeneration(model, input) {
|
|
|
1210
1370
|
if (!constraint.supportsSeed) {
|
|
1211
1371
|
throw new ApiError("invalid_request", `${model} does not support seed`);
|
|
1212
1372
|
}
|
|
1213
|
-
if (!Number.isInteger(input.seed) || input.seed < 0) {
|
|
1214
|
-
|
|
1373
|
+
if (!Number.isInteger(input.seed) || input.seed < 0 || constraint.maxSeed !== void 0 && input.seed > constraint.maxSeed) {
|
|
1374
|
+
const maximum = constraint.maxSeed === void 0 ? "" : ` no greater than ${constraint.maxSeed}`;
|
|
1375
|
+
throw new ApiError("invalid_request", `seed must be a non-negative integer${maximum}`);
|
|
1215
1376
|
}
|
|
1216
1377
|
}
|
|
1378
|
+
if (input.fps !== void 0 && (!constraint.allowedFps || !constraint.allowedFps.includes(input.fps))) {
|
|
1379
|
+
throw new ApiError("invalid_request", `${model} fps must be one of ${constraint.allowedFps?.join(", ") ?? "none"} (received: ${input.fps})`);
|
|
1380
|
+
}
|
|
1381
|
+
if (input.safetyTolerance !== void 0 && (!constraint.safetyTolerance || !Number.isInteger(input.safetyTolerance) || input.safetyTolerance < constraint.safetyTolerance.minimum || input.safetyTolerance > constraint.safetyTolerance.maximum)) {
|
|
1382
|
+
const range = constraint.safetyTolerance ? `${constraint.safetyTolerance.minimum}-${constraint.safetyTolerance.maximum}` : "unsupported";
|
|
1383
|
+
throw new ApiError("invalid_request", `${model} safety_tolerance must be ${range} (received: ${input.safetyTolerance})`);
|
|
1384
|
+
}
|
|
1217
1385
|
if (input.priority !== void 0 && !constraint.supportsPriority) {
|
|
1218
1386
|
throw new ApiError("invalid_request", `${model} does not support priority`);
|
|
1219
1387
|
}
|
|
@@ -1470,12 +1638,14 @@ function extractGeminiImageItems(response) {
|
|
|
1470
1638
|
}
|
|
1471
1639
|
function registerGen(program) {
|
|
1472
1640
|
const gen = program.command("gen").description("\u56FE\u50CF / \u89C6\u9891\u751F\u6210");
|
|
1473
|
-
gen.command("image").description("\u751F\u6210\u56FE\u50CF\uFF08\u7701\u7565 --model \u65F6\u81EA\u52A8\u9009\u62E9\u5F53\u524D\u53EF\u7528\u9ED8\u8BA4\u6A21\u578B\uFF09").argument("<prompt...>", "\u63D0\u793A\u8BCD").option("-m, --model <model>", "\u56FE\u50CF\u6A21\u578B ID\uFF1B\u7701\u7565\u65F6\u7531 focalapi \u81EA\u52A8\u9009\u62E9").option("--size <size>", "\u5C3A\u5BF8\uFF0C\u5982 1024x1024").option("--aspect-ratio <ratio>", "\u539F\u751F\u753B\u9762\u6BD4\u4F8B\
|
|
1641
|
+
gen.command("image").description("\u751F\u6210\u56FE\u50CF\uFF08\u7701\u7565 --model \u65F6\u81EA\u52A8\u9009\u62E9\u5F53\u524D\u53EF\u7528\u9ED8\u8BA4\u6A21\u578B\uFF09").argument("<prompt...>", "\u63D0\u793A\u8BCD").option("-m, --model <model>", "\u56FE\u50CF\u6A21\u578B ID\uFF1B\u7701\u7565\u65F6\u7531 focalapi \u81EA\u52A8\u9009\u62E9").option("--size <size>", "\u5C3A\u5BF8\uFF0C\u5982 1024x1024").option("--aspect-ratio <ratio>", "\u6A21\u578B\u539F\u751F\u753B\u9762\u6BD4\u4F8B\uFF0C\u5982 16:9").option("--resolution <resolution>", "\u6A21\u578B\u539F\u751F\u8F93\u51FA\u6863\u4F4D\uFF0C\u5982 1k\u30012k").option("--seed <n>", "\u6A21\u578B\u968F\u673A\u79CD\u5B50\uFF08\u975E\u8D1F\u6574\u6570\uFF09", (v) => Number.parseInt(v, 10)).option("--quality <quality>", "\u56FE\u50CF\u8D28\u91CF\u6863\u4F4D\uFF08\u4EC5\u652F\u6301\u8BE5\u53C2\u6570\u7684\u6A21\u578B\u751F\u6548\uFF09").option("--background <background>", "\u80CC\u666F\u6A21\u5F0F\uFF08\u4EC5 gpt-image-2 \u652F\u6301 auto/opaque\uFF09").option("--negative-prompt <text>", "\u8D1F\u9762\u63D0\u793A\u8BCD\uFF08\u4EC5\u652F\u6301\u8BE5\u53C2\u6570\u7684\u6A21\u578B\u751F\u6548\uFF09").option("--creativity <level>", "\u63D0\u793A\u8BCD\u6269\u5C55\u5F3A\u5EA6\uFF0C\u5982 raw\u3001low\u3001medium\u3001high").option("--prompt-extend <boolean>", "\u662F\u5426\u6269\u5C55\u63D0\u793A\u8BCD\uFF08\u53EA\u63A5\u53D7 true \u6216 false\uFF09", (v) => parseBooleanOption(v, "prompt-extend")).option("--style-references <json>", "Krea image_style_references JSON \u6570\u7EC4").option("--moodboards <json>", "Krea moodboards JSON \u6570\u7EC4").option("--watermark <boolean>", "\u662F\u5426\u6DFB\u52A0\u6C34\u5370\uFF08\u4EC5\u652F\u6301\u8BE5\u53C2\u6570\u7684\u6A21\u578B\u751F\u6548\uFF09", (v) => parseBooleanOption(v, "watermark")).option("--output-format <format>", "\u8F93\u51FA\u683C\u5F0F\uFF08\u4EC5 Seedream\uFF1Apng \u6216 jpeg\uFF09").option("--optimize-prompt <mode>", "\u63D0\u793A\u8BCD\u4F18\u5316\uFF08\u4EC5 Seedream\uFF1Aauto\u3001enabled \u6216 disabled\uFF09").option("--image <url...>", "\u53C2\u8003\u56FE\u6216\u7F16\u8F91\u56FE URL\uFF0C\u53EF\u591A\u4E2A").option("--mask <url>", "\u7F16\u8F91 mask URL\uFF08gpt-image-2 \u9700\u8981\u5355\u5F20\u53C2\u8003\u56FE\uFF09").option("--response-format <format>", "\u56FE\u50CF\u54CD\u5E94\u683C\u5F0F\uFF1Aurl \u6216 b64_json").option("--n <count>", "\u5F20\u6570\uFF081\u2013128\uFF09", (v) => Number.parseInt(v, 10), 1).option("--no-wait", "\u63D0\u4EA4\u540E\u7ACB\u5373\u8FD4\u56DE task_id\uFF0C\u4E0D\u7B49\u5F85\u56FE\u50CF\u751F\u6210\u5B8C\u6210").option("-o, --out <dir>", "\u8F93\u51FA\u76EE\u5F55", DEFAULT_OUT_DIR).action(async (promptParts, opts, cmd) => {
|
|
1474
1642
|
const g = cmd.optsWithGlobals();
|
|
1475
1643
|
const auth = resolveAuth(g);
|
|
1476
1644
|
const model = opts.model ?? (await resolveCreativeModel(auth, "image")).model.id;
|
|
1477
1645
|
if (!opts.model && !g.json) info(`\u5DF2\u81EA\u52A8\u9009\u62E9\u56FE\u50CF\u6A21\u578B\uFF1A${model}`);
|
|
1478
1646
|
const n = clampInt(opts.n, 1, MAX_IMAGE_N, "n");
|
|
1647
|
+
const styleReferences = opts.styleReferences ? parseJsonArray(opts.styleReferences, "style-references") : void 0;
|
|
1648
|
+
const moodboards = opts.moodboards ? parseJsonArray(opts.moodboards, "moodboards") : void 0;
|
|
1479
1649
|
validateImageGeneration(model, {
|
|
1480
1650
|
n,
|
|
1481
1651
|
size: opts.size,
|
|
@@ -1487,6 +1657,11 @@ function registerGen(program) {
|
|
|
1487
1657
|
watermark: opts.watermark,
|
|
1488
1658
|
outputFormat: opts.outputFormat,
|
|
1489
1659
|
optimizePrompt: opts.optimizePrompt,
|
|
1660
|
+
negativePrompt: opts.negativePrompt,
|
|
1661
|
+
creativity: opts.creativity,
|
|
1662
|
+
promptExtend: opts.promptExtend,
|
|
1663
|
+
styleReferenceCount: styleReferences?.length,
|
|
1664
|
+
moodboardCount: moodboards?.length,
|
|
1490
1665
|
responseFormat: opts.responseFormat,
|
|
1491
1666
|
imageCount: opts.image?.length,
|
|
1492
1667
|
hasMask: Boolean(opts.mask)
|
|
@@ -1501,6 +1676,11 @@ function registerGen(program) {
|
|
|
1501
1676
|
if (opts.seed !== void 0) body.seed = opts.seed;
|
|
1502
1677
|
if (opts.quality) body.quality = opts.quality;
|
|
1503
1678
|
if (opts.background) body.background = opts.background;
|
|
1679
|
+
if (opts.negativePrompt) body.negative_prompt = opts.negativePrompt;
|
|
1680
|
+
if (opts.creativity) body.creativity = opts.creativity.toLowerCase();
|
|
1681
|
+
if (opts.promptExtend !== void 0) body.prompt_extend = opts.promptExtend;
|
|
1682
|
+
if (styleReferences) body.image_style_references = styleReferences;
|
|
1683
|
+
if (moodboards) body.moodboards = moodboards;
|
|
1504
1684
|
if (opts.watermark !== void 0) body.watermark = opts.watermark;
|
|
1505
1685
|
if (opts.outputFormat) body.output_format = opts.outputFormat.toLowerCase();
|
|
1506
1686
|
if (opts.optimizePrompt) body.optimize_prompt_options = { thinking: opts.optimizePrompt.toLowerCase() };
|
|
@@ -1644,7 +1824,7 @@ function registerGen(program) {
|
|
|
1644
1824
|
if (res.id) info(`\u4EA4\u4E92 ID\uFF1A${res.id}`);
|
|
1645
1825
|
}
|
|
1646
1826
|
});
|
|
1647
|
-
gen.command("video").description("\u751F\u6210\u89C6\u9891\uFF08\u7701\u7565 --model \u65F6\u81EA\u52A8\u9009\u62E9\u5F53\u524D\u53EF\u7528\u9ED8\u8BA4\u6A21\u578B\uFF09").argument("<prompt...>", "\u63D0\u793A\u8BCD").option("-m, --model <model>", "\u89C6\u9891\u6A21\u578B ID\uFF1B\u7701\u7565\u65F6\u7531 focalapi \u81EA\u52A8\u9009\u62E9").option("--seconds <n>", "\u65F6\u957F\u79D2\u6570\uFF1B\u7CBE\u786E\u8303\u56F4\u8FD0\u884C focalapi models get <model> \u67E5\u770B", (v) => Number.parseInt(v, 10)).option("--size <size>", "\u5206\u8FA8\u7387\uFF0C\u5982 1280x720").option("--resolution <resolution>", "\u539F\u751F\u8F93\u51FA\u5206\u8FA8\u7387\uFF0C\u5982 480p\u3001720p\u30011080p\u30014k").option("--ratio <ratio>", "\u539F\u751F\u5BBD\u9AD8\u6BD4\uFF0C\u5982 16:9\u30019:16\u3001adaptive").option("--aspect-ratio <ratio>", "
|
|
1827
|
+
gen.command("video").description("\u751F\u6210\u89C6\u9891\uFF08\u7701\u7565 --model \u65F6\u81EA\u52A8\u9009\u62E9\u5F53\u524D\u53EF\u7528\u9ED8\u8BA4\u6A21\u578B\uFF09").argument("<prompt...>", "\u63D0\u793A\u8BCD").option("-m, --model <model>", "\u89C6\u9891\u6A21\u578B ID\uFF1B\u7701\u7565\u65F6\u7531 focalapi \u81EA\u52A8\u9009\u62E9").option("--seconds <n>", "\u65F6\u957F\u79D2\u6570\uFF1B\u7CBE\u786E\u8303\u56F4\u8FD0\u884C focalapi models get <model> \u67E5\u770B", (v) => Number.parseInt(v, 10)).option("--size <size>", "\u5206\u8FA8\u7387\uFF0C\u5982 1280x720").option("--resolution <resolution>", "\u539F\u751F\u8F93\u51FA\u5206\u8FA8\u7387\uFF0C\u5982 480p\u3001720p\u30011080p\u30014k").option("--ratio <ratio>", "\u539F\u751F\u5BBD\u9AD8\u6BD4\uFF0C\u5982 16:9\u30019:16\u3001adaptive").option("--aspect-ratio <ratio>", "\u6A21\u578B\u539F\u751F\u753B\u9762\u6BD4\u4F8B\uFF0C\u5982 16:9\u30019:16\u3001auto").option("--seed <n>", "\u6A21\u578B\u968F\u673A\u79CD\u5B50\uFF08\u975E\u8D1F\u6574\u6570\uFF09", (v) => Number.parseInt(v, 10)).option("--fps <n>", "\u8F93\u51FA\u5E27\u7387\uFF08\u4EC5\u652F\u6301\u8BE5\u53C2\u6570\u7684\u6A21\u578B\u751F\u6548\uFF09", (v) => Number.parseInt(v, 10)).option("--safety-tolerance <n>", "\u5B89\u5168\u5BB9\u5FCD\u5EA6\uFF08\u4EC5\u652F\u6301\u8BE5\u53C2\u6570\u7684\u6A21\u578B\u751F\u6548\uFF09", (v) => Number.parseInt(v, 10)).option("--image <url...>", "\u56FE\u751F\u89C6\u9891\u7684\u6E90\u56FE\u50CF URL\uFF0C\u53EF\u591A\u4E2A").option("--generate-audio <boolean>", "\u662F\u5426\u751F\u6210\u97F3\u9891\uFF08\u53EA\u63A5\u53D7 true \u6216 false\uFF09", (v) => parseBooleanOption(v, "generate-audio")).option("--watermark <boolean>", "\u662F\u5426\u6DFB\u52A0\u6C34\u5370\uFF08\u53EA\u63A5\u53D7 true \u6216 false\uFF09", (v) => parseBooleanOption(v, "watermark")).option("--service-tier <tier>", "\u670D\u52A1\u5C42\u7EA7\uFF08Seedance 2.0 \u9ED8\u8BA4 default\uFF09").option("--priority <n>", "\u4EFB\u52A1\u4F18\u5148\u7EA7\uFF08\u4EC5 Seedance 2.0 \u7CFB\u5217\uFF09", (v) => Number.parseInt(v, 10)).option("--callback-url <url>", "\u4EFB\u52A1\u5B8C\u6210\u56DE\u8C03 URL").option("--return-last-frame <boolean>", "\u662F\u5426\u8FD4\u56DE\u6700\u540E\u4E00\u5E27\uFF08\u53EA\u63A5\u53D7 true \u6216 false\uFF09", (v) => parseBooleanOption(v, "return-last-frame")).option("--execution-expires-after <seconds>", "\u4EFB\u52A1\u8FC7\u671F\u79D2\u6570\uFF083600\u2013259200\uFF09", (v) => Number.parseInt(v, 10)).option("--safety-identifier <identifier>", "Seedance \u5B89\u5168\u6807\u8BC6\u7B26\uFF081\u201364 \u4E2A\u53EF\u6253\u5370 ASCII \u5B57\u7B26\uFF09").option("--no-wait", "\u63D0\u4EA4\u540E\u7ACB\u5373\u8FD4\u56DE task_id\uFF0C\u4E0D\u7B49\u5F85\u5B8C\u6210").option("--poll-interval <ms>", "\u8F6E\u8BE2\u95F4\u9694\u6BEB\u79D2", (v) => Number.parseInt(v, 10), 5e3).option("--timeout <minutes>", "\u6700\u957F\u7B49\u5F85\u5206\u949F", (v) => Number.parseInt(v, 10), 30).option("-o, --out <dir>", "\u8F93\u51FA\u76EE\u5F55", DEFAULT_OUT_DIR).option("--content <json>", "Ark-compatible content JSON array; overrides prompt/image facade fields").action(
|
|
1648
1828
|
async (promptParts, opts, cmd) => {
|
|
1649
1829
|
const g = cmd.optsWithGlobals();
|
|
1650
1830
|
const auth = resolveAuth(g);
|
|
@@ -1662,6 +1842,8 @@ function registerGen(program) {
|
|
|
1662
1842
|
if (opts.ratio) metadata.ratio = opts.ratio;
|
|
1663
1843
|
if (opts.aspectRatio) metadata.ratio = opts.aspectRatio;
|
|
1664
1844
|
if (opts.seed !== void 0) metadata.seed = opts.seed;
|
|
1845
|
+
if (opts.fps !== void 0) metadata.fps = opts.fps;
|
|
1846
|
+
if (opts.safetyTolerance !== void 0) metadata.safety_tolerance = opts.safetyTolerance;
|
|
1665
1847
|
if (opts.generateAudio !== void 0) metadata.generate_audio = opts.generateAudio;
|
|
1666
1848
|
if (opts.watermark !== void 0) metadata.watermark = opts.watermark;
|
|
1667
1849
|
if (opts.serviceTier) metadata.service_tier = opts.serviceTier;
|
|
@@ -1677,6 +1859,8 @@ function registerGen(program) {
|
|
|
1677
1859
|
ratio: opts.ratio,
|
|
1678
1860
|
aspectRatio: opts.aspectRatio,
|
|
1679
1861
|
seed: opts.seed,
|
|
1862
|
+
fps: opts.fps,
|
|
1863
|
+
safetyTolerance: opts.safetyTolerance,
|
|
1680
1864
|
serviceTier: opts.serviceTier,
|
|
1681
1865
|
priority: opts.priority,
|
|
1682
1866
|
executionExpiresAfter: opts.executionExpiresAfter,
|
package/package.json
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "focalapi-cli",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "让任意 AI Agent 直接调用 focalapi 创作模型的命令行工具",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"focalapi": "dist/cli.js"
|
|
8
|
-
},
|
|
9
|
-
"files": [
|
|
10
|
-
"dist",
|
|
11
|
-
"scripts",
|
|
12
|
-
"skills",
|
|
13
|
-
"README.md",
|
|
14
|
-
"CHANGELOG.md",
|
|
15
|
-
"LICENSE"
|
|
16
|
-
],
|
|
17
|
-
"engines": {
|
|
18
|
-
"node": ">=18"
|
|
19
|
-
},
|
|
20
|
-
"scripts": {
|
|
21
|
-
"dev": "tsx src/cli.ts",
|
|
22
|
-
"build": "tsup",
|
|
23
|
-
"test": "vitest run",
|
|
24
|
-
"test:watch": "vitest",
|
|
25
|
-
"typecheck": "tsc --noEmit",
|
|
26
|
-
"postinstall": "node scripts/postinstall.cjs",
|
|
27
|
-
"prepublishOnly": "npm run build && npm test"
|
|
28
|
-
},
|
|
29
|
-
"keywords": [
|
|
30
|
-
"focalapi",
|
|
31
|
-
"ai",
|
|
32
|
-
"agent",
|
|
33
|
-
"cli",
|
|
34
|
-
"llm",
|
|
35
|
-
"image-generation",
|
|
36
|
-
"video-generation"
|
|
37
|
-
],
|
|
38
|
-
"license": "Apache-2.0",
|
|
39
|
-
"repository": {
|
|
40
|
-
"type": "git",
|
|
41
|
-
"url": "git+https://github.com/focalapi/focalapi-cli.git"
|
|
42
|
-
},
|
|
43
|
-
"homepage": "https://github.com/focalapi/focalapi-cli#readme",
|
|
44
|
-
"bugs": {
|
|
45
|
-
"url": "https://github.com/focalapi/focalapi-cli/issues"
|
|
46
|
-
},
|
|
47
|
-
"dependencies": {
|
|
48
|
-
"commander": "^12.1.0"
|
|
49
|
-
},
|
|
50
|
-
"devDependencies": {
|
|
51
|
-
"@types/node": "^20.11.0",
|
|
52
|
-
"tsup": "^8.2.4",
|
|
53
|
-
"tsx": "^4.19.0",
|
|
54
|
-
"typescript": "^5.5.4",
|
|
55
|
-
"vitest": "^2.1.9"
|
|
56
|
-
}
|
|
57
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "focalapi-cli",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "让任意 AI Agent 直接调用 focalapi 创作模型的命令行工具",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"focalapi": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"scripts",
|
|
12
|
+
"skills",
|
|
13
|
+
"README.md",
|
|
14
|
+
"CHANGELOG.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"dev": "tsx src/cli.ts",
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"postinstall": "node scripts/postinstall.cjs",
|
|
27
|
+
"prepublishOnly": "npm run build && npm test"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"focalapi",
|
|
31
|
+
"ai",
|
|
32
|
+
"agent",
|
|
33
|
+
"cli",
|
|
34
|
+
"llm",
|
|
35
|
+
"image-generation",
|
|
36
|
+
"video-generation"
|
|
37
|
+
],
|
|
38
|
+
"license": "Apache-2.0",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/focalapi/focalapi-cli.git"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/focalapi/focalapi-cli#readme",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/focalapi/focalapi-cli/issues"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"commander": "^12.1.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^20.11.0",
|
|
52
|
+
"tsup": "^8.2.4",
|
|
53
|
+
"tsx": "^4.19.0",
|
|
54
|
+
"typescript": "^5.5.4",
|
|
55
|
+
"vitest": "^2.1.9"
|
|
56
|
+
}
|
|
57
|
+
}
|
package/scripts/postinstall.cjs
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Best-effort Agent integration after global npm installation.
|
|
5
|
-
*
|
|
6
|
-
* Run local connect only: do not access the network, read an API key, or change an Agent provider.
|
|
7
|
-
* Missing Agents or integration failures never fail CLI installation; users can run focalapi connect later.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const { existsSync } = require('node:fs');
|
|
11
|
-
const { join } = require('node:path');
|
|
12
|
-
const { spawnSync } = require('node:child_process');
|
|
13
|
-
|
|
14
|
-
if (process.env.FOCALAPI_SKIP_POSTINSTALL === '1' || process.env.CI === '1' || process.env.CI === 'true') {
|
|
15
|
-
process.exit(0);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const cli = join(__dirname, '..', 'dist', 'cli.js');
|
|
19
|
-
if (!existsSync(cli)) process.exit(0);
|
|
20
|
-
|
|
21
|
-
const result = spawnSync(process.execPath, [cli, 'connect', 'install', '--json'], {
|
|
22
|
-
encoding: 'utf8',
|
|
23
|
-
env: process.env,
|
|
24
|
-
windowsHide: true,
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
if (result.status === 0) {
|
|
28
|
-
try {
|
|
29
|
-
const output = JSON.parse(result.stdout || '{}');
|
|
30
|
-
const count = Array.isArray(output.installed) ? output.installed.length : 0;
|
|
31
|
-
if (count > 0) console.log(`focalapi-cli: 已自动接入 ${count} 个 Agent Skills 目录;重启 Agent 后生效。`);
|
|
32
|
-
} catch {
|
|
33
|
-
// Unparseable output after a successful connect must not fail installation.
|
|
34
|
-
}
|
|
35
|
-
process.exit(0);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (!String(result.stderr).includes('未检测到本机 Agent')) {
|
|
39
|
-
console.warn('focalapi-cli: Agent Skills 自动接入未完成;请稍后运行 `focalapi connect`。');
|
|
40
|
-
}
|
|
41
|
-
process.exit(0);
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Best-effort Agent integration after global npm installation.
|
|
5
|
+
*
|
|
6
|
+
* Run local connect only: do not access the network, read an API key, or change an Agent provider.
|
|
7
|
+
* Missing Agents or integration failures never fail CLI installation; users can run focalapi connect later.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { existsSync } = require('node:fs');
|
|
11
|
+
const { join } = require('node:path');
|
|
12
|
+
const { spawnSync } = require('node:child_process');
|
|
13
|
+
|
|
14
|
+
if (process.env.FOCALAPI_SKIP_POSTINSTALL === '1' || process.env.CI === '1' || process.env.CI === 'true') {
|
|
15
|
+
process.exit(0);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const cli = join(__dirname, '..', 'dist', 'cli.js');
|
|
19
|
+
if (!existsSync(cli)) process.exit(0);
|
|
20
|
+
|
|
21
|
+
const result = spawnSync(process.execPath, [cli, 'connect', 'install', '--json'], {
|
|
22
|
+
encoding: 'utf8',
|
|
23
|
+
env: process.env,
|
|
24
|
+
windowsHide: true,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (result.status === 0) {
|
|
28
|
+
try {
|
|
29
|
+
const output = JSON.parse(result.stdout || '{}');
|
|
30
|
+
const count = Array.isArray(output.installed) ? output.installed.length : 0;
|
|
31
|
+
if (count > 0) console.log(`focalapi-cli: 已自动接入 ${count} 个 Agent Skills 目录;重启 Agent 后生效。`);
|
|
32
|
+
} catch {
|
|
33
|
+
// Unparseable output after a successful connect must not fail installation.
|
|
34
|
+
}
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!String(result.stderr).includes('未检测到本机 Agent')) {
|
|
39
|
+
console.warn('focalapi-cli: Agent Skills 自动接入未完成;请稍后运行 `focalapi connect`。');
|
|
40
|
+
}
|
|
41
|
+
process.exit(0);
|