flowscale 1.0.3
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/index.d.ts +52 -0
- package/dist/index.js +193 -0
- package/dist/types.d.ts +72 -0
- package/dist/types.js +3 -0
- package/package.json +23 -0
- package/src/index.ts +230 -0
- package/src/types.ts +82 -0
- package/tsconfig.json +11 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { HealthCheckResponse, QueueResponse, ExecuteWorkflowResponse, GetOutputResponse, RunDetailResponse, RunListResponse, CancelRunResponse } from './types';
|
|
2
|
+
export declare class FlowscaleAPI {
|
|
3
|
+
private apiKey;
|
|
4
|
+
private baseUrl;
|
|
5
|
+
private client;
|
|
6
|
+
constructor(apiKey: string, baseUrl: string);
|
|
7
|
+
/**
|
|
8
|
+
* Checks the health status of all ComfyUI instances within the specified cluster.
|
|
9
|
+
*/
|
|
10
|
+
checkHealth(): Promise<HealthCheckResponse>;
|
|
11
|
+
/**
|
|
12
|
+
* Retrieves the queue data for all ComfyUI instances in the cluster.
|
|
13
|
+
*/
|
|
14
|
+
getQueue(): Promise<QueueResponse>;
|
|
15
|
+
/**
|
|
16
|
+
* Executes a specified workflow by processing dynamic form data.
|
|
17
|
+
* @param workflowId - The ID of the workflow to execute.
|
|
18
|
+
* @param data - Form data including text fields and file uploads.
|
|
19
|
+
* @param groupId - Optional group ID.
|
|
20
|
+
*/
|
|
21
|
+
executeWorkflow(workflowId: string, data: {
|
|
22
|
+
[key: string]: any;
|
|
23
|
+
}, groupId?: string): Promise<ExecuteWorkflowResponse>;
|
|
24
|
+
/**
|
|
25
|
+
* Retrieves the output of a specific run by providing the filename.
|
|
26
|
+
* @param filename - The filename of the output to retrieve.
|
|
27
|
+
*/
|
|
28
|
+
getOutput(filename: string): Promise<GetOutputResponse | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Cancels a specific run using its unique run ID.
|
|
31
|
+
* @param runId - The ID of the run to cancel.
|
|
32
|
+
*/
|
|
33
|
+
cancelRun(runId: string): Promise<CancelRunResponse>;
|
|
34
|
+
/**
|
|
35
|
+
* Retrieves detailed information about a specific run using its unique run ID.
|
|
36
|
+
* @param runId - The ID of the run to retrieve.
|
|
37
|
+
*/
|
|
38
|
+
getRun(runId: string): Promise<RunDetailResponse>;
|
|
39
|
+
/**
|
|
40
|
+
* Retrieves a list of all runs associated with a specific group ID.
|
|
41
|
+
* @param groupId - The group ID to filter runs.
|
|
42
|
+
*/
|
|
43
|
+
getRuns(groupId: string): Promise<RunListResponse>;
|
|
44
|
+
/**
|
|
45
|
+
* Helper method to append data to FormData.
|
|
46
|
+
*/
|
|
47
|
+
private appendFormData;
|
|
48
|
+
/**
|
|
49
|
+
* Error handling helper.
|
|
50
|
+
*/
|
|
51
|
+
private handleError;
|
|
52
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.FlowscaleAPI = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const form_data_1 = __importDefault(require("form-data"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
class FlowscaleAPI {
|
|
12
|
+
constructor(apiKey, baseUrl) {
|
|
13
|
+
this.apiKey = apiKey;
|
|
14
|
+
this.baseUrl = baseUrl;
|
|
15
|
+
this.client = axios_1.default.create({
|
|
16
|
+
baseURL: this.baseUrl,
|
|
17
|
+
});
|
|
18
|
+
// Add the API key to all requests
|
|
19
|
+
this.client.interceptors.request.use((config) => {
|
|
20
|
+
if (!config.headers) {
|
|
21
|
+
config.headers = {};
|
|
22
|
+
}
|
|
23
|
+
config.headers['X-API-KEY'] = this.apiKey;
|
|
24
|
+
return config;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Checks the health status of all ComfyUI instances within the specified cluster.
|
|
29
|
+
*/
|
|
30
|
+
async checkHealth() {
|
|
31
|
+
try {
|
|
32
|
+
const response = await this.client.get('/api/v1/comfy/health');
|
|
33
|
+
return response.data;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
this.handleError(error);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Retrieves the queue data for all ComfyUI instances in the cluster.
|
|
41
|
+
*/
|
|
42
|
+
async getQueue() {
|
|
43
|
+
try {
|
|
44
|
+
const response = await this.client.get('/api/v1/comfy/queue');
|
|
45
|
+
return response.data;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
this.handleError(error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Executes a specified workflow by processing dynamic form data.
|
|
53
|
+
* @param workflowId - The ID of the workflow to execute.
|
|
54
|
+
* @param data - Form data including text fields and file uploads.
|
|
55
|
+
* @param groupId - Optional group ID.
|
|
56
|
+
*/
|
|
57
|
+
async executeWorkflow(workflowId, data, groupId) {
|
|
58
|
+
try {
|
|
59
|
+
const formData = new form_data_1.default();
|
|
60
|
+
// Append data to formData
|
|
61
|
+
for (const key in data) {
|
|
62
|
+
if (data.hasOwnProperty(key)) {
|
|
63
|
+
const value = data[key];
|
|
64
|
+
if (Array.isArray(value)) {
|
|
65
|
+
// Handle arrays (for multiple files)
|
|
66
|
+
value.forEach((item) => {
|
|
67
|
+
this.appendFormData(formData, key, item);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.appendFormData(formData, key, value);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const headers = {
|
|
76
|
+
...formData.getHeaders(),
|
|
77
|
+
'X-API-KEY': this.apiKey,
|
|
78
|
+
};
|
|
79
|
+
const url = `/api/v1/runs?workflow_id=${encodeURIComponent(workflowId)}${groupId ? `&group_id=${encodeURIComponent(groupId)}` : ''}`;
|
|
80
|
+
const response = await this.client.post(url, formData, { headers });
|
|
81
|
+
return response.data;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
this.handleError(error);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Retrieves the output of a specific run by providing the filename.
|
|
89
|
+
* @param filename - The filename of the output to retrieve.
|
|
90
|
+
*/
|
|
91
|
+
async getOutput(filename) {
|
|
92
|
+
try {
|
|
93
|
+
const response = await this.client.get('/api/v1/runs/output', {
|
|
94
|
+
params: { filename },
|
|
95
|
+
});
|
|
96
|
+
return response.data;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
const axiosError = error;
|
|
100
|
+
if (axiosError.response && axiosError.response.status === 204) {
|
|
101
|
+
return null; // No output found
|
|
102
|
+
}
|
|
103
|
+
else if (axiosError.response &&
|
|
104
|
+
axiosError.response.status === 408) {
|
|
105
|
+
throw new Error('Run Timeout');
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
this.handleError(error);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Cancels a specific run using its unique run ID.
|
|
114
|
+
* @param runId - The ID of the run to cancel.
|
|
115
|
+
*/
|
|
116
|
+
async cancelRun(runId) {
|
|
117
|
+
try {
|
|
118
|
+
const response = await this.client.post(`/api/v1/runs/${encodeURIComponent(runId)}/cancel`);
|
|
119
|
+
return response.data;
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
this.handleError(error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Retrieves detailed information about a specific run using its unique run ID.
|
|
127
|
+
* @param runId - The ID of the run to retrieve.
|
|
128
|
+
*/
|
|
129
|
+
async getRun(runId) {
|
|
130
|
+
try {
|
|
131
|
+
const response = await this.client.get(`/api/v1/runs/${encodeURIComponent(runId)}`);
|
|
132
|
+
return response.data;
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
this.handleError(error);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Retrieves a list of all runs associated with a specific group ID.
|
|
140
|
+
* @param groupId - The group ID to filter runs.
|
|
141
|
+
*/
|
|
142
|
+
async getRuns(groupId) {
|
|
143
|
+
try {
|
|
144
|
+
const response = await this.client.get('/api/v1/runs', {
|
|
145
|
+
params: { group_id: groupId },
|
|
146
|
+
});
|
|
147
|
+
return response.data;
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
this.handleError(error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Helper method to append data to FormData.
|
|
155
|
+
*/
|
|
156
|
+
appendFormData(formData, key, value) {
|
|
157
|
+
if (value instanceof fs_1.default.ReadStream) {
|
|
158
|
+
// It's a file stream
|
|
159
|
+
formData.append(key, value);
|
|
160
|
+
}
|
|
161
|
+
else if (Buffer.isBuffer(value)) {
|
|
162
|
+
// It's a Buffer
|
|
163
|
+
formData.append(key, value, { filename: `${key}.dat` });
|
|
164
|
+
}
|
|
165
|
+
else if (typeof value === 'string' && fs_1.default.existsSync(value)) {
|
|
166
|
+
// If the value is a file path
|
|
167
|
+
const fileName = path_1.default.basename(value);
|
|
168
|
+
formData.append(key, fs_1.default.createReadStream(value), fileName);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// Assume it's a string or other value
|
|
172
|
+
formData.append(key, value);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Error handling helper.
|
|
177
|
+
*/
|
|
178
|
+
handleError(error) {
|
|
179
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
180
|
+
if (error.response) {
|
|
181
|
+
// Server responded with a status code outside 2xx
|
|
182
|
+
throw new Error(`API Error: ${error.response.status} ${error.response.statusText} - ${JSON.stringify(error.response.data)}`);
|
|
183
|
+
}
|
|
184
|
+
else if (error.request) {
|
|
185
|
+
// Request was made but no response
|
|
186
|
+
throw new Error('No response received from API server');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Something else happened
|
|
190
|
+
throw new Error(`Error: ${error.message}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
exports.FlowscaleAPI = FlowscaleAPI;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export interface HealthCheckResponse {
|
|
2
|
+
status: string;
|
|
3
|
+
data: Array<{
|
|
4
|
+
container: string;
|
|
5
|
+
status: string;
|
|
6
|
+
}>;
|
|
7
|
+
}
|
|
8
|
+
export interface QueueResponse {
|
|
9
|
+
status: string;
|
|
10
|
+
data: Array<{
|
|
11
|
+
container: string;
|
|
12
|
+
queue: {
|
|
13
|
+
queue_running: any[];
|
|
14
|
+
queue_pending: any[];
|
|
15
|
+
};
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
export interface ExecuteWorkflowResponse {
|
|
19
|
+
status: string;
|
|
20
|
+
data: {
|
|
21
|
+
output_names: string[];
|
|
22
|
+
run_id: string;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface GetOutputResponse {
|
|
26
|
+
status: string;
|
|
27
|
+
data: {
|
|
28
|
+
download_url: string;
|
|
29
|
+
generation_status: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface RunDetail {
|
|
33
|
+
_id: string;
|
|
34
|
+
team_id: string;
|
|
35
|
+
workflow_id: string;
|
|
36
|
+
group_id?: string;
|
|
37
|
+
status: string;
|
|
38
|
+
inputs: Array<{
|
|
39
|
+
path: string;
|
|
40
|
+
value: string;
|
|
41
|
+
s3_key?: string;
|
|
42
|
+
url?: string;
|
|
43
|
+
}>;
|
|
44
|
+
outputs: Array<{
|
|
45
|
+
filename: string;
|
|
46
|
+
s3_key?: string;
|
|
47
|
+
url?: string;
|
|
48
|
+
}>;
|
|
49
|
+
created_at: string;
|
|
50
|
+
started_at?: string;
|
|
51
|
+
completed_at?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface RunDetailResponse {
|
|
54
|
+
status: string;
|
|
55
|
+
data: RunDetail;
|
|
56
|
+
}
|
|
57
|
+
export interface RunListResponse {
|
|
58
|
+
status: string;
|
|
59
|
+
data: {
|
|
60
|
+
group_id: string;
|
|
61
|
+
count: number;
|
|
62
|
+
runs: RunDetail[];
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export interface CancelRunResponse {
|
|
66
|
+
status: string;
|
|
67
|
+
data: string;
|
|
68
|
+
}
|
|
69
|
+
export interface ErrorResponse {
|
|
70
|
+
status: string;
|
|
71
|
+
errors: string;
|
|
72
|
+
}
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "flowscale",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "An NPM library for communicating with the Flowscale APIs",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "echo \"No tests yet\""
|
|
10
|
+
},
|
|
11
|
+
"author": "Your Name",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"axios": "^1.7.7",
|
|
15
|
+
"form-data": "^4.0.1",
|
|
16
|
+
"flowscale-test": "^1.0.1"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/form-data": "^2.5.2",
|
|
20
|
+
"@types/node": "^22.9.1",
|
|
21
|
+
"typescript": "^5.6.3"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import axios, { AxiosInstance, AxiosError, AxiosRequestHeaders } from 'axios';
|
|
2
|
+
import FormData from 'form-data';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import {
|
|
6
|
+
HealthCheckResponse,
|
|
7
|
+
QueueResponse,
|
|
8
|
+
ExecuteWorkflowResponse,
|
|
9
|
+
GetOutputResponse,
|
|
10
|
+
RunDetailResponse,
|
|
11
|
+
RunListResponse,
|
|
12
|
+
CancelRunResponse,
|
|
13
|
+
ErrorResponse,
|
|
14
|
+
} from './types';
|
|
15
|
+
|
|
16
|
+
export class FlowscaleAPI {
|
|
17
|
+
private apiKey: string;
|
|
18
|
+
private baseUrl: string;
|
|
19
|
+
private client: AxiosInstance;
|
|
20
|
+
|
|
21
|
+
constructor(apiKey: string, baseUrl: string) {
|
|
22
|
+
this.apiKey = apiKey;
|
|
23
|
+
this.baseUrl = baseUrl;
|
|
24
|
+
|
|
25
|
+
this.client = axios.create({
|
|
26
|
+
baseURL: this.baseUrl,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Add the API key to all requests
|
|
30
|
+
this.client.interceptors.request.use((config) => {
|
|
31
|
+
if (!config.headers) {
|
|
32
|
+
config.headers = {} as AxiosRequestHeaders
|
|
33
|
+
}
|
|
34
|
+
config.headers['X-API-KEY'] = this.apiKey;
|
|
35
|
+
return config;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Checks the health status of all ComfyUI instances within the specified cluster.
|
|
41
|
+
*/
|
|
42
|
+
public async checkHealth(): Promise<HealthCheckResponse> {
|
|
43
|
+
try {
|
|
44
|
+
const response = await this.client.get<HealthCheckResponse>(
|
|
45
|
+
'/api/v1/comfy/health'
|
|
46
|
+
);
|
|
47
|
+
return response.data;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
this.handleError(error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Retrieves the queue data for all ComfyUI instances in the cluster.
|
|
55
|
+
*/
|
|
56
|
+
public async getQueue(): Promise<QueueResponse> {
|
|
57
|
+
try {
|
|
58
|
+
const response = await this.client.get<QueueResponse>(
|
|
59
|
+
'/api/v1/comfy/queue'
|
|
60
|
+
);
|
|
61
|
+
return response.data;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
this.handleError(error);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Executes a specified workflow by processing dynamic form data.
|
|
69
|
+
* @param workflowId - The ID of the workflow to execute.
|
|
70
|
+
* @param data - Form data including text fields and file uploads.
|
|
71
|
+
* @param groupId - Optional group ID.
|
|
72
|
+
*/
|
|
73
|
+
public async executeWorkflow(
|
|
74
|
+
workflowId: string,
|
|
75
|
+
data: { [key: string]: any },
|
|
76
|
+
groupId?: string
|
|
77
|
+
): Promise<ExecuteWorkflowResponse> {
|
|
78
|
+
try {
|
|
79
|
+
const formData = new FormData();
|
|
80
|
+
|
|
81
|
+
// Append data to formData
|
|
82
|
+
for (const key in data) {
|
|
83
|
+
if (data.hasOwnProperty(key)) {
|
|
84
|
+
const value = data[key];
|
|
85
|
+
if (Array.isArray(value)) {
|
|
86
|
+
// Handle arrays (for multiple files)
|
|
87
|
+
value.forEach((item: any) => {
|
|
88
|
+
this.appendFormData(formData, key, item);
|
|
89
|
+
});
|
|
90
|
+
} else {
|
|
91
|
+
this.appendFormData(formData, key, value);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const headers = {
|
|
97
|
+
...formData.getHeaders(),
|
|
98
|
+
'X-API-KEY': this.apiKey,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const url = `/api/v1/runs?workflow_id=${encodeURIComponent(workflowId)}${
|
|
102
|
+
groupId ? `&group_id=${encodeURIComponent(groupId)}` : ''
|
|
103
|
+
}`;
|
|
104
|
+
|
|
105
|
+
const response = await this.client.post<ExecuteWorkflowResponse>(
|
|
106
|
+
url,
|
|
107
|
+
formData,
|
|
108
|
+
{ headers }
|
|
109
|
+
);
|
|
110
|
+
return response.data;
|
|
111
|
+
} catch (error) {
|
|
112
|
+
this.handleError(error);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Retrieves the output of a specific run by providing the filename.
|
|
118
|
+
* @param filename - The filename of the output to retrieve.
|
|
119
|
+
*/
|
|
120
|
+
public async getOutput(filename: string): Promise<GetOutputResponse | null> {
|
|
121
|
+
try {
|
|
122
|
+
const response = await this.client.get<GetOutputResponse>(
|
|
123
|
+
'/api/v1/runs/output',
|
|
124
|
+
{
|
|
125
|
+
params: { filename },
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
return response.data;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
const axiosError = error as AxiosError;
|
|
131
|
+
if (axiosError.response && axiosError.response.status === 204) {
|
|
132
|
+
return null; // No output found
|
|
133
|
+
} else if (
|
|
134
|
+
axiosError.response &&
|
|
135
|
+
axiosError.response.status === 408
|
|
136
|
+
) {
|
|
137
|
+
throw new Error('Run Timeout');
|
|
138
|
+
} else {
|
|
139
|
+
this.handleError(error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Cancels a specific run using its unique run ID.
|
|
146
|
+
* @param runId - The ID of the run to cancel.
|
|
147
|
+
*/
|
|
148
|
+
public async cancelRun(runId: string): Promise<CancelRunResponse> {
|
|
149
|
+
try {
|
|
150
|
+
const response = await this.client.post<CancelRunResponse>(
|
|
151
|
+
`/api/v1/runs/${encodeURIComponent(runId)}/cancel`
|
|
152
|
+
);
|
|
153
|
+
return response.data;
|
|
154
|
+
} catch (error) {
|
|
155
|
+
this.handleError(error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Retrieves detailed information about a specific run using its unique run ID.
|
|
161
|
+
* @param runId - The ID of the run to retrieve.
|
|
162
|
+
*/
|
|
163
|
+
public async getRun(runId: string): Promise<RunDetailResponse> {
|
|
164
|
+
try {
|
|
165
|
+
const response = await this.client.get<RunDetailResponse>(
|
|
166
|
+
`/api/v1/runs/${encodeURIComponent(runId)}`
|
|
167
|
+
);
|
|
168
|
+
return response.data;
|
|
169
|
+
} catch (error) {
|
|
170
|
+
this.handleError(error);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Retrieves a list of all runs associated with a specific group ID.
|
|
176
|
+
* @param groupId - The group ID to filter runs.
|
|
177
|
+
*/
|
|
178
|
+
public async getRuns(groupId: string): Promise<RunListResponse> {
|
|
179
|
+
try {
|
|
180
|
+
const response = await this.client.get<RunListResponse>('/api/v1/runs', {
|
|
181
|
+
params: { group_id: groupId },
|
|
182
|
+
});
|
|
183
|
+
return response.data;
|
|
184
|
+
} catch (error) {
|
|
185
|
+
this.handleError(error);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Helper method to append data to FormData.
|
|
191
|
+
*/
|
|
192
|
+
private appendFormData(formData: FormData, key: string, value: any) {
|
|
193
|
+
if (value instanceof fs.ReadStream) {
|
|
194
|
+
// It's a file stream
|
|
195
|
+
formData.append(key, value);
|
|
196
|
+
} else if (Buffer.isBuffer(value)) {
|
|
197
|
+
// It's a Buffer
|
|
198
|
+
formData.append(key, value, { filename: `${key}.dat` });
|
|
199
|
+
} else if (typeof value === 'string' && fs.existsSync(value)) {
|
|
200
|
+
// If the value is a file path
|
|
201
|
+
const fileName = path.basename(value);
|
|
202
|
+
formData.append(key, fs.createReadStream(value), fileName);
|
|
203
|
+
} else {
|
|
204
|
+
// Assume it's a string or other value
|
|
205
|
+
formData.append(key, value);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Error handling helper.
|
|
211
|
+
*/
|
|
212
|
+
private handleError(error: any): never {
|
|
213
|
+
if (axios.isAxiosError(error)) {
|
|
214
|
+
if (error.response) {
|
|
215
|
+
// Server responded with a status code outside 2xx
|
|
216
|
+
throw new Error(
|
|
217
|
+
`API Error: ${error.response.status} ${error.response.statusText} - ${JSON.stringify(
|
|
218
|
+
error.response.data
|
|
219
|
+
)}`
|
|
220
|
+
);
|
|
221
|
+
} else if (error.request) {
|
|
222
|
+
// Request was made but no response
|
|
223
|
+
throw new Error('No response received from API server');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
console.error(error);
|
|
227
|
+
// Something else happened
|
|
228
|
+
throw new Error(`Error: ${error.message}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
|
|
3
|
+
export interface HealthCheckResponse {
|
|
4
|
+
status: string;
|
|
5
|
+
data: Array<{
|
|
6
|
+
container: string;
|
|
7
|
+
status: string;
|
|
8
|
+
}>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface QueueResponse {
|
|
12
|
+
status: string;
|
|
13
|
+
data: Array<{
|
|
14
|
+
container: string;
|
|
15
|
+
queue: {
|
|
16
|
+
queue_running: any[];
|
|
17
|
+
queue_pending: any[];
|
|
18
|
+
};
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ExecuteWorkflowResponse {
|
|
23
|
+
status: string;
|
|
24
|
+
data: {
|
|
25
|
+
output_names: string[];
|
|
26
|
+
run_id: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface GetOutputResponse {
|
|
31
|
+
status: string;
|
|
32
|
+
data: {
|
|
33
|
+
download_url: string;
|
|
34
|
+
generation_status: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface RunDetail {
|
|
39
|
+
_id: string;
|
|
40
|
+
team_id: string;
|
|
41
|
+
workflow_id: string;
|
|
42
|
+
group_id?: string;
|
|
43
|
+
status: string;
|
|
44
|
+
inputs: Array<{
|
|
45
|
+
path: string;
|
|
46
|
+
value: string;
|
|
47
|
+
s3_key?: string;
|
|
48
|
+
url?: string;
|
|
49
|
+
}>;
|
|
50
|
+
outputs: Array<{
|
|
51
|
+
filename: string;
|
|
52
|
+
s3_key?: string;
|
|
53
|
+
url?: string;
|
|
54
|
+
}>;
|
|
55
|
+
created_at: string;
|
|
56
|
+
started_at?: string;
|
|
57
|
+
completed_at?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface RunDetailResponse {
|
|
61
|
+
status: string;
|
|
62
|
+
data: RunDetail;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface RunListResponse {
|
|
66
|
+
status: string;
|
|
67
|
+
data: {
|
|
68
|
+
group_id: string;
|
|
69
|
+
count: number;
|
|
70
|
+
runs: RunDetail[];
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface CancelRunResponse {
|
|
75
|
+
status: string;
|
|
76
|
+
data: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface ErrorResponse {
|
|
80
|
+
status: string;
|
|
81
|
+
errors: string;
|
|
82
|
+
}
|