seacloud-sdk 0.10.0 → 0.10.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/README.md +168 -0
- package/dist/cli.js +30 -339
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +5 -211
- package/dist/index.js +31 -147
- package/dist/index.js.map +1 -1
- package/package.json +4 -19
package/README.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# SeaCloud SDK
|
|
2
|
+
|
|
3
|
+
SeaCloud SDK for JavaScript/TypeScript - 用于调用 SeaCloud AI 服务的官方 SDK。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 🤖 **Agent Chat API** - 多轮对话、工具调用、流式输出
|
|
8
|
+
- 🎨 **图像生成** - 支持多种 AI 图像生成模型
|
|
9
|
+
- 🎬 **视频生成** - Text-to-Video、Image-to-Video
|
|
10
|
+
- 🎵 **音乐生成** - 歌曲、歌词生成
|
|
11
|
+
- 🔄 **流式响应** - 实时获取 AI 响应
|
|
12
|
+
- 📦 **TypeScript 支持** - 完整的类型定义
|
|
13
|
+
|
|
14
|
+
## 安装
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm install seacloud-sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 快速开始
|
|
21
|
+
|
|
22
|
+
### 初始化 SDK
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { initSeacloud, agentChatCompletions, createTextMessage } from 'seacloud-sdk';
|
|
26
|
+
|
|
27
|
+
// 初始化 SDK
|
|
28
|
+
initSeacloud({
|
|
29
|
+
apiKey: 'your-api-key',
|
|
30
|
+
baseUrl: 'https://proxy-rs.seaverse.ai',
|
|
31
|
+
xProject: 'SeaArt', // 可选,默认为 'SeaVerse'
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 简单对话
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
const response = await agentChatCompletions({
|
|
39
|
+
agent_id: 'seagen_agent',
|
|
40
|
+
messages: [
|
|
41
|
+
createTextMessage('user', 'Hello! How are you?')
|
|
42
|
+
],
|
|
43
|
+
model: 'gpt-4o',
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
console.log(response.choices[0].message.content);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 流式对话
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
const stream = await agentChatCompletions({
|
|
53
|
+
agent_id: 'seagen_agent',
|
|
54
|
+
messages: [
|
|
55
|
+
createTextMessage('user', 'Tell me a story')
|
|
56
|
+
],
|
|
57
|
+
model: 'gpt-4o',
|
|
58
|
+
stream: true,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
for await (const chunk of stream) {
|
|
62
|
+
const content = chunk.choices[0]?.delta?.content;
|
|
63
|
+
if (content) {
|
|
64
|
+
process.stdout.write(content);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 配置选项
|
|
70
|
+
|
|
71
|
+
### initSeacloud(options)
|
|
72
|
+
|
|
73
|
+
| 参数 | 类型 | 默认值 | 描述 |
|
|
74
|
+
|------|------|--------|------|
|
|
75
|
+
| `apiKey` | `string` | - | API 密钥,也可通过环境变量 `API_SERVICE_TOKEN` 设置 |
|
|
76
|
+
| `baseUrl` | `string` | `https://proxy-rs.seaverse.ai` | API 服务器地址 |
|
|
77
|
+
| `timeout` | `number` | `30000` | 请求超时时间(毫秒) |
|
|
78
|
+
| `intervalMs` | `number` | `3000` | 轮询间隔(毫秒) |
|
|
79
|
+
| `maxAttempts` | `number` | `100` | 最大轮询次数 |
|
|
80
|
+
| `xProject` | `string` | `'SeaVerse'` | X-Project header 值,用于项目标识 |
|
|
81
|
+
|
|
82
|
+
### xProject 参数说明
|
|
83
|
+
|
|
84
|
+
`xProject` 参数用于设置请求头 `X-Project`,标识请求来源的项目。不同项目可能有不同的配额和权限:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// SeaArt 项目
|
|
88
|
+
initSeacloud({
|
|
89
|
+
apiKey: 'your-api-key',
|
|
90
|
+
xProject: 'SeaArt',
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// KIIRA 项目
|
|
94
|
+
initSeacloud({
|
|
95
|
+
apiKey: 'your-api-key',
|
|
96
|
+
xProject: 'KIIRA',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// 默认使用 SeaVerse
|
|
100
|
+
initSeacloud({
|
|
101
|
+
apiKey: 'your-api-key',
|
|
102
|
+
// xProject 默认为 'SeaVerse'
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Token 获取优先级
|
|
107
|
+
|
|
108
|
+
SDK 会按以下优先级获取 API Token:
|
|
109
|
+
|
|
110
|
+
1. `initSeacloud({ apiKey: '...' })` 传入的 apiKey
|
|
111
|
+
2. 浏览器环境:`localStorage.getItem('auth_token')`
|
|
112
|
+
3. Node.js 环境:`process.env.API_SERVICE_TOKEN`
|
|
113
|
+
|
|
114
|
+
## 环境变量
|
|
115
|
+
|
|
116
|
+
| 变量名 | 描述 |
|
|
117
|
+
|--------|------|
|
|
118
|
+
| `API_SERVICE_TOKEN` | API 密钥 |
|
|
119
|
+
| `SEACLOUD_BASE_URL` | API 服务器地址 |
|
|
120
|
+
|
|
121
|
+
## API 参考
|
|
122
|
+
|
|
123
|
+
### Agent Chat API
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { agentChatCompletions, createTextMessage, createImageMessage, createTool } from 'seacloud-sdk';
|
|
127
|
+
|
|
128
|
+
// 文本消息
|
|
129
|
+
const textMessage = createTextMessage('user', 'Hello!');
|
|
130
|
+
|
|
131
|
+
// 图片消息
|
|
132
|
+
const imageMessage = createImageMessage('user', 'What is this?', 'https://example.com/image.jpg');
|
|
133
|
+
|
|
134
|
+
// 创建工具
|
|
135
|
+
const tool = createTool('seagen_text2image_flux1d_artifact_tool');
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 可用工具列表
|
|
139
|
+
|
|
140
|
+
**图像生成:**
|
|
141
|
+
- `seagen_text2image_flux1d_artifact_tool`
|
|
142
|
+
- `seagen_text2image_seedream40_artifact_tool`
|
|
143
|
+
- `seagen_text2image_google_gemini3_pro_image_artifact_tool`
|
|
144
|
+
- `seagen_blackforestlabs_flux_2_pro_tool`
|
|
145
|
+
- `mm_volces_seedream_4_5_gateway_tool`
|
|
146
|
+
|
|
147
|
+
**图像编辑:**
|
|
148
|
+
- `seagen_edit_image_google_artifact_tool`
|
|
149
|
+
- `seagen_blackforestlabs_flux_2_pro_edit_tool`
|
|
150
|
+
|
|
151
|
+
**视频生成:**
|
|
152
|
+
- `seagen_image2video_wanx26_artifact_tool`
|
|
153
|
+
- `seagen_text2video_wanx26_artifact_tool`
|
|
154
|
+
- `seagen_image2video_seedance_pro_fast_artifact_tool`
|
|
155
|
+
- `mm_text2video_kling_v2_6_gateway_tool`
|
|
156
|
+
- `mm_image2video_kling_v2_6_i2v_gateway_tool`
|
|
157
|
+
|
|
158
|
+
**音乐生成:**
|
|
159
|
+
- `seagen_text2song_mureka_artifact_tool`
|
|
160
|
+
- `seagen_text2lyrics_mureka_artifact_tool`
|
|
161
|
+
|
|
162
|
+
## 示例
|
|
163
|
+
|
|
164
|
+
更多示例请查看 [examples_agent.ts](./examples_agent.ts)
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
MIT
|
package/dist/cli.js
CHANGED
|
@@ -13,51 +13,7 @@ var SeacloudError = class extends Error {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
// src/core/config.ts
|
|
16
|
-
function
|
|
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) {
|
|
16
|
+
function getApiToken(providedApiKey) {
|
|
61
17
|
if (providedApiKey) {
|
|
62
18
|
return providedApiKey;
|
|
63
19
|
}
|
|
@@ -73,27 +29,23 @@ async function getApiToken(providedApiKey) {
|
|
|
73
29
|
if (typeof process !== "undefined" && process.env?.API_SERVICE_TOKEN) {
|
|
74
30
|
return process.env.API_SERVICE_TOKEN;
|
|
75
31
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return parentToken;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return "";
|
|
32
|
+
throw new Error(
|
|
33
|
+
'SeaCloud SDK: No API token found. Please ensure token is available in localStorage.getItem("auth_token") (browser) or process.env.API_SERVICE_TOKEN (Node.js), or initialize with initSeacloud({ apiKey: "your-token" }).'
|
|
34
|
+
);
|
|
83
35
|
}
|
|
84
36
|
function createConfig(options = {}) {
|
|
85
|
-
const apiKey = options.apiKey;
|
|
37
|
+
const apiKey = getApiToken(options.apiKey);
|
|
86
38
|
const baseUrl = options.baseUrl || (typeof process !== "undefined" ? process.env?.SEACLOUD_BASE_URL : void 0) || "https://proxy-rs.seaverse.ai";
|
|
87
39
|
const fetchImpl = options.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
|
|
88
40
|
if (!fetchImpl) {
|
|
89
41
|
throw new Error("fetch is not available. Please provide a fetch implementation in config or upgrade to Node.js 18+");
|
|
90
42
|
}
|
|
91
43
|
return {
|
|
92
|
-
apiKey
|
|
93
|
-
// 提供默认空字符串,实际请求时会动态获取
|
|
44
|
+
apiKey,
|
|
94
45
|
baseUrl,
|
|
95
46
|
fetch: fetchImpl,
|
|
96
|
-
timeout: options.timeout || 3e4
|
|
47
|
+
timeout: options.timeout || 3e4,
|
|
48
|
+
xProject: options.xProject || "SeaVerse"
|
|
97
49
|
};
|
|
98
50
|
}
|
|
99
51
|
function validateConfig(config) {
|
|
@@ -135,7 +87,7 @@ var SeacloudClient = class {
|
|
|
135
87
|
*/
|
|
136
88
|
async createTask(endpoint, body) {
|
|
137
89
|
const url = `${this.config.baseUrl}${endpoint}`;
|
|
138
|
-
const currentToken =
|
|
90
|
+
const currentToken = getApiToken(this.providedApiKey);
|
|
139
91
|
const controller = new AbortController();
|
|
140
92
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
141
93
|
try {
|
|
@@ -182,7 +134,7 @@ var SeacloudClient = class {
|
|
|
182
134
|
*/
|
|
183
135
|
async getTaskStatus(endpoint, taskId) {
|
|
184
136
|
const url = `${this.config.baseUrl}${endpoint}/task/${taskId}`;
|
|
185
|
-
const currentToken =
|
|
137
|
+
const currentToken = getApiToken(this.providedApiKey);
|
|
186
138
|
const controller = new AbortController();
|
|
187
139
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
188
140
|
try {
|
|
@@ -253,7 +205,8 @@ function initSeacloud(apiKeyOrConfig, options) {
|
|
|
253
205
|
globalConfig.client = new SeacloudClient({
|
|
254
206
|
apiKey: apiKey || "",
|
|
255
207
|
baseUrl: config.baseUrl,
|
|
256
|
-
timeout: config.timeout
|
|
208
|
+
timeout: config.timeout,
|
|
209
|
+
xProject: config.xProject
|
|
257
210
|
});
|
|
258
211
|
if (config.intervalMs !== void 0) {
|
|
259
212
|
globalConfig.defaultPollingOptions.intervalMs = config.intervalMs;
|
|
@@ -279,7 +232,6 @@ async function llmChatCompletions(params) {
|
|
|
279
232
|
const client = getClient();
|
|
280
233
|
const config = client.getConfig();
|
|
281
234
|
const url = `${config.baseUrl}/llm/chat/completions`;
|
|
282
|
-
const token = await getApiToken(config.apiKey);
|
|
283
235
|
const controller = new AbortController();
|
|
284
236
|
const timeoutId = setTimeout(() => controller.abort(), config.timeout);
|
|
285
237
|
try {
|
|
@@ -287,7 +239,7 @@ async function llmChatCompletions(params) {
|
|
|
287
239
|
method: "POST",
|
|
288
240
|
headers: {
|
|
289
241
|
"Content-Type": "application/json",
|
|
290
|
-
"Authorization": `Bearer ${
|
|
242
|
+
"Authorization": `Bearer ${config.apiKey}`
|
|
291
243
|
},
|
|
292
244
|
body: JSON.stringify(params),
|
|
293
245
|
signal: controller.signal
|
|
@@ -373,14 +325,16 @@ async function agentChatCompletions(params) {
|
|
|
373
325
|
const controller = new AbortController();
|
|
374
326
|
const timeoutId = setTimeout(() => controller.abort(), config.timeout);
|
|
375
327
|
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
|
+
}
|
|
376
335
|
const response = await config.fetch(url, {
|
|
377
336
|
method: "POST",
|
|
378
|
-
headers
|
|
379
|
-
"Content-Type": "application/json",
|
|
380
|
-
"Authorization": `Bearer ${config.apiKey}`,
|
|
381
|
-
"X-Project": "SeaArt"
|
|
382
|
-
// Required header for agent API
|
|
383
|
-
},
|
|
337
|
+
headers,
|
|
384
338
|
body: JSON.stringify(requestBody),
|
|
385
339
|
signal: controller.signal
|
|
386
340
|
});
|
|
@@ -565,14 +519,17 @@ async function appSearch(params) {
|
|
|
565
519
|
const timeoutId = setTimeout(() => controller.abort(), config.timeout);
|
|
566
520
|
try {
|
|
567
521
|
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
|
+
}
|
|
568
530
|
const response = await config.fetch(url, {
|
|
569
531
|
method: "POST",
|
|
570
|
-
headers
|
|
571
|
-
"Content-Type": "application/json",
|
|
572
|
-
"Authorization": `Bearer ${config.apiKey}`,
|
|
573
|
-
"X-Request-Id": requestId,
|
|
574
|
-
"X-Project": "KIIRA"
|
|
575
|
-
},
|
|
532
|
+
headers,
|
|
576
533
|
body: JSON.stringify(params),
|
|
577
534
|
signal: controller.signal
|
|
578
535
|
});
|
|
@@ -588,73 +545,6 @@ async function appSearch(params) {
|
|
|
588
545
|
throw error;
|
|
589
546
|
}
|
|
590
547
|
}
|
|
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
|
-
}
|
|
658
548
|
var __filename$1 = fileURLToPath(import.meta.url);
|
|
659
549
|
dirname(__filename$1);
|
|
660
550
|
function showHelp() {
|
|
@@ -668,8 +558,6 @@ Commands:
|
|
|
668
558
|
llm <prompt> Chat with LLM models
|
|
669
559
|
agent <prompt> Chat with Fast Agent (supports image/video generation)
|
|
670
560
|
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
|
|
673
561
|
<model> Test specific model generation
|
|
674
562
|
|
|
675
563
|
App Subcommands:
|
|
@@ -695,21 +583,11 @@ App Generation Options:
|
|
|
695
583
|
--template-id <id> Template ID (required)
|
|
696
584
|
--params <json> Input parameters as JSON string (required)
|
|
697
585
|
|
|
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
|
-
|
|
704
586
|
Model Generation Options:
|
|
705
587
|
--api-key <key> API key (or set API_SERVICE_TOKEN env var)
|
|
706
588
|
--base-url <url> Base URL (default: http://proxy.sg.seaverse.dev)
|
|
707
589
|
--params <json> JSON parameters for the model
|
|
708
590
|
|
|
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
|
-
|
|
713
591
|
Examples:
|
|
714
592
|
# Chat with LLM (non-streaming)
|
|
715
593
|
seacloud llm "What is the capital of France?"
|
|
@@ -733,18 +611,6 @@ Examples:
|
|
|
733
611
|
# Create generation task (app generation)
|
|
734
612
|
seacloud app generation --template-id "d26trpte878eqsnm3bjg" --params '[{"field":"prompt1","value":"hello"}]'
|
|
735
613
|
|
|
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
|
-
|
|
748
614
|
# Test model generation
|
|
749
615
|
seacloud flux_1_1_pro --params '{"prompt":"a beautiful sunset"}'
|
|
750
616
|
|
|
@@ -1043,167 +909,6 @@ async function runAppSearch(templateIdsStr, args) {
|
|
|
1043
909
|
});
|
|
1044
910
|
console.log(JSON.stringify(result, null, 2));
|
|
1045
911
|
}
|
|
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
|
-
}
|
|
1207
912
|
async function main() {
|
|
1208
913
|
const args = process.argv.slice(2);
|
|
1209
914
|
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
@@ -1226,20 +931,6 @@ async function main() {
|
|
|
1226
931
|
process.exit(1);
|
|
1227
932
|
}
|
|
1228
933
|
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));
|
|
1243
934
|
} else if (command === "app") {
|
|
1244
935
|
const subcommand = args[1];
|
|
1245
936
|
if (!subcommand) {
|