seacloud-sdk 0.9.8 → 0.10.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/cli.js +266 -0
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +210 -1
- package/dist/index.js +74 -1
- package/dist/index.js.map +1 -1
- package/package.json +19 -4
package/dist/cli.js
CHANGED
|
@@ -588,6 +588,73 @@ async function appSearch(params) {
|
|
|
588
588
|
throw error;
|
|
589
589
|
}
|
|
590
590
|
}
|
|
591
|
+
|
|
592
|
+
// src/api/scan.ts
|
|
593
|
+
async function scan(params) {
|
|
594
|
+
if (!params.uri && !params.img_base64) {
|
|
595
|
+
throw new SeacloudError("\u5FC5\u987B\u63D0\u4F9B uri \u6216 img_base64 \u4E2D\u7684\u81F3\u5C11\u4E00\u4E2A\u53C2\u6570");
|
|
596
|
+
}
|
|
597
|
+
if (params.is_video === 1 && params.img_base64) {
|
|
598
|
+
throw new SeacloudError("\u89C6\u9891\u68C0\u6D4B\u4E0D\u652F\u6301 base64 \u8F93\u5165\uFF0C\u5FC5\u987B\u4F7F\u7528 uri \u53C2\u6570");
|
|
599
|
+
}
|
|
600
|
+
if (!params.risk_types || params.risk_types.length === 0) {
|
|
601
|
+
throw new SeacloudError("\u5FC5\u987B\u63D0\u4F9B\u81F3\u5C11\u4E00\u4E2A\u98CE\u9669\u7C7B\u578B");
|
|
602
|
+
}
|
|
603
|
+
const client = getClient();
|
|
604
|
+
const config = client.getConfig();
|
|
605
|
+
const url = `${config.baseUrl}/scan`;
|
|
606
|
+
const token = await getApiToken(config.apiKey);
|
|
607
|
+
const controller = new AbortController();
|
|
608
|
+
const timeoutId = setTimeout(() => controller.abort(), config.timeout);
|
|
609
|
+
try {
|
|
610
|
+
const response = await config.fetch(url, {
|
|
611
|
+
method: "POST",
|
|
612
|
+
headers: {
|
|
613
|
+
"Content-Type": "application/json",
|
|
614
|
+
"Authorization": `Bearer ${token}`
|
|
615
|
+
},
|
|
616
|
+
body: JSON.stringify(params),
|
|
617
|
+
signal: controller.signal
|
|
618
|
+
});
|
|
619
|
+
clearTimeout(timeoutId);
|
|
620
|
+
if (!response.ok) {
|
|
621
|
+
const errorBody = await response.text();
|
|
622
|
+
throw new SeacloudError(
|
|
623
|
+
`HTTP ${response.status}: ${errorBody}`,
|
|
624
|
+
response.status,
|
|
625
|
+
errorBody
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
const responseData = await response.json();
|
|
629
|
+
let result;
|
|
630
|
+
if (responseData.success !== void 0 && responseData.data) {
|
|
631
|
+
result = responseData.data;
|
|
632
|
+
} else {
|
|
633
|
+
result = responseData;
|
|
634
|
+
}
|
|
635
|
+
if (!result.ok) {
|
|
636
|
+
throw new SeacloudError(
|
|
637
|
+
`\u5185\u5BB9\u5B89\u5168\u68C0\u6D4B\u4E1A\u52A1\u9519\u8BEF: ${result.error || "\u672A\u77E5\u9519\u8BEF"}`,
|
|
638
|
+
void 0,
|
|
639
|
+
result
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
return result;
|
|
643
|
+
} catch (error) {
|
|
644
|
+
clearTimeout(timeoutId);
|
|
645
|
+
if (error instanceof SeacloudError) {
|
|
646
|
+
throw error;
|
|
647
|
+
}
|
|
648
|
+
if (error.name === "AbortError") {
|
|
649
|
+
throw new SeacloudError(`Request timeout after ${config.timeout}ms`);
|
|
650
|
+
}
|
|
651
|
+
throw new SeacloudError(
|
|
652
|
+
`Request failed: ${error.message}`,
|
|
653
|
+
void 0,
|
|
654
|
+
error
|
|
655
|
+
);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
591
658
|
var __filename$1 = fileURLToPath(import.meta.url);
|
|
592
659
|
dirname(__filename$1);
|
|
593
660
|
function showHelp() {
|
|
@@ -601,6 +668,8 @@ Commands:
|
|
|
601
668
|
llm <prompt> Chat with LLM models
|
|
602
669
|
agent <prompt> Chat with Fast Agent (supports image/video generation)
|
|
603
670
|
app <subcommand> App-related operations (search, generation)
|
|
671
|
+
scan <uri> Content safety scan (image/video/audio)
|
|
672
|
+
status <task-id> Query task status by task ID
|
|
604
673
|
<model> Test specific model generation
|
|
605
674
|
|
|
606
675
|
App Subcommands:
|
|
@@ -626,11 +695,21 @@ App Generation Options:
|
|
|
626
695
|
--template-id <id> Template ID (required)
|
|
627
696
|
--params <json> Input parameters as JSON string (required)
|
|
628
697
|
|
|
698
|
+
Scan Options:
|
|
699
|
+
--risk-types <types> Risk types (default: POLITY,EROTIC,VIOLENT,CHILD)
|
|
700
|
+
--detected-age Enable age detection (default: false)
|
|
701
|
+
--api-key <key> API key (or set API_SERVICE_TOKEN env var)
|
|
702
|
+
--base-url <url> Base URL (default: http://proxy.sg.seaverse.dev)
|
|
703
|
+
|
|
629
704
|
Model Generation Options:
|
|
630
705
|
--api-key <key> API key (or set API_SERVICE_TOKEN env var)
|
|
631
706
|
--base-url <url> Base URL (default: http://proxy.sg.seaverse.dev)
|
|
632
707
|
--params <json> JSON parameters for the model
|
|
633
708
|
|
|
709
|
+
Status Query Options:
|
|
710
|
+
--api-key <key> API key (or set API_SERVICE_TOKEN env var)
|
|
711
|
+
--base-url <url> Base URL (default: http://proxy.sg.seaverse.dev)
|
|
712
|
+
|
|
634
713
|
Examples:
|
|
635
714
|
# Chat with LLM (non-streaming)
|
|
636
715
|
seacloud llm "What is the capital of France?"
|
|
@@ -654,6 +733,18 @@ Examples:
|
|
|
654
733
|
# Create generation task (app generation)
|
|
655
734
|
seacloud app generation --template-id "d26trpte878eqsnm3bjg" --params '[{"field":"prompt1","value":"hello"}]'
|
|
656
735
|
|
|
736
|
+
# Query task status
|
|
737
|
+
seacloud status d123456789abcdef
|
|
738
|
+
|
|
739
|
+
# Scan image
|
|
740
|
+
seacloud scan "https://example.com/image.jpg"
|
|
741
|
+
|
|
742
|
+
# Scan video with custom risk types
|
|
743
|
+
seacloud scan "https://example.com/video.mp4" --risk-types EROTIC,VIOLENT
|
|
744
|
+
|
|
745
|
+
# Scan with age detection
|
|
746
|
+
seacloud scan "https://example.com/photo.jpg" --detected-age
|
|
747
|
+
|
|
657
748
|
# Test model generation
|
|
658
749
|
seacloud flux_1_1_pro --params '{"prompt":"a beautiful sunset"}'
|
|
659
750
|
|
|
@@ -952,6 +1043,167 @@ async function runAppSearch(templateIdsStr, args) {
|
|
|
952
1043
|
});
|
|
953
1044
|
console.log(JSON.stringify(result, null, 2));
|
|
954
1045
|
}
|
|
1046
|
+
function detectMediaType(uri) {
|
|
1047
|
+
const videoExtRegex = /\.(?:mp4|avi|mkv|mov|flv|wmv|webm|m4v|3gp|ts|mts|mpeg|mpg|vob|ogv|m2ts|divx|rm|rmvb|asf|f4v)(?:[^a-z0-9]|$)/i;
|
|
1048
|
+
const audioExtRegex = /\.(?:mp3|wav|ogg|m4a|aac|flac|wma|m4b|m4p|m4r)(?:[^a-z0-9]|$)/i;
|
|
1049
|
+
if (videoExtRegex.test(uri)) {
|
|
1050
|
+
return { isVideo: 1, mediaType: "video" };
|
|
1051
|
+
}
|
|
1052
|
+
if (audioExtRegex.test(uri)) {
|
|
1053
|
+
return { isVideo: 1, mediaType: "audio" };
|
|
1054
|
+
}
|
|
1055
|
+
return { isVideo: 0, mediaType: "image" };
|
|
1056
|
+
}
|
|
1057
|
+
async function runScan(uri, args) {
|
|
1058
|
+
const options = {
|
|
1059
|
+
riskTypes: ["POLITY", "EROTIC", "VIOLENT", "CHILD"],
|
|
1060
|
+
detectedAge: false
|
|
1061
|
+
};
|
|
1062
|
+
for (let i = 0; i < args.length; i++) {
|
|
1063
|
+
const arg = args[i];
|
|
1064
|
+
if (arg === "--risk-types") {
|
|
1065
|
+
options.riskTypes = args[++i].split(",").map((t) => t.trim());
|
|
1066
|
+
} else if (arg === "--detected-age") {
|
|
1067
|
+
options.detectedAge = true;
|
|
1068
|
+
} else if (arg === "--api-key") {
|
|
1069
|
+
options.apiKey = args[++i];
|
|
1070
|
+
} else if (arg === "--base-url") {
|
|
1071
|
+
options.baseUrl = args[++i];
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
const apiKey = options.apiKey || process.env.API_SERVICE_TOKEN || "";
|
|
1075
|
+
const baseUrl = options.baseUrl || process.env.SEACLOUD_BASE_URL || "http://proxy.sg.seaverse.dev";
|
|
1076
|
+
initSeacloud(apiKey, { baseUrl });
|
|
1077
|
+
const { isVideo, mediaType } = detectMediaType(uri);
|
|
1078
|
+
console.log(`\u8D44\u6E90\u5730\u5740: ${uri}`);
|
|
1079
|
+
console.log(`\u5A92\u4F53\u7C7B\u578B: ${mediaType}`);
|
|
1080
|
+
console.log(`\u98CE\u9669\u7C7B\u578B: ${options.riskTypes.join(", ")}`);
|
|
1081
|
+
console.log(`\u5E74\u9F84\u68C0\u6D4B: ${options.detectedAge ? "\u542F\u7528" : "\u7981\u7528"}`);
|
|
1082
|
+
console.log("");
|
|
1083
|
+
try {
|
|
1084
|
+
const result = await scan({
|
|
1085
|
+
uri,
|
|
1086
|
+
risk_types: options.riskTypes,
|
|
1087
|
+
detected_age: options.detectedAge ? 1 : 0,
|
|
1088
|
+
is_video: isVideo
|
|
1089
|
+
});
|
|
1090
|
+
console.log("\u2705 \u626B\u63CF\u5B8C\u6210!\n");
|
|
1091
|
+
console.log(`\u8BF7\u6C42\u72B6\u6001: ${result.ok ? "\u6210\u529F" : "\u5931\u8D25"}`);
|
|
1092
|
+
if (result.nsfw_level !== void 0) {
|
|
1093
|
+
console.log(`\u98CE\u9669\u7EA7\u522B: ${result.nsfw_level} (0-6)`);
|
|
1094
|
+
}
|
|
1095
|
+
if (result.risk_types && result.risk_types.length > 0) {
|
|
1096
|
+
console.log(`\u68C0\u6D4B\u5230\u7684\u98CE\u9669\u7C7B\u578B: ${result.risk_types.join(", ")}`);
|
|
1097
|
+
}
|
|
1098
|
+
if (result.age_group && result.age_group.length > 0) {
|
|
1099
|
+
console.log(`\u5E74\u9F84\u7EC4: ${JSON.stringify(result.age_group)}`);
|
|
1100
|
+
}
|
|
1101
|
+
if (isVideo === 1) {
|
|
1102
|
+
if (result.video_duration !== void 0) {
|
|
1103
|
+
console.log(`\u89C6\u9891\u65F6\u957F: ${result.video_duration} \u79D2`);
|
|
1104
|
+
}
|
|
1105
|
+
if (result.frame_count !== void 0) {
|
|
1106
|
+
console.log(`\u603B\u62BD\u5E27\u6570: ${result.frame_count}`);
|
|
1107
|
+
}
|
|
1108
|
+
if (result.frames_checked !== void 0) {
|
|
1109
|
+
console.log(`\u5B9E\u9645\u68C0\u6D4B\u5E27\u6570: ${result.frames_checked}`);
|
|
1110
|
+
}
|
|
1111
|
+
if (result.max_risk_frame !== void 0) {
|
|
1112
|
+
console.log(`\u6700\u9AD8\u98CE\u9669\u5E27\u7D22\u5F15: ${result.max_risk_frame}`);
|
|
1113
|
+
}
|
|
1114
|
+
if (result.early_exit !== void 0) {
|
|
1115
|
+
console.log(`\u63D0\u524D\u9000\u51FA: ${result.early_exit ? "\u662F" : "\u5426"}`);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
if (result.label_items && result.label_items.length > 0) {
|
|
1119
|
+
console.log(`
|
|
1120
|
+
\u68C0\u6D4B\u5230\u7684\u6807\u7B7E (${result.label_items.length} \u4E2A):`);
|
|
1121
|
+
result.label_items.forEach((item, i) => {
|
|
1122
|
+
console.log(` ${i + 1}. ${item.name}`);
|
|
1123
|
+
console.log(` \u98CE\u9669\u7EA7\u522B: ${item.score}, \u7C7B\u578B: ${item.risk_type}`);
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
if (result.frame_results && result.frame_results.length > 0) {
|
|
1127
|
+
console.log(`
|
|
1128
|
+
\u5E27\u68C0\u6D4B\u7ED3\u679C (\u524D5\u5E27):`);
|
|
1129
|
+
result.frame_results.slice(0, 5).forEach((frame) => {
|
|
1130
|
+
console.log(` \u5E27 ${frame.frame_index}: \u98CE\u9669\u7EA7\u522B ${frame.nsfw_level}, \u6807\u7B7E\u6570 ${frame.label_items.length}`);
|
|
1131
|
+
});
|
|
1132
|
+
if (result.frame_results.length > 5) {
|
|
1133
|
+
console.log(` ... \u8FD8\u6709 ${result.frame_results.length - 5} \u5E27\u7ED3\u679C`);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
if (result.error) {
|
|
1137
|
+
console.log(`
|
|
1138
|
+
\u274C \u9519\u8BEF: ${result.error}`);
|
|
1139
|
+
}
|
|
1140
|
+
} catch (error) {
|
|
1141
|
+
console.error("\n\u274C \u626B\u63CF\u5931\u8D25:", error.message);
|
|
1142
|
+
process.exit(1);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
async function runTaskStatus(taskId, args) {
|
|
1146
|
+
const options = {};
|
|
1147
|
+
for (let i = 0; i < args.length; i++) {
|
|
1148
|
+
const arg = args[i];
|
|
1149
|
+
if (arg === "--api-key") options.apiKey = args[++i];
|
|
1150
|
+
else if (arg === "--base-url") options.baseUrl = args[++i];
|
|
1151
|
+
}
|
|
1152
|
+
const apiKey = options.apiKey || process.env.API_SERVICE_TOKEN || "";
|
|
1153
|
+
const baseUrl = options.baseUrl || process.env.SEACLOUD_BASE_URL || "http://proxy.sg.seaverse.dev";
|
|
1154
|
+
const client = new SeacloudClient({ apiKey, baseUrl });
|
|
1155
|
+
console.log(`Querying task status...`);
|
|
1156
|
+
console.log(`Task ID: ${taskId}`);
|
|
1157
|
+
console.log(`Base URL: ${baseUrl}
|
|
1158
|
+
`);
|
|
1159
|
+
try {
|
|
1160
|
+
const result = await client.getTaskStatus("/model/v1/generation", taskId);
|
|
1161
|
+
console.log(`Status: ${result.status}`);
|
|
1162
|
+
console.log(`Task ID: ${result.id}
|
|
1163
|
+
`);
|
|
1164
|
+
if (result.status === "completed") {
|
|
1165
|
+
console.log("\u2705 Task completed successfully!\n");
|
|
1166
|
+
console.log("Output:");
|
|
1167
|
+
console.log(JSON.stringify(result.output, null, 2));
|
|
1168
|
+
if (result.output) {
|
|
1169
|
+
const urls = [];
|
|
1170
|
+
for (const item of result.output) {
|
|
1171
|
+
if (item.content) {
|
|
1172
|
+
for (const resource of item.content) {
|
|
1173
|
+
if (resource.url) {
|
|
1174
|
+
urls.push(resource.url);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
if (urls.length > 0) {
|
|
1180
|
+
console.log("\nGenerated URLs:");
|
|
1181
|
+
urls.forEach((url, i) => {
|
|
1182
|
+
console.log(` ${i + 1}. ${url}`);
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
} else if (result.status === "failed") {
|
|
1187
|
+
console.log("\u274C Task failed!\n");
|
|
1188
|
+
console.log("Error:", JSON.stringify(result.error, null, 2));
|
|
1189
|
+
} else if (result.status === "processing") {
|
|
1190
|
+
console.log("\u23F3 Task is still processing...");
|
|
1191
|
+
console.log("Please check again later.");
|
|
1192
|
+
} else if (result.status === "pending") {
|
|
1193
|
+
console.log("\u23F3 Task is pending...");
|
|
1194
|
+
console.log("Please check again later.");
|
|
1195
|
+
} else {
|
|
1196
|
+
console.log("Full result:");
|
|
1197
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1198
|
+
}
|
|
1199
|
+
} catch (error) {
|
|
1200
|
+
console.error("\nError querying task status:", error.message);
|
|
1201
|
+
if (error.statusCode) {
|
|
1202
|
+
console.error("HTTP Status Code:", error.statusCode);
|
|
1203
|
+
}
|
|
1204
|
+
process.exit(1);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
955
1207
|
async function main() {
|
|
956
1208
|
const args = process.argv.slice(2);
|
|
957
1209
|
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
@@ -974,6 +1226,20 @@ async function main() {
|
|
|
974
1226
|
process.exit(1);
|
|
975
1227
|
}
|
|
976
1228
|
await runAgent(args[1], args.slice(2));
|
|
1229
|
+
} else if (command === "scan") {
|
|
1230
|
+
if (args.length < 2) {
|
|
1231
|
+
console.error("Error: URI required for scan command");
|
|
1232
|
+
console.log('Usage: seacloud scan "<uri>" [options]');
|
|
1233
|
+
process.exit(1);
|
|
1234
|
+
}
|
|
1235
|
+
await runScan(args[1], args.slice(2));
|
|
1236
|
+
} else if (command === "status") {
|
|
1237
|
+
if (args.length < 2) {
|
|
1238
|
+
console.error("Error: task ID required for status command");
|
|
1239
|
+
console.log("Usage: seacloud status <task-id> [options]");
|
|
1240
|
+
process.exit(1);
|
|
1241
|
+
}
|
|
1242
|
+
await runTaskStatus(args[1], args.slice(2));
|
|
977
1243
|
} else if (command === "app") {
|
|
978
1244
|
const subcommand = args[1];
|
|
979
1245
|
if (!subcommand) {
|