seacloud-sdk 0.12.4 → 0.12.6

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 CHANGED
@@ -20,6 +20,25 @@ function isInIframe() {
20
20
  return true;
21
21
  }
22
22
  }
23
+ function notifyParentError(status, errorBody) {
24
+ if (!isInIframe()) {
25
+ return;
26
+ }
27
+ try {
28
+ const errorPayload = {
29
+ type: "seaverse:error",
30
+ error: {
31
+ status,
32
+ message: `HTTP ${status}`,
33
+ body: errorBody,
34
+ timestamp: Date.now()
35
+ }
36
+ };
37
+ globalThis.window.parent.postMessage(errorPayload, "*");
38
+ } catch (e) {
39
+ console.warn("[SeaCloud SDK] Failed to notify parent of error:", e);
40
+ }
41
+ }
23
42
  async function getTokenFromParent(timeout = 5e3) {
24
43
  if (!isInIframe()) {
25
44
  return null;
@@ -57,19 +76,19 @@ async function getTokenFromParent(timeout = 5e3) {
57
76
  }
58
77
  });
59
78
  }
60
- async function getHostFromParent(timeout = 5e3) {
79
+ async function getEnvFromParent(timeout = 5e3) {
61
80
  if (!isInIframe()) {
62
81
  return null;
63
82
  }
64
83
  return new Promise((resolve) => {
65
84
  const messageHandler = (event) => {
66
- if (event.data && event.data.type === "seaverse:host") {
85
+ if (event.data && event.data.type === "seaverse:env") {
67
86
  cleanup();
68
- const host = event.data.payload?.host;
69
- resolve(host || null);
87
+ const env = event.data.payload?.env;
88
+ resolve(env || null);
70
89
  } else if (event.data && event.data.type === "seaverse:error") {
71
90
  cleanup();
72
- console.warn("[SeaCloud SDK] Error getting host from parent:", event.data.error);
91
+ console.warn("[SeaCloud SDK] Error getting env from parent:", event.data.error);
73
92
  resolve(null);
74
93
  }
75
94
  };
@@ -84,7 +103,7 @@ async function getHostFromParent(timeout = 5e3) {
84
103
  globalThis.window.addEventListener("message", messageHandler);
85
104
  try {
86
105
  globalThis.window.parent.postMessage(
87
- { type: "seaverse:get_host" },
106
+ { type: "seaverse:get_env" },
88
107
  "*"
89
108
  // 允许任何源,支持跨域场景
90
109
  );
@@ -122,22 +141,34 @@ function checkIsDevelopmentHost(host) {
122
141
  const devHostPatterns = ["localhost", "127.0.0.1", ":3000", ":8080", "seaverse.dev"];
123
142
  return devHostPatterns.some((pattern) => host.includes(pattern));
124
143
  }
125
- function createConfig(options = {}) {
126
- const apiKey = options.apiKey;
127
- let baseUrl;
128
- if (options.baseUrl) {
129
- baseUrl = options.baseUrl;
130
- } else if (typeof process !== "undefined" && process.env?.SEACLOUD_BASE_URL) {
131
- baseUrl = process.env.SEACLOUD_BASE_URL;
132
- } else {
133
- const currentHost = typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined" ? globalThis.window.location.host : "";
134
- if (checkIsDevelopmentHost(currentHost)) {
135
- baseUrl = "https://proxy-rs.sg.seaverse.dev";
136
- console.log("[SeaCloud SDK] \u68C0\u6D4B\u5230\u5F00\u53D1\u73AF\u5883\uFF08currentHost\uFF09\uFF0C\u4F7F\u7528\u5F00\u53D1 baseUrl:", baseUrl);
144
+ async function getBaseUrl(userBaseUrl) {
145
+ if (userBaseUrl) {
146
+ return userBaseUrl;
147
+ }
148
+ if (typeof process !== "undefined" && process.env?.SEACLOUD_BASE_URL) {
149
+ return process.env.SEACLOUD_BASE_URL;
150
+ }
151
+ if (isInIframe()) {
152
+ const parentEnv = await getEnvFromParent(3e3);
153
+ if (parentEnv === "develop") {
154
+ console.log("[SeaCloud SDK] iframe \u73AF\u5883\uFF1A\u7236\u9875\u9762\u8FD4\u56DE\u5F00\u53D1\u73AF\u5883\uFF0C\u4F7F\u7528\u5F00\u53D1 baseUrl");
155
+ return "https://proxy-rs.sg.seaverse.dev";
137
156
  } else {
138
- baseUrl = "https://proxy-rs.seaverse.ai";
157
+ console.log("[SeaCloud SDK] iframe \u73AF\u5883\uFF1A\u4F7F\u7528\u7EBF\u4E0A baseUrl");
158
+ return "https://proxy-rs.seaverse.ai";
139
159
  }
140
160
  }
161
+ const currentHost = typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined" ? globalThis.window.location.host : "";
162
+ if (checkIsDevelopmentHost(currentHost)) {
163
+ console.log("[SeaCloud SDK] \u68C0\u6D4B\u5230\u5F00\u53D1\u73AF\u5883\uFF08currentHost\uFF09\uFF0C\u4F7F\u7528\u5F00\u53D1 baseUrl");
164
+ return "https://proxy-rs.sg.seaverse.dev";
165
+ } else {
166
+ return "https://proxy-rs.seaverse.ai";
167
+ }
168
+ }
169
+ async function createConfig(options = {}) {
170
+ const apiKey = options.apiKey;
171
+ const baseUrl = await getBaseUrl(options.baseUrl);
141
172
  const fetchImpl = options.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
142
173
  if (!fetchImpl) {
143
174
  throw new Error("fetch is not available. Please provide a fetch implementation in config or upgrade to Node.js 18+");
@@ -164,11 +195,11 @@ function validateConfig(config) {
164
195
  var VERSION = "0.9.6";
165
196
 
166
197
  // src/core/client.ts
167
- var SeacloudClient = class {
198
+ var SeacloudClient = class _SeacloudClient {
168
199
  // 保存用户提供的 apiKey
169
- constructor(config = {}) {
170
- this.config = createConfig(config);
171
- this.providedApiKey = config.apiKey;
200
+ constructor(config, providedApiKey) {
201
+ this.config = config;
202
+ this.providedApiKey = providedApiKey;
172
203
  validateConfig(this.config);
173
204
  const isBrowser = typeof globalThis.window !== "undefined" && typeof globalThis.localStorage !== "undefined";
174
205
  if (isBrowser) {
@@ -182,6 +213,15 @@ var SeacloudClient = class {
182
213
  });
183
214
  }
184
215
  }
216
+ /**
217
+ * 创建 SeacloudClient 实例(异步工厂方法)
218
+ * @param config 配置选项
219
+ * @returns SeacloudClient 实例
220
+ */
221
+ static async create(config = {}) {
222
+ const fullConfig = await createConfig(config);
223
+ return new _SeacloudClient(fullConfig, config.apiKey);
224
+ }
185
225
  /**
186
226
  * 创建一个新任务
187
227
  * @param endpoint API 端点路径(例如:/model/tasks)
@@ -251,6 +291,7 @@ var SeacloudClient = class {
251
291
  clearTimeout(timeoutId);
252
292
  if (!response.ok) {
253
293
  const errorBody = await response.text();
294
+ notifyParentError(response.status, errorBody);
254
295
  throw new SeacloudError(
255
296
  `HTTP ${response.status}: ${errorBody}`,
256
297
  response.status,
@@ -306,24 +347,9 @@ async function initSeacloud(apiKeyOrConfig, options) {
306
347
  apiKey = void 0;
307
348
  }
308
349
  if (!config.baseUrl) {
309
- try {
310
- const parentHost = await getHostFromParent(3e3);
311
- if (parentHost) {
312
- const currentHost = typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined" ? globalThis.window.location.host : "";
313
- const isDevelopment = checkIsDevelopmentHost(currentHost) || checkIsDevelopmentHost(parentHost);
314
- if (isDevelopment) {
315
- config.baseUrl = "https://proxy-rs.sg.seaverse.dev";
316
- console.log("[SeaCloud SDK] \u68C0\u6D4B\u5230\u5F00\u53D1\u73AF\u5883\uFF0C\u4F7F\u7528\u5F00\u53D1 baseUrl:", config.baseUrl);
317
- } else {
318
- config.baseUrl = "https://proxy-rs.seaverse.ai";
319
- console.log("[SeaCloud SDK] \u68C0\u6D4B\u5230\u6B63\u5F0F\u73AF\u5883\uFF0C\u4F7F\u7528\u6B63\u5F0F baseUrl:", config.baseUrl);
320
- }
321
- }
322
- } catch (error) {
323
- console.warn("[SeaCloud SDK] \u83B7\u53D6\u7236\u9875\u9762 host \u5931\u8D25\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E", error);
324
- }
350
+ config.baseUrl = await getBaseUrl();
325
351
  }
326
- globalConfig.client = new SeacloudClient({
352
+ globalConfig.client = await SeacloudClient.create({
327
353
  apiKey: apiKey || "",
328
354
  baseUrl: config.baseUrl,
329
355
  timeout: config.timeout,
@@ -337,11 +363,11 @@ async function initSeacloud(apiKeyOrConfig, options) {
337
363
  }
338
364
  return globalConfig.client;
339
365
  }
340
- function getClient() {
366
+ async function getClient() {
341
367
  if (globalConfig.client) {
342
368
  return globalConfig.client;
343
369
  }
344
- return new SeacloudClient({
370
+ return await SeacloudClient.create({
345
371
  // 不传 apiKey - 让 createConfig() 自动从环境变量/localStorage 读取
346
372
  // 不传 baseUrl - 让 createConfig() 自动从环境变量读取或使用默认值
347
373
  // 不传 timeout - 使用默认 30000ms
@@ -350,7 +376,7 @@ function getClient() {
350
376
 
351
377
  // src/api/llm_chat_completions.ts
352
378
  async function llmChatCompletions(params) {
353
- const client = getClient();
379
+ const client = await getClient();
354
380
  const config = client.getConfig();
355
381
  const url = `${config.baseUrl}/llm/chat/completions`;
356
382
  const token = await getApiToken(config.apiKey);
@@ -370,6 +396,7 @@ async function llmChatCompletions(params) {
370
396
  clearTimeout(timeoutId);
371
397
  if (!response.ok) {
372
398
  const errorBody = await response.text();
399
+ notifyParentError(response.status, errorBody);
373
400
  throw new SeacloudError(
374
401
  `HTTP ${response.status}: ${errorBody}`,
375
402
  response.status,
@@ -434,7 +461,7 @@ async function* parseStreamingResponse(response) {
434
461
 
435
462
  // src/api/agent_chat_completions.ts
436
463
  async function agentChatCompletions(params) {
437
- const client = getClient();
464
+ const client = await getClient();
438
465
  const config = client.getConfig();
439
466
  const url = `${config.baseUrl}/agent/api/v1/chat/completions`;
440
467
  const model = params.model || "custom_openai/vertex-ai-claude-sonnet-4.5";
@@ -465,6 +492,7 @@ async function agentChatCompletions(params) {
465
492
  clearTimeout(timeoutId);
466
493
  if (!response.ok) {
467
494
  const errorBody = await response.text();
495
+ notifyParentError(response.status, errorBody);
468
496
  throw new SeacloudError(
469
497
  `HTTP ${response.status}: ${errorBody}`,
470
498
  response.status,
@@ -636,7 +664,7 @@ function createTextMessage(role, text) {
636
664
 
637
665
  // src/api/app_search.ts
638
666
  async function appSearch(params) {
639
- const client = getClient();
667
+ const client = await getClient();
640
668
  const config = client.getConfig();
641
669
  const url = `${config.baseUrl}/model/v1/template/specs`;
642
670
  const controller = new AbortController();
@@ -681,7 +709,7 @@ async function scan(params) {
681
709
  if (!params.risk_types || params.risk_types.length === 0) {
682
710
  throw new SeacloudError("\u5FC5\u987B\u63D0\u4F9B\u81F3\u5C11\u4E00\u4E2A\u98CE\u9669\u7C7B\u578B");
683
711
  }
684
- const client = getClient();
712
+ const client = await getClient();
685
713
  const config = client.getConfig();
686
714
  const url = `${config.baseUrl}/scan`;
687
715
  const token = await getApiToken(config.apiKey);
@@ -874,7 +902,7 @@ async function testModel(model, options) {
874
902
  console.log(`Base URL: ${baseUrl}`);
875
903
  console.log(`Parameters:`, JSON.stringify(options.params, null, 2));
876
904
  console.log("");
877
- const client = new SeacloudClient({ apiKey, baseUrl });
905
+ const client = await SeacloudClient.create({ apiKey, baseUrl });
878
906
  try {
879
907
  console.log("Creating task...");
880
908
  const task = await client.createTask("/model/v1/generation", {
@@ -1064,7 +1092,7 @@ async function runAppGeneration(args) {
1064
1092
  }
1065
1093
  const apiKey = options.apiKey || process.env.API_SERVICE_TOKEN || "";
1066
1094
  const baseUrl = options.baseUrl || process.env.SEACLOUD_BASE_URL || "http://proxy.sg.seaverse.dev";
1067
- const client = new SeacloudClient({ apiKey, baseUrl });
1095
+ const client = await SeacloudClient.create({ apiKey, baseUrl });
1068
1096
  try {
1069
1097
  console.log("Creating task...");
1070
1098
  const task = await client.createTask("/model/v1/generation", {
@@ -1232,7 +1260,7 @@ async function runTaskStatus(taskId, args) {
1232
1260
  }
1233
1261
  const apiKey = options.apiKey || process.env.API_SERVICE_TOKEN || "";
1234
1262
  const baseUrl = options.baseUrl || process.env.SEACLOUD_BASE_URL || "http://proxy.sg.seaverse.dev";
1235
- const client = new SeacloudClient({ apiKey, baseUrl });
1263
+ const client = await SeacloudClient.create({ apiKey, baseUrl });
1236
1264
  console.log(`Querying task status...`);
1237
1265
  console.log(`Task ID: ${taskId}`);
1238
1266
  console.log(`Base URL: ${baseUrl}