skytells 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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Skytells, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # Skytells JavaScript/TypeScript SDK
2
+
3
+ The official JavaScript/TypeScript SDK for interacting with the [Skytells](https://skytells.ai) API. Edge-compatible with Cloudflare Pages, Vercel Edge Functions, and more.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install skytells
9
+ # or
10
+ yarn add skytells
11
+ # or
12
+ pnpm add skytells
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { createClient } from 'skytells';
19
+
20
+ // Initialize the client with your API key
21
+ const skytells = createClient('your-api-key-here');
22
+
23
+ // Make a prediction
24
+ async function makePrediction() {
25
+ try {
26
+ const prediction = await skytells.predict({
27
+ model: 'model-name',
28
+ input: {
29
+ prompt: 'Your prompt here'
30
+ }
31
+ });
32
+
33
+ console.log('Prediction ID:', prediction.id);
34
+ console.log('Status:', prediction.status);
35
+ console.log('Output:', prediction.output);
36
+ } catch (error) {
37
+ console.error('Error making prediction:', error);
38
+ }
39
+ }
40
+
41
+ // List available models
42
+ async function listModels() {
43
+ try {
44
+ const models = await skytells.listModels();
45
+ console.log('Available models:', models);
46
+ } catch (error) {
47
+ console.error('Error listing models:', error);
48
+ }
49
+ }
50
+
51
+ // Get a prediction by ID
52
+ async function getPrediction(id) {
53
+ try {
54
+ const prediction = await skytells.getPrediction(id);
55
+ console.log('Prediction:', prediction);
56
+ } catch (error) {
57
+ console.error('Error getting prediction:', error);
58
+ }
59
+ }
60
+ ```
61
+
62
+ ## Edge Compatibility
63
+
64
+ This SDK is fully compatible with edge environments including:
65
+
66
+ - Cloudflare Workers and Pages
67
+ - Vercel Edge Functions
68
+ - Netlify Edge Functions
69
+ - Deno Deploy
70
+ - Any environment with Fetch API support
71
+
72
+ To use a custom API endpoint or proxy:
73
+
74
+ ```typescript
75
+ import { createClient } from 'skytells';
76
+
77
+ // Use a custom API endpoint or proxy
78
+ const client = createClient('your-api-key', {
79
+ baseUrl: 'https://your-proxy.example.com/v1'
80
+ });
81
+ ```
82
+
83
+ ## API Reference
84
+
85
+ ### Creating a Client
86
+
87
+ ```typescript
88
+ import { createClient } from 'skytells';
89
+
90
+ // With API key (authenticated)
91
+ const client = createClient('your-api-key');
92
+
93
+ // Without API key (unauthenticated, limited functionality)
94
+ const unauthenticatedClient = createClient();
95
+
96
+ // With options
97
+ const clientWithOptions = createClient('your-api-key', {
98
+ baseUrl: 'https://api.skytells.ai/v1', // Custom API URL
99
+ timeout: 30000 // Custom timeout in ms
100
+ });
101
+ ```
102
+
103
+ ### Predictions
104
+
105
+ #### Make a Prediction
106
+
107
+ ```typescript
108
+ const prediction = await client.predict({
109
+ model: 'model-name',
110
+ input: {
111
+ // Model-specific inputs
112
+ prompt: 'Your prompt here',
113
+ // Other parameters...
114
+ }
115
+ });
116
+ ```
117
+
118
+ #### Get a Prediction by ID
119
+
120
+ ```typescript
121
+ const prediction = await client.getPrediction('prediction-id');
122
+ ```
123
+
124
+ #### Stream a Prediction
125
+
126
+ ```typescript
127
+ const prediction = await client.streamPrediction('prediction-id');
128
+ ```
129
+
130
+ #### Cancel a Prediction
131
+
132
+ ```typescript
133
+ const prediction = await client.cancelPrediction('prediction-id');
134
+ ```
135
+
136
+ #### Delete a Prediction
137
+
138
+ ```typescript
139
+ const prediction = await client.deletePrediction('prediction-id');
140
+ ```
141
+
142
+ ### Models
143
+
144
+ #### List All Models
145
+
146
+ ```typescript
147
+ const models = await client.listModels();
148
+ ```
149
+
150
+ ## TypeScript Support
151
+
152
+ This SDK is built with TypeScript and provides full type definitions for all methods and responses.
153
+
154
+ ## Error Handling
155
+
156
+ All API methods return promises that may reject with a `SkytellsError`. The SDK parses API error responses into this structured format:
157
+
158
+ ```typescript
159
+ import { createClient, SkytellsError } from 'skytells';
160
+
161
+ try {
162
+ const prediction = await client.predict({
163
+ model: 'model-name',
164
+ input: { prompt: 'Your prompt' }
165
+ });
166
+ } catch (error) {
167
+ if (error instanceof SkytellsError) {
168
+ console.error('Error message:', error.message);
169
+ console.error('Error ID:', error.errorId); // Example: "VALIDATION_ERROR"
170
+ console.error('Error details:', error.details); // Detailed error information
171
+ console.error('HTTP status:', error.httpStatus); // HTTP status code (e.g., 422)
172
+ } else {
173
+ console.error('Unknown error:', error);
174
+ }
175
+ }
176
+ ```
177
+
178
+ ### Common Error IDs
179
+
180
+ - `VALIDATION_ERROR` - Request parameters failed validation
181
+ - `AUTHENTICATION_ERROR` - Invalid or missing API key
182
+ - `RATE_LIMIT_EXCEEDED` - Too many requests
183
+ - `RESOURCE_NOT_FOUND` - The requested resource doesn't exist
184
+ - `NETWORK_ERROR` - Connection issue with the API
185
+ - `REQUEST_TIMEOUT` - Request took too long to complete
186
+ - `SERVER_ERROR` - The server responded with a non-JSON response (e.g., HTML error page)
187
+ - `INVALID_JSON` - The server returned invalid JSON content
188
+
189
+ ### Non-JSON Response Handling
190
+
191
+ The SDK automatically handles cases when the server doesn't respond with valid JSON:
192
+
193
+ ```typescript
194
+ try {
195
+ const models = await client.listModels();
196
+ } catch (error) {
197
+ if (error instanceof SkytellsError) {
198
+ if (error.errorId === 'SERVER_ERROR') {
199
+ console.error('The server returned a non-JSON response:', error.message);
200
+ console.error('Response content excerpt:', error.details);
201
+ // This could indicate a server outage or maintenance
202
+ } else if (error.errorId === 'INVALID_JSON') {
203
+ console.error('The server returned malformed JSON:', error.message);
204
+ console.error('Response content excerpt:', error.details);
205
+ // This could indicate an API bug or server issue
206
+ }
207
+ }
208
+ }
209
+ ```
210
+
211
+ ## Development
212
+
213
+ ```bash
214
+ # Install dependencies
215
+ npm install
216
+
217
+ # Build the SDK
218
+ npm run build
219
+
220
+ # Run tests
221
+ npm test
222
+
223
+ # Run linting
224
+ npm run lint
225
+ ```
226
+
227
+ ## License
228
+
229
+ MIT
@@ -0,0 +1,59 @@
1
+ const { HTTP } = require("./http.js");
2
+ const { ENDPOINTS } = require("./endpoints.js");
3
+ export class SkytellsClient {
4
+ /**
5
+ * Creates a new Skytells client
6
+ * @param apiKey Your Skytells API key
7
+ * @param options Configuration options
8
+ */
9
+ constructor(apiKey, options = {}) {
10
+ this.http = new HTTP(apiKey, options.baseUrl, options.timeout);
11
+ }
12
+ /**
13
+ * Send a prediction request to the Skytells API
14
+ * @param payload The prediction request parameters
15
+ * @returns A promise that resolves to the prediction response
16
+ */
17
+ async predict(payload) {
18
+ return this.http.request('POST', ENDPOINTS.PREDICT, payload);
19
+ }
20
+ /**
21
+ * Get a prediction by ID
22
+ * @param id The prediction ID
23
+ * @returns A promise that resolves to the prediction response
24
+ */
25
+ async getPrediction(id) {
26
+ return this.http.request('GET', ENDPOINTS.PREDICTION_BY_ID(id));
27
+ }
28
+ /**
29
+ * List all available models
30
+ * @returns A promise that resolves to an array of models
31
+ */
32
+ async listModels() {
33
+ return this.http.request('GET', ENDPOINTS.MODELS);
34
+ }
35
+ /**
36
+ * Stream a prediction by ID
37
+ * @param id The prediction ID
38
+ * @returns A promise that resolves to the prediction response
39
+ */
40
+ async streamPrediction(id) {
41
+ return this.http.request('GET', ENDPOINTS.STREAM_PREDICTION_BY_ID(id));
42
+ }
43
+ /**
44
+ * Cancel a prediction by ID
45
+ * @param id The prediction ID
46
+ * @returns A promise that resolves to the prediction response
47
+ */
48
+ async cancelPrediction(id) {
49
+ return this.http.request('POST', ENDPOINTS.CANCEL_PREDICTION_BY_ID(id));
50
+ }
51
+ /**
52
+ * Delete a prediction by ID
53
+ * @param id The prediction ID
54
+ * @returns A promise that resolves to the prediction response
55
+ */
56
+ async deletePrediction(id) {
57
+ return this.http.request('DELETE', ENDPOINTS.DELETE_PREDICTION_BY_ID(id));
58
+ }
59
+ }
@@ -0,0 +1,45 @@
1
+ import { PredictionRequest, PredictionResponse, Model, ClientOptions } from './types/index.js';
2
+ export declare class SkytellsClient {
3
+ private http;
4
+ /**
5
+ * Creates a new Skytells client
6
+ * @param apiKey Your Skytells API key
7
+ * @param options Configuration options
8
+ */
9
+ constructor(apiKey?: string, options?: ClientOptions);
10
+ /**
11
+ * Send a prediction request to the Skytells API
12
+ * @param payload The prediction request parameters
13
+ * @returns A promise that resolves to the prediction response
14
+ */
15
+ predict(payload: PredictionRequest): Promise<PredictionResponse>;
16
+ /**
17
+ * Get a prediction by ID
18
+ * @param id The prediction ID
19
+ * @returns A promise that resolves to the prediction response
20
+ */
21
+ getPrediction(id: string): Promise<PredictionResponse>;
22
+ /**
23
+ * List all available models
24
+ * @returns A promise that resolves to an array of models
25
+ */
26
+ listModels(): Promise<Model[]>;
27
+ /**
28
+ * Stream a prediction by ID
29
+ * @param id The prediction ID
30
+ * @returns A promise that resolves to the prediction response
31
+ */
32
+ streamPrediction(id: string): Promise<PredictionResponse>;
33
+ /**
34
+ * Cancel a prediction by ID
35
+ * @param id The prediction ID
36
+ * @returns A promise that resolves to the prediction response
37
+ */
38
+ cancelPrediction(id: string): Promise<PredictionResponse>;
39
+ /**
40
+ * Delete a prediction by ID
41
+ * @param id The prediction ID
42
+ * @returns A promise that resolves to the prediction response
43
+ */
44
+ deletePrediction(id: string): Promise<PredictionResponse>;
45
+ }
package/dist/client.js ADDED
@@ -0,0 +1,59 @@
1
+ import { HTTP } from './http.js';
2
+ import { ENDPOINTS } from './endpoints.js';
3
+ export class SkytellsClient {
4
+ /**
5
+ * Creates a new Skytells client
6
+ * @param apiKey Your Skytells API key
7
+ * @param options Configuration options
8
+ */
9
+ constructor(apiKey, options = {}) {
10
+ this.http = new HTTP(apiKey, options.baseUrl, options.timeout);
11
+ }
12
+ /**
13
+ * Send a prediction request to the Skytells API
14
+ * @param payload The prediction request parameters
15
+ * @returns A promise that resolves to the prediction response
16
+ */
17
+ async predict(payload) {
18
+ return this.http.request('POST', ENDPOINTS.PREDICT, payload);
19
+ }
20
+ /**
21
+ * Get a prediction by ID
22
+ * @param id The prediction ID
23
+ * @returns A promise that resolves to the prediction response
24
+ */
25
+ async getPrediction(id) {
26
+ return this.http.request('GET', ENDPOINTS.PREDICTION_BY_ID(id));
27
+ }
28
+ /**
29
+ * List all available models
30
+ * @returns A promise that resolves to an array of models
31
+ */
32
+ async listModels() {
33
+ return this.http.request('GET', ENDPOINTS.MODELS);
34
+ }
35
+ /**
36
+ * Stream a prediction by ID
37
+ * @param id The prediction ID
38
+ * @returns A promise that resolves to the prediction response
39
+ */
40
+ async streamPrediction(id) {
41
+ return this.http.request('GET', ENDPOINTS.STREAM_PREDICTION_BY_ID(id));
42
+ }
43
+ /**
44
+ * Cancel a prediction by ID
45
+ * @param id The prediction ID
46
+ * @returns A promise that resolves to the prediction response
47
+ */
48
+ async cancelPrediction(id) {
49
+ return this.http.request('POST', ENDPOINTS.CANCEL_PREDICTION_BY_ID(id));
50
+ }
51
+ /**
52
+ * Delete a prediction by ID
53
+ * @param id The prediction ID
54
+ * @returns A promise that resolves to the prediction response
55
+ */
56
+ async deletePrediction(id) {
57
+ return this.http.request('DELETE', ENDPOINTS.DELETE_PREDICTION_BY_ID(id));
58
+ }
59
+ }
@@ -0,0 +1,9 @@
1
+ const API_BASE_URL = module.exports.API_BASE_URL = "https://api.skytells.ai/v1";
2
+ const ENDPOINTS = module.exports.ENDPOINTS = {
3
+ PREDICT: "/predict",
4
+ MODELS: "/models",
5
+ PREDICTION_BY_ID: (id) => `/predictions/${id}`,
6
+ STREAM_PREDICTION_BY_ID: (id) => `/predictions/${id}/stream`,
7
+ CANCEL_PREDICTION_BY_ID: (id) => `/predictions/${id}/cancel`,
8
+ DELETE_PREDICTION_BY_ID: (id) => `/predictions/${id}/delete`,
9
+ };
@@ -0,0 +1,9 @@
1
+ export declare const API_BASE_URL = "https://api.skytells.ai/v1";
2
+ export declare const ENDPOINTS: {
3
+ PREDICT: string;
4
+ MODELS: string;
5
+ PREDICTION_BY_ID: (id: string) => string;
6
+ STREAM_PREDICTION_BY_ID: (id: string) => string;
7
+ CANCEL_PREDICTION_BY_ID: (id: string) => string;
8
+ DELETE_PREDICTION_BY_ID: (id: string) => string;
9
+ };
@@ -0,0 +1,9 @@
1
+ export const API_BASE_URL = "https://api.skytells.ai/v1";
2
+ export const ENDPOINTS = {
3
+ PREDICT: "/predict",
4
+ MODELS: "/models",
5
+ PREDICTION_BY_ID: (id) => `/predictions/${id}`,
6
+ STREAM_PREDICTION_BY_ID: (id) => `/predictions/${id}/stream`,
7
+ CANCEL_PREDICTION_BY_ID: (id) => `/predictions/${id}/cancel`,
8
+ DELETE_PREDICTION_BY_ID: (id) => `/predictions/${id}/delete`,
9
+ };
package/dist/http.cjs ADDED
@@ -0,0 +1,118 @@
1
+ const { API_BASE_URL } = require("./endpoints.js");
2
+ const { SkytellsError } = require("./types/shared.types.js");
3
+ // Default timeout in milliseconds
4
+ // 60 seconds
5
+ const DEFAULT_TIMEOUT = 60000;
6
+ export class HTTP {
7
+ constructor(apiKey, baseUrl = API_BASE_URL, timeout = DEFAULT_TIMEOUT) {
8
+ this.apiKey = apiKey;
9
+ this.baseUrl = baseUrl;
10
+ this.timeout = timeout;
11
+ }
12
+ async request(method, path, data) {
13
+ const headers = {
14
+ 'Content-Type': 'application/json',
15
+ };
16
+ if (this.apiKey) {
17
+ headers['x-api-key'] = this.apiKey;
18
+ }
19
+ const options = {
20
+ method,
21
+ headers,
22
+ };
23
+ if (method === 'POST' && data) {
24
+ options.body = JSON.stringify(data);
25
+ }
26
+ // Add AbortController for timeout handling
27
+ const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
28
+ if (controller) {
29
+ options.signal = controller.signal;
30
+ }
31
+ // Set up timeout if AbortController is available
32
+ let timeoutId = null;
33
+ if (controller) {
34
+ timeoutId = setTimeout(() => {
35
+ controller.abort();
36
+ }, this.timeout);
37
+ }
38
+ try {
39
+ // Use native fetch which is available in modern browsers and edge environments
40
+ const response = await fetch(`${this.baseUrl}${path}`, options);
41
+ // Get the response content type to check if it's JSON
42
+ const contentType = response.headers.get('content-type') || '';
43
+ const isJsonResponse = contentType.includes('application/json');
44
+ // Handle non-JSON responses properly
45
+ if (!isJsonResponse) {
46
+ // If not JSON, get the text for error details
47
+ let responseText = '';
48
+ try {
49
+ responseText = await response.text();
50
+ // Truncate if too long to avoid huge error messages
51
+ if (responseText.length > 500) {
52
+ responseText = responseText.substring(0, 500) + '... [truncated]';
53
+ }
54
+ }
55
+ catch (textError) {
56
+ responseText = 'Could not read response body';
57
+ }
58
+ throw new SkytellsError(`Server responded with non-JSON content (${contentType})`, 'SERVER_ERROR', `Status: ${response.status}, Content: ${responseText}`, response.status);
59
+ }
60
+ // Try to parse as JSON
61
+ let responseData;
62
+ try {
63
+ responseData = await response.json();
64
+ }
65
+ catch (error) {
66
+ // Get response text for better error details
67
+ let responseText = '';
68
+ try {
69
+ // Need to clone response since we already tried to read it as JSON
70
+ responseText = await response.clone().text();
71
+ if (responseText.length > 500) {
72
+ responseText = responseText.substring(0, 500) + '... [truncated]';
73
+ }
74
+ }
75
+ catch (textError) {
76
+ responseText = 'Could not read response body';
77
+ }
78
+ throw new SkytellsError('Invalid JSON response', 'INVALID_JSON', `The server returned invalid JSON. Status: ${response.status}, Content: ${responseText}`, response.status);
79
+ }
80
+ // Check if the response indicates an error
81
+ if (!response.ok || (responseData && responseData.status === false)) {
82
+ if (responseData && responseData.error) {
83
+ // API returned a structured error
84
+ throw new SkytellsError(responseData.error.message || responseData.response || 'API error occurred', responseData.error.error_id || 'UNKNOWN_ERROR', responseData.error.details || responseData.response || 'No additional details', responseData.error.http_status || response.status);
85
+ }
86
+ else if (responseData && responseData.response) {
87
+ // Simple error with just a response message
88
+ throw new SkytellsError(responseData.response, 'API_ERROR', responseData.response, response.status);
89
+ }
90
+ else {
91
+ // Generic HTTP error
92
+ throw new SkytellsError(`HTTP error ${response.status}`, 'HTTP_ERROR', `The server returned status code ${response.status}`, response.status);
93
+ }
94
+ }
95
+ return responseData;
96
+ }
97
+ catch (error) {
98
+ // Check if it's an abort error (timeout)
99
+ if (error && typeof error === 'object' && 'name' in error && error.name === 'AbortError') {
100
+ throw new SkytellsError(`Request timed out after ${this.timeout}ms`, 'REQUEST_TIMEOUT', `The request took longer than ${this.timeout}ms to complete`, 408 // Request Timeout status code
101
+ );
102
+ }
103
+ // Re-throw original error
104
+ if (error instanceof SkytellsError) {
105
+ throw error;
106
+ }
107
+ // Network or other errors
108
+ throw new SkytellsError(error instanceof Error ? error.message : 'Network error occurred', 'NETWORK_ERROR', 'A network error occurred while communicating with the API', 0 // No HTTP status for network errors
109
+ );
110
+ }
111
+ finally {
112
+ // Clear timeout if it was set
113
+ if (timeoutId !== null) {
114
+ clearTimeout(timeoutId);
115
+ }
116
+ }
117
+ }
118
+ }
package/dist/http.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export declare class HTTP {
2
+ private apiKey?;
3
+ private baseUrl;
4
+ private timeout;
5
+ constructor(apiKey?: string, baseUrl?: string, timeout?: number);
6
+ request<T>(method: 'GET' | 'POST' | 'DELETE', path: string, data?: Record<string, unknown>): Promise<T>;
7
+ }
package/dist/http.js ADDED
@@ -0,0 +1,118 @@
1
+ import { API_BASE_URL } from './endpoints.js';
2
+ import { SkytellsError } from './types/shared.types.js';
3
+ // Default timeout in milliseconds
4
+ // 60 seconds
5
+ const DEFAULT_TIMEOUT = 60000;
6
+ export class HTTP {
7
+ constructor(apiKey, baseUrl = API_BASE_URL, timeout = DEFAULT_TIMEOUT) {
8
+ this.apiKey = apiKey;
9
+ this.baseUrl = baseUrl;
10
+ this.timeout = timeout;
11
+ }
12
+ async request(method, path, data) {
13
+ const headers = {
14
+ 'Content-Type': 'application/json',
15
+ };
16
+ if (this.apiKey) {
17
+ headers['x-api-key'] = this.apiKey;
18
+ }
19
+ const options = {
20
+ method,
21
+ headers,
22
+ };
23
+ if (method === 'POST' && data) {
24
+ options.body = JSON.stringify(data);
25
+ }
26
+ // Add AbortController for timeout handling
27
+ const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
28
+ if (controller) {
29
+ options.signal = controller.signal;
30
+ }
31
+ // Set up timeout if AbortController is available
32
+ let timeoutId = null;
33
+ if (controller) {
34
+ timeoutId = setTimeout(() => {
35
+ controller.abort();
36
+ }, this.timeout);
37
+ }
38
+ try {
39
+ // Use native fetch which is available in modern browsers and edge environments
40
+ const response = await fetch(`${this.baseUrl}${path}`, options);
41
+ // Get the response content type to check if it's JSON
42
+ const contentType = response.headers.get('content-type') || '';
43
+ const isJsonResponse = contentType.includes('application/json');
44
+ // Handle non-JSON responses properly
45
+ if (!isJsonResponse) {
46
+ // If not JSON, get the text for error details
47
+ let responseText = '';
48
+ try {
49
+ responseText = await response.text();
50
+ // Truncate if too long to avoid huge error messages
51
+ if (responseText.length > 500) {
52
+ responseText = responseText.substring(0, 500) + '... [truncated]';
53
+ }
54
+ }
55
+ catch (textError) {
56
+ responseText = 'Could not read response body';
57
+ }
58
+ throw new SkytellsError(`Server responded with non-JSON content (${contentType})`, 'SERVER_ERROR', `Status: ${response.status}, Content: ${responseText}`, response.status);
59
+ }
60
+ // Try to parse as JSON
61
+ let responseData;
62
+ try {
63
+ responseData = await response.json();
64
+ }
65
+ catch (error) {
66
+ // Get response text for better error details
67
+ let responseText = '';
68
+ try {
69
+ // Need to clone response since we already tried to read it as JSON
70
+ responseText = await response.clone().text();
71
+ if (responseText.length > 500) {
72
+ responseText = responseText.substring(0, 500) + '... [truncated]';
73
+ }
74
+ }
75
+ catch (textError) {
76
+ responseText = 'Could not read response body';
77
+ }
78
+ throw new SkytellsError('Invalid JSON response', 'INVALID_JSON', `The server returned invalid JSON. Status: ${response.status}, Content: ${responseText}`, response.status);
79
+ }
80
+ // Check if the response indicates an error
81
+ if (!response.ok || (responseData && responseData.status === false)) {
82
+ if (responseData && responseData.error) {
83
+ // API returned a structured error
84
+ throw new SkytellsError(responseData.error.message || responseData.response || 'API error occurred', responseData.error.error_id || 'UNKNOWN_ERROR', responseData.error.details || responseData.response || 'No additional details', responseData.error.http_status || response.status);
85
+ }
86
+ else if (responseData && responseData.response) {
87
+ // Simple error with just a response message
88
+ throw new SkytellsError(responseData.response, 'API_ERROR', responseData.response, response.status);
89
+ }
90
+ else {
91
+ // Generic HTTP error
92
+ throw new SkytellsError(`HTTP error ${response.status}`, 'HTTP_ERROR', `The server returned status code ${response.status}`, response.status);
93
+ }
94
+ }
95
+ return responseData;
96
+ }
97
+ catch (error) {
98
+ // Check if it's an abort error (timeout)
99
+ if (error && typeof error === 'object' && 'name' in error && error.name === 'AbortError') {
100
+ throw new SkytellsError(`Request timed out after ${this.timeout}ms`, 'REQUEST_TIMEOUT', `The request took longer than ${this.timeout}ms to complete`, 408 // Request Timeout status code
101
+ );
102
+ }
103
+ // Re-throw original error
104
+ if (error instanceof SkytellsError) {
105
+ throw error;
106
+ }
107
+ // Network or other errors
108
+ throw new SkytellsError(error instanceof Error ? error.message : 'Network error occurred', 'NETWORK_ERROR', 'A network error occurred while communicating with the API', 0 // No HTTP status for network errors
109
+ );
110
+ }
111
+ finally {
112
+ // Clear timeout if it was set
113
+ if (timeoutId !== null) {
114
+ clearTimeout(timeoutId);
115
+ }
116
+ }
117
+ }
118
+ }
package/dist/index.cjs ADDED
@@ -0,0 +1,14 @@
1
+ const { SkytellsClient } = require("./client.js");
2
+ /**
3
+ * Create a new Skytells API client
4
+ * @param apiKey Optional API key for authenticated requests
5
+ * @param options Optional client configuration
6
+ * @returns A new Skytells client instance
7
+ */
8
+ function createClient(apiKey, options = {}) {
9
+ return new SkytellsClient(apiKey, options);
10
+ }
11
+ export * from './types/index.js';
12
+ module.exports = { SkytellsClient } from './client.js';
13
+ module.exports = { API_BASE_URL } from './endpoints.js';
14
+ module.exports = { SkytellsError } from './types/shared.types.js';
@@ -0,0 +1,13 @@
1
+ import { SkytellsClient } from './client.js';
2
+ import { ClientOptions } from './types/shared.types.js';
3
+ /**
4
+ * Create a new Skytells API client
5
+ * @param apiKey Optional API key for authenticated requests
6
+ * @param options Optional client configuration
7
+ * @returns A new Skytells client instance
8
+ */
9
+ export declare function createClient(apiKey?: string, options?: ClientOptions): SkytellsClient;
10
+ export * from './types/index.js';
11
+ export { SkytellsClient } from './client.js';
12
+ export { API_BASE_URL } from './endpoints.js';
13
+ export { SkytellsError } from './types/shared.types.js';
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ import { SkytellsClient } from './client.js';
2
+ /**
3
+ * Create a new Skytells API client
4
+ * @param apiKey Optional API key for authenticated requests
5
+ * @param options Optional client configuration
6
+ * @returns A new Skytells client instance
7
+ */
8
+ export function createClient(apiKey, options = {}) {
9
+ return new SkytellsClient(apiKey, options);
10
+ }
11
+ export * from './types/index.js';
12
+ export { SkytellsClient } from './client.js';
13
+ export { API_BASE_URL } from './endpoints.js';
14
+ export { SkytellsError } from './types/shared.types.js';
@@ -0,0 +1,3 @@
1
+ export * from './predict.types.js';
2
+ export * from './model.types.js';
3
+ export * from './shared.types.js';
@@ -0,0 +1,3 @@
1
+ export * from './predict.types.js';
2
+ export * from './model.types.js';
3
+ export * from './shared.types.js';
@@ -0,0 +1,13 @@
1
+ export interface Model {
2
+ name: string;
3
+ description?: string;
4
+ namespace: string;
5
+ type: string;
6
+ billable?: boolean;
7
+ pricing?: {
8
+ amount: number;
9
+ currency: string;
10
+ unit: string;
11
+ };
12
+ status: string;
13
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,80 @@
1
+ export interface PredictionRequest {
2
+ /**
3
+ * Model to use for the prediction
4
+ */
5
+ model: string;
6
+ /**
7
+ * Input to the prediction
8
+ */
9
+ input: Record<string, any>;
10
+ /**
11
+ * Webhook to receive prediction events
12
+ */
13
+ webhook?: {
14
+ url: string;
15
+ events: string[];
16
+ };
17
+ /**
18
+ * Whether to wait for the prediction to complete
19
+ * @default false
20
+ */
21
+ await?: boolean;
22
+ /**
23
+ * Whether to stream the prediction events
24
+ * @default false
25
+ */
26
+ stream?: boolean;
27
+ }
28
+ export declare enum PredictionStatus {
29
+ PENDING = "pending",
30
+ PROCESSING = "processing",
31
+ SUCCEEDED = "succeeded",
32
+ FAILED = "failed",
33
+ CANCELLED = "cancelled",
34
+ STARTING = "starting",
35
+ STARTED = "started"
36
+ }
37
+ export interface PredictionResponse {
38
+ status: PredictionStatus;
39
+ id: string;
40
+ response: string;
41
+ stream: boolean;
42
+ input: Record<string, any>;
43
+ output?: string[];
44
+ created_at: string;
45
+ started_at: string;
46
+ completed_at: string;
47
+ updated_at: string;
48
+ privacy: string;
49
+ model?: {
50
+ name: string;
51
+ type: string;
52
+ };
53
+ webhook?: {
54
+ url: string;
55
+ events: string[];
56
+ };
57
+ metrics?: {
58
+ image_count: number;
59
+ predict_time: number;
60
+ };
61
+ metadata?: {
62
+ billing?: {
63
+ credits_used: number;
64
+ };
65
+ storage?: {
66
+ files: {
67
+ name: string;
68
+ type: string;
69
+ size: number;
70
+ url: string;
71
+ }[];
72
+ };
73
+ };
74
+ urls?: {
75
+ get?: string;
76
+ cancel?: string;
77
+ stream?: string;
78
+ delete?: string;
79
+ };
80
+ }
@@ -0,0 +1,10 @@
1
+ export var PredictionStatus;
2
+ (function (PredictionStatus) {
3
+ PredictionStatus["PENDING"] = "pending";
4
+ PredictionStatus["PROCESSING"] = "processing";
5
+ PredictionStatus["SUCCEEDED"] = "succeeded";
6
+ PredictionStatus["FAILED"] = "failed";
7
+ PredictionStatus["CANCELLED"] = "cancelled";
8
+ PredictionStatus["STARTING"] = "starting";
9
+ PredictionStatus["STARTED"] = "started";
10
+ })(PredictionStatus || (PredictionStatus = {}));
@@ -0,0 +1,20 @@
1
+ export interface ApiError {
2
+ status: boolean;
3
+ response: string;
4
+ error: {
5
+ http_status: number;
6
+ message: string;
7
+ details: string;
8
+ error_id: string;
9
+ };
10
+ }
11
+ export interface ClientOptions {
12
+ baseUrl?: string;
13
+ timeout?: number;
14
+ }
15
+ export declare class SkytellsError extends Error {
16
+ errorId: string;
17
+ details: string;
18
+ httpStatus: number;
19
+ constructor(message: string, errorId: string, details: string, httpStatus?: number);
20
+ }
@@ -0,0 +1,11 @@
1
+ export class SkytellsError extends Error {
2
+ constructor(message, errorId, details, httpStatus) {
3
+ super(message);
4
+ this.name = 'SkytellsError';
5
+ this.errorId = errorId;
6
+ this.details = details;
7
+ this.httpStatus = httpStatus || 0;
8
+ // This is needed for proper instanceof checks in some environments
9
+ Object.setPrototypeOf(this, SkytellsError.prototype);
10
+ }
11
+ }
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "skytells",
3
+ "version": "1.0.0",
4
+ "description": "Official Skytells JavaScript/TypeScript SDK - Edge compatible",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "node build.js",
12
+ "build:types": "tsc --emitDeclarationOnly",
13
+ "test": "jest",
14
+ "lint": "eslint src --ext .ts",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/skytells/ts-sdk.git"
20
+ },
21
+ "keywords": [
22
+ "ai",
23
+ "skytells",
24
+ "skytells-ai",
25
+ "skytells-sdk",
26
+ "edge",
27
+ "cloudflare",
28
+ "vercel-edge",
29
+ "netlify-edge"
30
+ ],
31
+ "author": "Skytells, Inc.",
32
+ "license": "MIT",
33
+ "bugs": {
34
+ "url": "https://github.com/skytells/ts-sdk/issues"
35
+ },
36
+ "homepage": "https://github.com/skytells/ts-sdk#readme",
37
+ "devDependencies": {
38
+ "@types/jest": "^29.5.0",
39
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
40
+ "@typescript-eslint/parser": "^6.0.0",
41
+ "eslint": "^8.40.0",
42
+ "jest": "^29.5.0",
43
+ "ts-jest": "^29.1.0",
44
+ "typescript": "^5.8.2"
45
+ },
46
+ "engines": {
47
+ "node": ">=14"
48
+ },
49
+ "type": "module",
50
+ "exports": {
51
+ ".": {
52
+ "types": "./dist/index.d.ts",
53
+ "import": "./dist/index.js",
54
+ "require": "./dist/index.cjs"
55
+ }
56
+ }
57
+ }