seacloud-sdk 0.10.2 → 0.11.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 +339 -30
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +996 -5
- package/dist/index.js +672 -31
- package/dist/index.js.map +1 -1
- package/package.json +19 -4
- package/README.md +0 -168
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,51 @@ var SeacloudError = class extends Error {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
// src/core/config.ts
|
|
16
|
-
function
|
|
16
|
+
function isInIframe() {
|
|
17
|
+
try {
|
|
18
|
+
return typeof globalThis.window !== "undefined" && globalThis.window.self !== globalThis.window.top;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function getTokenFromParent(timeout = 5e3) {
|
|
24
|
+
if (!isInIframe()) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
const messageHandler = (event) => {
|
|
29
|
+
if (event.data && event.data.type === "seaverse:token") {
|
|
30
|
+
cleanup();
|
|
31
|
+
const token = event.data.payload?.accessToken;
|
|
32
|
+
resolve(token || null);
|
|
33
|
+
} else if (event.data && event.data.type === "seaverse:error") {
|
|
34
|
+
cleanup();
|
|
35
|
+
console.warn("[SeaCloud SDK] Error getting token from parent:", event.data.error);
|
|
36
|
+
resolve(null);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const timeoutId = setTimeout(() => {
|
|
40
|
+
cleanup();
|
|
41
|
+
resolve(null);
|
|
42
|
+
}, timeout);
|
|
43
|
+
const cleanup = () => {
|
|
44
|
+
clearTimeout(timeoutId);
|
|
45
|
+
globalThis.window.removeEventListener("message", messageHandler);
|
|
46
|
+
};
|
|
47
|
+
globalThis.window.addEventListener("message", messageHandler);
|
|
48
|
+
try {
|
|
49
|
+
globalThis.window.parent.postMessage(
|
|
50
|
+
{ type: "seaverse:get_token" },
|
|
51
|
+
"*"
|
|
52
|
+
// 允许任何源,支持跨域场景
|
|
53
|
+
);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
cleanup();
|
|
56
|
+
resolve(null);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async function getApiToken(providedApiKey) {
|
|
17
61
|
if (providedApiKey) {
|
|
18
62
|
return providedApiKey;
|
|
19
63
|
}
|
|
@@ -29,23 +73,27 @@ function getApiToken(providedApiKey) {
|
|
|
29
73
|
if (typeof process !== "undefined" && process.env?.API_SERVICE_TOKEN) {
|
|
30
74
|
return process.env.API_SERVICE_TOKEN;
|
|
31
75
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
76
|
+
if (typeof globalThis.window !== "undefined") {
|
|
77
|
+
const parentToken = await getTokenFromParent();
|
|
78
|
+
if (parentToken) {
|
|
79
|
+
return parentToken;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return "";
|
|
35
83
|
}
|
|
36
84
|
function createConfig(options = {}) {
|
|
37
|
-
const apiKey =
|
|
85
|
+
const apiKey = options.apiKey;
|
|
38
86
|
const baseUrl = options.baseUrl || (typeof process !== "undefined" ? process.env?.SEACLOUD_BASE_URL : void 0) || "https://proxy-rs.seaverse.ai";
|
|
39
87
|
const fetchImpl = options.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
|
|
40
88
|
if (!fetchImpl) {
|
|
41
89
|
throw new Error("fetch is not available. Please provide a fetch implementation in config or upgrade to Node.js 18+");
|
|
42
90
|
}
|
|
43
91
|
return {
|
|
44
|
-
apiKey,
|
|
92
|
+
apiKey: apiKey || "",
|
|
93
|
+
// 提供默认空字符串,实际请求时会动态获取
|
|
45
94
|
baseUrl,
|
|
46
95
|
fetch: fetchImpl,
|
|
47
|
-
timeout: options.timeout || 3e4
|
|
48
|
-
xProject: options.xProject || "SeaVerse"
|
|
96
|
+
timeout: options.timeout || 3e4
|
|
49
97
|
};
|
|
50
98
|
}
|
|
51
99
|
function validateConfig(config) {
|
|
@@ -87,7 +135,7 @@ var SeacloudClient = class {
|
|
|
87
135
|
*/
|
|
88
136
|
async createTask(endpoint, body) {
|
|
89
137
|
const url = `${this.config.baseUrl}${endpoint}`;
|
|
90
|
-
const currentToken = getApiToken(this.providedApiKey);
|
|
138
|
+
const currentToken = await getApiToken(this.providedApiKey);
|
|
91
139
|
const controller = new AbortController();
|
|
92
140
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
93
141
|
try {
|
|
@@ -134,7 +182,7 @@ var SeacloudClient = class {
|
|
|
134
182
|
*/
|
|
135
183
|
async getTaskStatus(endpoint, taskId) {
|
|
136
184
|
const url = `${this.config.baseUrl}${endpoint}/task/${taskId}`;
|
|
137
|
-
const currentToken = getApiToken(this.providedApiKey);
|
|
185
|
+
const currentToken = await getApiToken(this.providedApiKey);
|
|
138
186
|
const controller = new AbortController();
|
|
139
187
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
140
188
|
try {
|
|
@@ -205,8 +253,7 @@ function initSeacloud(apiKeyOrConfig, options) {
|
|
|
205
253
|
globalConfig.client = new SeacloudClient({
|
|
206
254
|
apiKey: apiKey || "",
|
|
207
255
|
baseUrl: config.baseUrl,
|
|
208
|
-
timeout: config.timeout
|
|
209
|
-
xProject: config.xProject
|
|
256
|
+
timeout: config.timeout
|
|
210
257
|
});
|
|
211
258
|
if (config.intervalMs !== void 0) {
|
|
212
259
|
globalConfig.defaultPollingOptions.intervalMs = config.intervalMs;
|
|
@@ -232,6 +279,7 @@ async function llmChatCompletions(params) {
|
|
|
232
279
|
const client = getClient();
|
|
233
280
|
const config = client.getConfig();
|
|
234
281
|
const url = `${config.baseUrl}/llm/chat/completions`;
|
|
282
|
+
const token = await getApiToken(config.apiKey);
|
|
235
283
|
const controller = new AbortController();
|
|
236
284
|
const timeoutId = setTimeout(() => controller.abort(), config.timeout);
|
|
237
285
|
try {
|
|
@@ -239,7 +287,7 @@ async function llmChatCompletions(params) {
|
|
|
239
287
|
method: "POST",
|
|
240
288
|
headers: {
|
|
241
289
|
"Content-Type": "application/json",
|
|
242
|
-
"Authorization": `Bearer ${
|
|
290
|
+
"Authorization": `Bearer ${token}`
|
|
243
291
|
},
|
|
244
292
|
body: JSON.stringify(params),
|
|
245
293
|
signal: controller.signal
|
|
@@ -325,16 +373,14 @@ async function agentChatCompletions(params) {
|
|
|
325
373
|
const controller = new AbortController();
|
|
326
374
|
const timeoutId = setTimeout(() => controller.abort(), config.timeout);
|
|
327
375
|
try {
|
|
328
|
-
const headers = {
|
|
329
|
-
"Content-Type": "application/json",
|
|
330
|
-
"Authorization": `Bearer ${config.apiKey}`
|
|
331
|
-
};
|
|
332
|
-
if (config.xProject) {
|
|
333
|
-
headers["X-Project"] = config.xProject;
|
|
334
|
-
}
|
|
335
376
|
const response = await config.fetch(url, {
|
|
336
377
|
method: "POST",
|
|
337
|
-
headers
|
|
378
|
+
headers: {
|
|
379
|
+
"Content-Type": "application/json",
|
|
380
|
+
"Authorization": `Bearer ${config.apiKey}`,
|
|
381
|
+
"X-Project": "SeaArt"
|
|
382
|
+
// Required header for agent API
|
|
383
|
+
},
|
|
338
384
|
body: JSON.stringify(requestBody),
|
|
339
385
|
signal: controller.signal
|
|
340
386
|
});
|
|
@@ -519,17 +565,14 @@ async function appSearch(params) {
|
|
|
519
565
|
const timeoutId = setTimeout(() => controller.abort(), config.timeout);
|
|
520
566
|
try {
|
|
521
567
|
const requestId = `req-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
522
|
-
const headers = {
|
|
523
|
-
"Content-Type": "application/json",
|
|
524
|
-
"Authorization": `Bearer ${config.apiKey}`,
|
|
525
|
-
"X-Request-Id": requestId
|
|
526
|
-
};
|
|
527
|
-
if (config.xProject) {
|
|
528
|
-
headers["X-Project"] = config.xProject;
|
|
529
|
-
}
|
|
530
568
|
const response = await config.fetch(url, {
|
|
531
569
|
method: "POST",
|
|
532
|
-
headers
|
|
570
|
+
headers: {
|
|
571
|
+
"Content-Type": "application/json",
|
|
572
|
+
"Authorization": `Bearer ${config.apiKey}`,
|
|
573
|
+
"X-Request-Id": requestId,
|
|
574
|
+
"X-Project": "KIIRA"
|
|
575
|
+
},
|
|
533
576
|
body: JSON.stringify(params),
|
|
534
577
|
signal: controller.signal
|
|
535
578
|
});
|
|
@@ -545,6 +588,73 @@ async function appSearch(params) {
|
|
|
545
588
|
throw error;
|
|
546
589
|
}
|
|
547
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
|
+
}
|
|
548
658
|
var __filename$1 = fileURLToPath(import.meta.url);
|
|
549
659
|
dirname(__filename$1);
|
|
550
660
|
function showHelp() {
|
|
@@ -558,6 +668,8 @@ Commands:
|
|
|
558
668
|
llm <prompt> Chat with LLM models
|
|
559
669
|
agent <prompt> Chat with Fast Agent (supports image/video generation)
|
|
560
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
|
|
561
673
|
<model> Test specific model generation
|
|
562
674
|
|
|
563
675
|
App Subcommands:
|
|
@@ -583,11 +695,21 @@ App Generation Options:
|
|
|
583
695
|
--template-id <id> Template ID (required)
|
|
584
696
|
--params <json> Input parameters as JSON string (required)
|
|
585
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
|
+
|
|
586
704
|
Model Generation Options:
|
|
587
705
|
--api-key <key> API key (or set API_SERVICE_TOKEN env var)
|
|
588
706
|
--base-url <url> Base URL (default: http://proxy.sg.seaverse.dev)
|
|
589
707
|
--params <json> JSON parameters for the model
|
|
590
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
|
+
|
|
591
713
|
Examples:
|
|
592
714
|
# Chat with LLM (non-streaming)
|
|
593
715
|
seacloud llm "What is the capital of France?"
|
|
@@ -611,6 +733,18 @@ Examples:
|
|
|
611
733
|
# Create generation task (app generation)
|
|
612
734
|
seacloud app generation --template-id "d26trpte878eqsnm3bjg" --params '[{"field":"prompt1","value":"hello"}]'
|
|
613
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
|
+
|
|
614
748
|
# Test model generation
|
|
615
749
|
seacloud flux_1_1_pro --params '{"prompt":"a beautiful sunset"}'
|
|
616
750
|
|
|
@@ -909,6 +1043,167 @@ async function runAppSearch(templateIdsStr, args) {
|
|
|
909
1043
|
});
|
|
910
1044
|
console.log(JSON.stringify(result, null, 2));
|
|
911
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
|
+
}
|
|
912
1207
|
async function main() {
|
|
913
1208
|
const args = process.argv.slice(2);
|
|
914
1209
|
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
@@ -931,6 +1226,20 @@ async function main() {
|
|
|
931
1226
|
process.exit(1);
|
|
932
1227
|
}
|
|
933
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));
|
|
934
1243
|
} else if (command === "app") {
|
|
935
1244
|
const subcommand = args[1];
|
|
936
1245
|
if (!subcommand) {
|