seacloud-sdk 0.9.9 → 0.10.1
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/README.md +969 -0
- package/dist/cli.js +189 -0
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +182 -1
- package/dist/index.js +68 -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,7 @@ 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)
|
|
604
672
|
status <task-id> Query task status by task ID
|
|
605
673
|
<model> Test specific model generation
|
|
606
674
|
|
|
@@ -627,6 +695,12 @@ App Generation Options:
|
|
|
627
695
|
--template-id <id> Template ID (required)
|
|
628
696
|
--params <json> Input parameters as JSON string (required)
|
|
629
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
|
+
|
|
630
704
|
Model Generation Options:
|
|
631
705
|
--api-key <key> API key (or set API_SERVICE_TOKEN env var)
|
|
632
706
|
--base-url <url> Base URL (default: http://proxy.sg.seaverse.dev)
|
|
@@ -662,6 +736,15 @@ Examples:
|
|
|
662
736
|
# Query task status
|
|
663
737
|
seacloud status d123456789abcdef
|
|
664
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
|
+
|
|
665
748
|
# Test model generation
|
|
666
749
|
seacloud flux_1_1_pro --params '{"prompt":"a beautiful sunset"}'
|
|
667
750
|
|
|
@@ -960,6 +1043,105 @@ async function runAppSearch(templateIdsStr, args) {
|
|
|
960
1043
|
});
|
|
961
1044
|
console.log(JSON.stringify(result, null, 2));
|
|
962
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
|
+
}
|
|
963
1145
|
async function runTaskStatus(taskId, args) {
|
|
964
1146
|
const options = {};
|
|
965
1147
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -1044,6 +1226,13 @@ async function main() {
|
|
|
1044
1226
|
process.exit(1);
|
|
1045
1227
|
}
|
|
1046
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));
|
|
1047
1236
|
} else if (command === "status") {
|
|
1048
1237
|
if (args.length < 2) {
|
|
1049
1238
|
console.error("Error: task ID required for status command");
|