@synova-cloud/sdk 1.0.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/LICENSE +21 -0
- package/README.md +475 -0
- package/dist/index.cjs +630 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +564 -0
- package/dist/index.d.ts +564 -0
- package/dist/index.js +620 -0
- package/dist/index.js.map +1 -0
- package/package.json +76 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
// src/errors/index.ts
|
|
2
|
+
var SynovaError = class extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "SynovaError";
|
|
6
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
var ApiSynovaError = class extends SynovaError {
|
|
10
|
+
code;
|
|
11
|
+
httpCode;
|
|
12
|
+
requestId;
|
|
13
|
+
timestamp;
|
|
14
|
+
constructor(response) {
|
|
15
|
+
super(response.message);
|
|
16
|
+
this.name = "ApiSynovaError";
|
|
17
|
+
this.code = response.code;
|
|
18
|
+
this.httpCode = response.httpCode;
|
|
19
|
+
this.requestId = response.requestId;
|
|
20
|
+
this.timestamp = response.timestamp;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
var AuthSynovaError = class extends SynovaError {
|
|
24
|
+
constructor(message = "Invalid or missing API key") {
|
|
25
|
+
super(message);
|
|
26
|
+
this.name = "AuthSynovaError";
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var NotFoundSynovaError = class extends SynovaError {
|
|
30
|
+
resourceType;
|
|
31
|
+
resourceId;
|
|
32
|
+
constructor(resourceType, resourceId) {
|
|
33
|
+
super(`${resourceType} not found: ${resourceId}`);
|
|
34
|
+
this.name = "NotFoundSynovaError";
|
|
35
|
+
this.resourceType = resourceType;
|
|
36
|
+
this.resourceId = resourceId;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
var RateLimitSynovaError = class extends SynovaError {
|
|
40
|
+
retryAfterMs;
|
|
41
|
+
constructor(message = "Rate limit exceeded", retryAfterMs) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.name = "RateLimitSynovaError";
|
|
44
|
+
this.retryAfterMs = retryAfterMs;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var TimeoutSynovaError = class extends SynovaError {
|
|
48
|
+
timeoutMs;
|
|
49
|
+
constructor(timeoutMs) {
|
|
50
|
+
super(`Request timed out after ${timeoutMs}ms`);
|
|
51
|
+
this.name = "TimeoutSynovaError";
|
|
52
|
+
this.timeoutMs = timeoutMs;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var NetworkSynovaError = class extends SynovaError {
|
|
56
|
+
cause;
|
|
57
|
+
constructor(message, cause) {
|
|
58
|
+
super(message);
|
|
59
|
+
this.name = "NetworkSynovaError";
|
|
60
|
+
this.cause = cause;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var ServerSynovaError = class extends SynovaError {
|
|
64
|
+
httpCode;
|
|
65
|
+
retryable;
|
|
66
|
+
constructor(httpCode, message) {
|
|
67
|
+
super(message || `Server error: ${httpCode}`);
|
|
68
|
+
this.name = "ServerSynovaError";
|
|
69
|
+
this.httpCode = httpCode;
|
|
70
|
+
this.retryable = true;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// src/utils/http.ts
|
|
75
|
+
var HttpClient = class {
|
|
76
|
+
config;
|
|
77
|
+
constructor(config) {
|
|
78
|
+
this.config = config;
|
|
79
|
+
}
|
|
80
|
+
async request(options) {
|
|
81
|
+
const url = this.buildUrl(options.path, options.query);
|
|
82
|
+
const { maxRetries } = this.config.retry;
|
|
83
|
+
let lastError = null;
|
|
84
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
85
|
+
try {
|
|
86
|
+
if (attempt > 0) {
|
|
87
|
+
const delay = this.calculateRetryDelay(attempt, lastError);
|
|
88
|
+
this.log(
|
|
89
|
+
`Retry attempt ${attempt}/${maxRetries} after ${delay}ms (strategy: ${this.config.retry.strategy})`
|
|
90
|
+
);
|
|
91
|
+
await this.sleep(delay);
|
|
92
|
+
}
|
|
93
|
+
return await this.makeRequest(url, options);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
lastError = error;
|
|
96
|
+
if (!this.isRetryable(error)) {
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
if (attempt === maxRetries) {
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
this.log(`Request failed, will retry: ${error.message}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
throw lastError;
|
|
106
|
+
}
|
|
107
|
+
async upload(options) {
|
|
108
|
+
const url = this.buildUrl(options.path);
|
|
109
|
+
const { maxRetries } = this.config.retry;
|
|
110
|
+
let lastError = null;
|
|
111
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
112
|
+
try {
|
|
113
|
+
if (attempt > 0) {
|
|
114
|
+
const delay = this.calculateRetryDelay(attempt, lastError);
|
|
115
|
+
this.log(
|
|
116
|
+
`Retry attempt ${attempt}/${maxRetries} after ${delay}ms (strategy: ${this.config.retry.strategy})`
|
|
117
|
+
);
|
|
118
|
+
await this.sleep(delay);
|
|
119
|
+
}
|
|
120
|
+
return await this.makeUploadRequest(url, options.formData);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
lastError = error;
|
|
123
|
+
if (!this.isRetryable(error)) {
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
if (attempt === maxRetries) {
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
this.log(`Upload failed, will retry: ${error.message}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
throw lastError;
|
|
133
|
+
}
|
|
134
|
+
async makeRequest(url, options) {
|
|
135
|
+
const controller = new AbortController();
|
|
136
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
137
|
+
this.log(`${options.method} ${url}`);
|
|
138
|
+
try {
|
|
139
|
+
const response = await fetch(url, {
|
|
140
|
+
method: options.method,
|
|
141
|
+
headers: {
|
|
142
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
143
|
+
"Content-Type": "application/json",
|
|
144
|
+
"User-Agent": "synova-cloud-sdk-node/0.1.0"
|
|
145
|
+
},
|
|
146
|
+
body: options.body ? JSON.stringify(options.body) : void 0,
|
|
147
|
+
signal: controller.signal
|
|
148
|
+
});
|
|
149
|
+
clearTimeout(timeoutId);
|
|
150
|
+
if (!response.ok) {
|
|
151
|
+
await this.handleErrorResponse(response);
|
|
152
|
+
}
|
|
153
|
+
const data = await response.json();
|
|
154
|
+
this.log(`Response: ${response.status}`);
|
|
155
|
+
return data;
|
|
156
|
+
} catch (error) {
|
|
157
|
+
clearTimeout(timeoutId);
|
|
158
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
159
|
+
throw new TimeoutSynovaError(this.config.timeout);
|
|
160
|
+
}
|
|
161
|
+
if (error instanceof ApiSynovaError || error instanceof AuthSynovaError || error instanceof NotFoundSynovaError || error instanceof RateLimitSynovaError || error instanceof ServerSynovaError) {
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
throw new NetworkSynovaError(
|
|
165
|
+
`Network request failed: ${error.message}`,
|
|
166
|
+
error
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async makeUploadRequest(url, formData) {
|
|
171
|
+
const controller = new AbortController();
|
|
172
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
173
|
+
this.log(`POST (upload) ${url}`);
|
|
174
|
+
try {
|
|
175
|
+
const response = await fetch(url, {
|
|
176
|
+
method: "POST",
|
|
177
|
+
headers: {
|
|
178
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
179
|
+
"User-Agent": "synova-cloud-sdk-node/0.1.0"
|
|
180
|
+
// Note: Content-Type is not set for FormData - browser/node sets it with boundary
|
|
181
|
+
},
|
|
182
|
+
body: formData,
|
|
183
|
+
signal: controller.signal
|
|
184
|
+
});
|
|
185
|
+
clearTimeout(timeoutId);
|
|
186
|
+
if (!response.ok) {
|
|
187
|
+
await this.handleErrorResponse(response);
|
|
188
|
+
}
|
|
189
|
+
const data = await response.json();
|
|
190
|
+
this.log(`Response: ${response.status}`);
|
|
191
|
+
return data;
|
|
192
|
+
} catch (error) {
|
|
193
|
+
clearTimeout(timeoutId);
|
|
194
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
195
|
+
throw new TimeoutSynovaError(this.config.timeout);
|
|
196
|
+
}
|
|
197
|
+
if (error instanceof ApiSynovaError || error instanceof AuthSynovaError || error instanceof NotFoundSynovaError || error instanceof RateLimitSynovaError || error instanceof ServerSynovaError) {
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
throw new NetworkSynovaError(
|
|
201
|
+
`Upload request failed: ${error.message}`,
|
|
202
|
+
error
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async handleErrorResponse(response) {
|
|
207
|
+
const status = response.status;
|
|
208
|
+
let errorBody = null;
|
|
209
|
+
try {
|
|
210
|
+
errorBody = await response.json();
|
|
211
|
+
} catch {
|
|
212
|
+
}
|
|
213
|
+
if (status === 401) {
|
|
214
|
+
throw new AuthSynovaError(errorBody?.message);
|
|
215
|
+
}
|
|
216
|
+
if (status === 404) {
|
|
217
|
+
throw new NotFoundSynovaError("Resource", errorBody?.message || "unknown");
|
|
218
|
+
}
|
|
219
|
+
if (status === 429) {
|
|
220
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
221
|
+
const retryAfterMs = retryAfter ? parseInt(retryAfter, 10) * 1e3 : void 0;
|
|
222
|
+
throw new RateLimitSynovaError(errorBody?.message, retryAfterMs);
|
|
223
|
+
}
|
|
224
|
+
if (status >= 500) {
|
|
225
|
+
throw new ServerSynovaError(status, errorBody?.message);
|
|
226
|
+
}
|
|
227
|
+
if (errorBody) {
|
|
228
|
+
throw new ApiSynovaError(errorBody);
|
|
229
|
+
}
|
|
230
|
+
throw new ApiSynovaError({
|
|
231
|
+
code: "UNKNOWN_ERROR",
|
|
232
|
+
httpCode: status,
|
|
233
|
+
message: `HTTP ${status}: ${response.statusText}`,
|
|
234
|
+
requestId: "unknown",
|
|
235
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
buildUrl(path, query) {
|
|
239
|
+
const url = new URL(path, this.config.baseUrl);
|
|
240
|
+
if (query) {
|
|
241
|
+
for (const [key, value] of Object.entries(query)) {
|
|
242
|
+
if (value !== void 0) {
|
|
243
|
+
url.searchParams.set(key, value);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return url.toString();
|
|
248
|
+
}
|
|
249
|
+
isRetryable(error) {
|
|
250
|
+
if (error instanceof RateLimitSynovaError) return true;
|
|
251
|
+
if (error instanceof ServerSynovaError) return true;
|
|
252
|
+
if (error instanceof NetworkSynovaError) return true;
|
|
253
|
+
if (error instanceof TimeoutSynovaError) return true;
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
calculateRetryDelay(attempt, error) {
|
|
257
|
+
const { strategy, initialDelayMs, maxDelayMs, backoffMultiplier } = this.config.retry;
|
|
258
|
+
if (error instanceof RateLimitSynovaError && error.retryAfterMs) {
|
|
259
|
+
return Math.min(error.retryAfterMs, maxDelayMs);
|
|
260
|
+
}
|
|
261
|
+
let baseDelay;
|
|
262
|
+
if (strategy === "linear") {
|
|
263
|
+
baseDelay = initialDelayMs * attempt;
|
|
264
|
+
} else {
|
|
265
|
+
baseDelay = initialDelayMs * Math.pow(backoffMultiplier, attempt - 1);
|
|
266
|
+
}
|
|
267
|
+
const jitter = baseDelay * 0.1 * (Math.random() * 2 - 1);
|
|
268
|
+
const delay = baseDelay + jitter;
|
|
269
|
+
return Math.min(Math.max(delay, 0), maxDelayMs);
|
|
270
|
+
}
|
|
271
|
+
sleep(ms) {
|
|
272
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
273
|
+
}
|
|
274
|
+
log(message) {
|
|
275
|
+
if (this.config.debug) {
|
|
276
|
+
this.config.logger.debug(`[Synova SDK] ${message}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
// src/resources/prompts.ts
|
|
282
|
+
var PromptsResource = class {
|
|
283
|
+
constructor(http) {
|
|
284
|
+
this.http = http;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Get a prompt by ID (returns version with 'latest' tag)
|
|
288
|
+
*
|
|
289
|
+
* @param promptId - The prompt ID (e.g., 'prm_abc123')
|
|
290
|
+
* @param options - Optional settings
|
|
291
|
+
* @returns The prompt data
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```ts
|
|
295
|
+
* // Get default (latest) version
|
|
296
|
+
* const prompt = await client.prompts.get('prm_abc123');
|
|
297
|
+
*
|
|
298
|
+
* // Get by specific tag
|
|
299
|
+
* const production = await client.prompts.get('prm_abc123', { tag: 'production' });
|
|
300
|
+
*
|
|
301
|
+
* // Get specific version
|
|
302
|
+
* const v2 = await client.prompts.get('prm_abc123', { version: '2.0.0' });
|
|
303
|
+
* ```
|
|
304
|
+
*/
|
|
305
|
+
async get(promptId, options) {
|
|
306
|
+
if (options?.version) {
|
|
307
|
+
return this.http.request({
|
|
308
|
+
method: "GET",
|
|
309
|
+
path: `/api/v1/prompts/${promptId}/versions/${options.version}`
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
const tag = options?.tag || "latest";
|
|
313
|
+
if (tag === "latest") {
|
|
314
|
+
return this.http.request({
|
|
315
|
+
method: "GET",
|
|
316
|
+
path: `/api/v1/prompts/${promptId}`
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
return this.http.request({
|
|
320
|
+
method: "GET",
|
|
321
|
+
path: `/api/v1/prompts/${promptId}/tags/${tag}`
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Execute a prompt with 'latest' tag
|
|
326
|
+
*
|
|
327
|
+
* @param promptId - The prompt ID
|
|
328
|
+
* @param options - Execution options including provider, model and variables
|
|
329
|
+
* @returns The execution response
|
|
330
|
+
*
|
|
331
|
+
* @example
|
|
332
|
+
* ```ts
|
|
333
|
+
* const result = await client.prompts.execute('prm_abc123', {
|
|
334
|
+
* provider: 'openai',
|
|
335
|
+
* model: 'gpt-4o',
|
|
336
|
+
* variables: { topic: 'TypeScript' },
|
|
337
|
+
* });
|
|
338
|
+
*
|
|
339
|
+
* if (result.type === 'message') {
|
|
340
|
+
* console.log(result.content);
|
|
341
|
+
* }
|
|
342
|
+
*
|
|
343
|
+
* // Image generation
|
|
344
|
+
* const imageResult = await client.prompts.execute('prm_image123', {
|
|
345
|
+
* provider: 'google',
|
|
346
|
+
* model: 'gemini-2.0-flash-exp',
|
|
347
|
+
* variables: { style: 'modern' },
|
|
348
|
+
* });
|
|
349
|
+
*
|
|
350
|
+
* if (imageResult.type === 'image') {
|
|
351
|
+
* console.log('Generated images:', imageResult.files);
|
|
352
|
+
* }
|
|
353
|
+
* ```
|
|
354
|
+
*/
|
|
355
|
+
async execute(promptId, options) {
|
|
356
|
+
const body = {
|
|
357
|
+
provider: options.provider,
|
|
358
|
+
model: options.model
|
|
359
|
+
};
|
|
360
|
+
if (options.variables !== void 0) body.variables = options.variables;
|
|
361
|
+
if (options.messages !== void 0) body.messages = options.messages;
|
|
362
|
+
if (options.tag !== void 0) body.tag = options.tag;
|
|
363
|
+
if (options.version !== void 0) body.version = options.version;
|
|
364
|
+
if (options.metadata !== void 0) body.metadata = options.metadata;
|
|
365
|
+
if (options.parameters !== void 0) body.parameters = options.parameters;
|
|
366
|
+
if (options.responseSchema !== void 0) body.responseSchema = options.responseSchema;
|
|
367
|
+
return this.http.request({
|
|
368
|
+
method: "POST",
|
|
369
|
+
path: `/api/v1/prompts/${promptId}/run`,
|
|
370
|
+
body
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Execute a prompt by tag
|
|
375
|
+
*
|
|
376
|
+
* @param promptId - The prompt ID
|
|
377
|
+
* @param tag - The tag (e.g., 'latest', 'production', 'staging')
|
|
378
|
+
* @param options - Execution options
|
|
379
|
+
* @returns The execution response
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```ts
|
|
383
|
+
* const result = await client.prompts.executeByTag('prm_abc123', 'production', {
|
|
384
|
+
* provider: 'openai',
|
|
385
|
+
* model: 'gpt-4o',
|
|
386
|
+
* variables: { topic: 'TypeScript' },
|
|
387
|
+
* });
|
|
388
|
+
* ```
|
|
389
|
+
*/
|
|
390
|
+
async executeByTag(promptId, tag, options) {
|
|
391
|
+
return this.http.request({
|
|
392
|
+
method: "POST",
|
|
393
|
+
path: `/api/v1/prompts/${promptId}/run`,
|
|
394
|
+
body: {
|
|
395
|
+
tag,
|
|
396
|
+
provider: options.provider,
|
|
397
|
+
model: options.model,
|
|
398
|
+
variables: options.variables,
|
|
399
|
+
messages: options.messages,
|
|
400
|
+
metadata: options.metadata,
|
|
401
|
+
parameters: options.parameters
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Execute a prompt by version
|
|
407
|
+
*
|
|
408
|
+
* @param promptId - The prompt ID
|
|
409
|
+
* @param version - The semantic version (e.g., '1.0.0', '2.1.0')
|
|
410
|
+
* @param options - Execution options
|
|
411
|
+
* @returns The execution response
|
|
412
|
+
*
|
|
413
|
+
* @example
|
|
414
|
+
* ```ts
|
|
415
|
+
* const result = await client.prompts.executeByVersion('prm_abc123', '1.2.0', {
|
|
416
|
+
* provider: 'openai',
|
|
417
|
+
* model: 'gpt-4o',
|
|
418
|
+
* variables: { topic: 'TypeScript' },
|
|
419
|
+
* });
|
|
420
|
+
* ```
|
|
421
|
+
*/
|
|
422
|
+
async executeByVersion(promptId, version, options) {
|
|
423
|
+
return this.http.request({
|
|
424
|
+
method: "POST",
|
|
425
|
+
path: `/api/v1/prompts/${promptId}/run`,
|
|
426
|
+
body: {
|
|
427
|
+
version,
|
|
428
|
+
provider: options.provider,
|
|
429
|
+
model: options.model,
|
|
430
|
+
variables: options.variables,
|
|
431
|
+
messages: options.messages,
|
|
432
|
+
metadata: options.metadata,
|
|
433
|
+
parameters: options.parameters
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
// src/resources/models.ts
|
|
440
|
+
var ModelsResource = class {
|
|
441
|
+
constructor(http) {
|
|
442
|
+
this.http = http;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* List all available models
|
|
446
|
+
*
|
|
447
|
+
* @param options - Optional filters
|
|
448
|
+
* @returns List of providers with their models
|
|
449
|
+
*
|
|
450
|
+
* @example
|
|
451
|
+
* ```ts
|
|
452
|
+
* // Get all models
|
|
453
|
+
* const { providers } = await client.models.list();
|
|
454
|
+
*
|
|
455
|
+
* // Filter by type
|
|
456
|
+
* const imageModels = await client.models.list({ type: 'image' });
|
|
457
|
+
*
|
|
458
|
+
* // Filter by capability
|
|
459
|
+
* const functionCallingModels = await client.models.list({
|
|
460
|
+
* capability: 'function_calling',
|
|
461
|
+
* });
|
|
462
|
+
*
|
|
463
|
+
* // Filter by provider
|
|
464
|
+
* const openaiModels = await client.models.list({ provider: 'openai' });
|
|
465
|
+
* ```
|
|
466
|
+
*/
|
|
467
|
+
async list(options) {
|
|
468
|
+
return this.http.request({
|
|
469
|
+
method: "GET",
|
|
470
|
+
path: "/api/v1/models",
|
|
471
|
+
query: {
|
|
472
|
+
type: options?.type,
|
|
473
|
+
capability: options?.capability,
|
|
474
|
+
provider: options?.provider
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Get models for a specific provider
|
|
480
|
+
*
|
|
481
|
+
* @param provider - Provider ID (e.g., 'openai', 'anthropic')
|
|
482
|
+
* @returns List of models for the provider
|
|
483
|
+
*
|
|
484
|
+
* @example
|
|
485
|
+
* ```ts
|
|
486
|
+
* const { models } = await client.models.getByProvider('openai');
|
|
487
|
+
* ```
|
|
488
|
+
*/
|
|
489
|
+
async getByProvider(provider) {
|
|
490
|
+
const response = await this.http.request({
|
|
491
|
+
method: "GET",
|
|
492
|
+
path: `/api/v1/models/${provider}`
|
|
493
|
+
});
|
|
494
|
+
return response.models;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Get a specific model
|
|
498
|
+
*
|
|
499
|
+
* @param provider - Provider ID
|
|
500
|
+
* @param model - Model ID
|
|
501
|
+
* @returns Model details
|
|
502
|
+
*
|
|
503
|
+
* @example
|
|
504
|
+
* ```ts
|
|
505
|
+
* const model = await client.models.get('openai', 'gpt-4o');
|
|
506
|
+
* console.log(model.capabilities);
|
|
507
|
+
* console.log(model.limits);
|
|
508
|
+
* ```
|
|
509
|
+
*/
|
|
510
|
+
async get(provider, model) {
|
|
511
|
+
return this.http.request({
|
|
512
|
+
method: "GET",
|
|
513
|
+
path: `/api/v1/models/${provider}/${model}`
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
// src/resources/files.ts
|
|
519
|
+
var FilesResource = class {
|
|
520
|
+
constructor(http) {
|
|
521
|
+
this.http = http;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Upload files for use in prompt execution
|
|
525
|
+
*
|
|
526
|
+
* @param files - Array of File or Blob objects to upload
|
|
527
|
+
* @param options - Upload options including projectId
|
|
528
|
+
* @returns Upload response with file metadata
|
|
529
|
+
*
|
|
530
|
+
* @example
|
|
531
|
+
* ```ts
|
|
532
|
+
* // Upload files
|
|
533
|
+
* const result = await client.files.upload(
|
|
534
|
+
* [file1, file2],
|
|
535
|
+
* { projectId: 'prj_abc123' }
|
|
536
|
+
* );
|
|
537
|
+
*
|
|
538
|
+
* console.log('Uploaded files:', result.data);
|
|
539
|
+
*
|
|
540
|
+
* // Use uploaded file in prompt execution
|
|
541
|
+
* const response = await client.prompts.execute('prm_abc123', {
|
|
542
|
+
* provider: 'openai',
|
|
543
|
+
* model: 'gpt-4o',
|
|
544
|
+
* messages: [
|
|
545
|
+
* {
|
|
546
|
+
* role: 'user',
|
|
547
|
+
* content: 'Describe this image',
|
|
548
|
+
* files: [{ fileId: result.data[0].id }],
|
|
549
|
+
* },
|
|
550
|
+
* ],
|
|
551
|
+
* });
|
|
552
|
+
* ```
|
|
553
|
+
*/
|
|
554
|
+
async upload(files, options) {
|
|
555
|
+
const formData = new FormData();
|
|
556
|
+
for (const file of files) {
|
|
557
|
+
formData.append("files", file);
|
|
558
|
+
}
|
|
559
|
+
formData.append("projectId", options.projectId);
|
|
560
|
+
return this.http.upload({
|
|
561
|
+
path: "/api/v1/files/upload",
|
|
562
|
+
formData
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
// src/client.ts
|
|
568
|
+
var DEFAULT_BASE_URL = "https://api.synova.cloud";
|
|
569
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
570
|
+
var DEFAULT_RETRY = {
|
|
571
|
+
maxRetries: 3,
|
|
572
|
+
strategy: "exponential",
|
|
573
|
+
initialDelayMs: 1e3,
|
|
574
|
+
maxDelayMs: 3e4,
|
|
575
|
+
backoffMultiplier: 2
|
|
576
|
+
};
|
|
577
|
+
var DEFAULT_LOGGER = {
|
|
578
|
+
debug: (message, ...args) => console.debug(message, ...args),
|
|
579
|
+
info: (message, ...args) => console.info(message, ...args),
|
|
580
|
+
warn: (message, ...args) => console.warn(message, ...args),
|
|
581
|
+
error: (messageOrError, ...args) => console.error(messageOrError, ...args)
|
|
582
|
+
};
|
|
583
|
+
var SynovaCloudSdk = class {
|
|
584
|
+
prompts;
|
|
585
|
+
models;
|
|
586
|
+
files;
|
|
587
|
+
http;
|
|
588
|
+
/**
|
|
589
|
+
* Create a new Synova Cloud SDK client
|
|
590
|
+
*
|
|
591
|
+
* @param apiKey - Your Synova API key
|
|
592
|
+
* @param config - Optional configuration
|
|
593
|
+
*/
|
|
594
|
+
constructor(apiKey, config) {
|
|
595
|
+
if (!apiKey) {
|
|
596
|
+
throw new Error("API key is required");
|
|
597
|
+
}
|
|
598
|
+
this.http = new HttpClient({
|
|
599
|
+
baseUrl: config?.baseUrl ?? DEFAULT_BASE_URL,
|
|
600
|
+
apiKey,
|
|
601
|
+
timeout: config?.timeout ?? DEFAULT_TIMEOUT,
|
|
602
|
+
retry: {
|
|
603
|
+
maxRetries: config?.retry?.maxRetries ?? DEFAULT_RETRY.maxRetries,
|
|
604
|
+
strategy: config?.retry?.strategy ?? DEFAULT_RETRY.strategy,
|
|
605
|
+
initialDelayMs: config?.retry?.initialDelayMs ?? DEFAULT_RETRY.initialDelayMs,
|
|
606
|
+
maxDelayMs: config?.retry?.maxDelayMs ?? DEFAULT_RETRY.maxDelayMs,
|
|
607
|
+
backoffMultiplier: config?.retry?.backoffMultiplier ?? DEFAULT_RETRY.backoffMultiplier
|
|
608
|
+
},
|
|
609
|
+
debug: config?.debug ?? false,
|
|
610
|
+
logger: config?.logger ?? DEFAULT_LOGGER
|
|
611
|
+
});
|
|
612
|
+
this.prompts = new PromptsResource(this.http);
|
|
613
|
+
this.models = new ModelsResource(this.http);
|
|
614
|
+
this.files = new FilesResource(this.http);
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
export { ApiSynovaError, AuthSynovaError, NetworkSynovaError, NotFoundSynovaError, RateLimitSynovaError, ServerSynovaError, SynovaCloudSdk, SynovaError, TimeoutSynovaError };
|
|
619
|
+
//# sourceMappingURL=index.js.map
|
|
620
|
+
//# sourceMappingURL=index.js.map
|