@tanstack/openai-base 0.2.0 → 0.3.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/README.md +121 -0
- package/dist/esm/adapters/chat-completions-text.d.ts +49 -21
- package/dist/esm/adapters/chat-completions-text.js +476 -68
- package/dist/esm/adapters/chat-completions-text.js.map +1 -1
- package/dist/esm/adapters/chat-completions-tool-converter.d.ts +8 -4
- package/dist/esm/adapters/chat-completions-tool-converter.js.map +1 -1
- package/dist/esm/adapters/responses-text.d.ts +46 -33
- package/dist/esm/adapters/responses-text.js +657 -142
- package/dist/esm/adapters/responses-text.js.map +1 -1
- package/dist/esm/index.d.ts +2 -9
- package/dist/esm/index.js +4 -16
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tools/apply-patch-tool.d.ts +2 -2
- package/dist/esm/tools/apply-patch-tool.js.map +1 -1
- package/dist/esm/tools/code-interpreter-tool.d.ts +3 -2
- package/dist/esm/tools/code-interpreter-tool.js.map +1 -1
- package/dist/esm/tools/computer-use-tool.d.ts +2 -2
- package/dist/esm/tools/computer-use-tool.js.map +1 -1
- package/dist/esm/tools/custom-tool.d.ts +2 -2
- package/dist/esm/tools/custom-tool.js.map +1 -1
- package/dist/esm/tools/file-search-tool.d.ts +2 -2
- package/dist/esm/tools/file-search-tool.js.map +1 -1
- package/dist/esm/tools/function-tool.d.ts +2 -2
- package/dist/esm/tools/function-tool.js.map +1 -1
- package/dist/esm/tools/image-generation-tool.d.ts +3 -2
- package/dist/esm/tools/image-generation-tool.js.map +1 -1
- package/dist/esm/tools/local-shell-tool.d.ts +3 -2
- package/dist/esm/tools/local-shell-tool.js.map +1 -1
- package/dist/esm/tools/mcp-tool.d.ts +3 -2
- package/dist/esm/tools/mcp-tool.js.map +1 -1
- package/dist/esm/tools/shell-tool.d.ts +2 -2
- package/dist/esm/tools/shell-tool.js.map +1 -1
- package/dist/esm/tools/web-search-preview-tool.d.ts +2 -2
- package/dist/esm/tools/web-search-preview-tool.js.map +1 -1
- package/dist/esm/tools/web-search-tool.d.ts +2 -2
- package/dist/esm/tools/web-search-tool.js.map +1 -1
- package/package.json +6 -6
- package/src/adapters/chat-completions-text.ts +601 -117
- package/src/adapters/chat-completions-tool-converter.ts +9 -5
- package/src/adapters/responses-text.ts +865 -210
- package/src/index.ts +2 -12
- package/src/tools/apply-patch-tool.ts +2 -2
- package/src/tools/code-interpreter-tool.ts +4 -2
- package/src/tools/computer-use-tool.ts +2 -2
- package/src/tools/custom-tool.ts +2 -2
- package/src/tools/file-search-tool.ts +3 -3
- package/src/tools/function-tool.ts +2 -2
- package/src/tools/image-generation-tool.ts +4 -2
- package/src/tools/local-shell-tool.ts +4 -2
- package/src/tools/mcp-tool.ts +4 -2
- package/src/tools/shell-tool.ts +2 -2
- package/src/tools/web-search-preview-tool.ts +2 -2
- package/src/tools/web-search-tool.ts +2 -2
- package/dist/esm/adapters/image.d.ts +0 -32
- package/dist/esm/adapters/image.js +0 -89
- package/dist/esm/adapters/image.js.map +0 -1
- package/dist/esm/adapters/summarize.d.ts +0 -28
- package/dist/esm/adapters/summarize.js +0 -112
- package/dist/esm/adapters/summarize.js.map +0 -1
- package/dist/esm/adapters/transcription.d.ts +0 -34
- package/dist/esm/adapters/transcription.js +0 -131
- package/dist/esm/adapters/transcription.js.map +0 -1
- package/dist/esm/adapters/tts.d.ts +0 -26
- package/dist/esm/adapters/tts.js +0 -78
- package/dist/esm/adapters/tts.js.map +0 -1
- package/dist/esm/adapters/video.d.ts +0 -72
- package/dist/esm/adapters/video.js +0 -238
- package/dist/esm/adapters/video.js.map +0 -1
- package/dist/esm/types/config.d.ts +0 -4
- package/dist/esm/utils/client.d.ts +0 -3
- package/dist/esm/utils/client.js +0 -8
- package/dist/esm/utils/client.js.map +0 -1
- package/src/adapters/image.ts +0 -158
- package/src/adapters/summarize.ts +0 -174
- package/src/adapters/transcription.ts +0 -194
- package/src/adapters/tts.ts +0 -124
- package/src/adapters/video.ts +0 -385
- package/src/types/config.ts +0 -5
- package/src/utils/client.ts +0 -8
package/src/adapters/video.ts
DELETED
|
@@ -1,385 +0,0 @@
|
|
|
1
|
-
import { BaseVideoAdapter } from '@tanstack/ai/adapters'
|
|
2
|
-
import { toRunErrorPayload } from '@tanstack/ai/adapter-internals'
|
|
3
|
-
import { arrayBufferToBase64 } from '@tanstack/ai-utils'
|
|
4
|
-
import { createOpenAICompatibleClient } from '../utils/client'
|
|
5
|
-
import type {
|
|
6
|
-
VideoGenerationOptions,
|
|
7
|
-
VideoJobResult,
|
|
8
|
-
VideoStatusResult,
|
|
9
|
-
VideoUrlResult,
|
|
10
|
-
} from '@tanstack/ai'
|
|
11
|
-
import type OpenAI_SDK from 'openai'
|
|
12
|
-
import type { OpenAICompatibleClientConfig } from '../types/config'
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Threshold for emitting a "this download will probably OOM serverless
|
|
16
|
-
* runtimes" warning. Anything larger than this (in bytes) gets surfaced via
|
|
17
|
-
* console.warn — workers and small isolates routinely run out of memory once
|
|
18
|
-
* a downloaded video is base64-encoded (the encoded form is ~33% larger and
|
|
19
|
-
* resides in V8 heap rather than streaming through the runtime's network
|
|
20
|
-
* layer).
|
|
21
|
-
*/
|
|
22
|
-
const LARGE_MEDIA_BUFFER_BYTES = 10 * 1024 * 1024
|
|
23
|
-
|
|
24
|
-
function warnIfLargeMediaBuffer(
|
|
25
|
-
byteLength: number,
|
|
26
|
-
source: string,
|
|
27
|
-
providerName: string,
|
|
28
|
-
): void {
|
|
29
|
-
if (byteLength <= LARGE_MEDIA_BUFFER_BYTES) return
|
|
30
|
-
// No InternalLogger plumbed through to these download paths yet; surface
|
|
31
|
-
// via console.warn so Workers / Lambda dashboards still capture it.
|
|
32
|
-
console.warn(
|
|
33
|
-
`[${providerName}.${source}] downloaded ${(byteLength / 1024 / 1024).toFixed(1)} MiB into memory before base64 encoding. ` +
|
|
34
|
-
`Workers/serverless runtimes commonly run out of memory above ~10 MiB. ` +
|
|
35
|
-
`Consider streaming the video through a CDN or your own storage layer instead.`,
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* OpenAI-Compatible Video Generation Adapter
|
|
41
|
-
*
|
|
42
|
-
* A generalized base class for providers that implement OpenAI-compatible video
|
|
43
|
-
* generation APIs. Uses a job/polling architecture for async video generation.
|
|
44
|
-
*
|
|
45
|
-
* Providers can extend this class and only need to:
|
|
46
|
-
* - Set `baseURL` in the config
|
|
47
|
-
* - Lock the generic type parameters to provider-specific types
|
|
48
|
-
* - Override validation or request building methods as needed
|
|
49
|
-
*
|
|
50
|
-
* All methods that validate inputs, build requests, or map responses are `protected`
|
|
51
|
-
* so subclasses can override them.
|
|
52
|
-
*
|
|
53
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
54
|
-
*/
|
|
55
|
-
export class OpenAICompatibleVideoAdapter<
|
|
56
|
-
TModel extends string,
|
|
57
|
-
TProviderOptions extends object = Record<string, any>,
|
|
58
|
-
TModelProviderOptionsByName extends Record<string, any> = Record<string, any>,
|
|
59
|
-
TModelSizeByName extends Record<string, string> = Record<string, string>,
|
|
60
|
-
> extends BaseVideoAdapter<
|
|
61
|
-
TModel,
|
|
62
|
-
TProviderOptions,
|
|
63
|
-
TModelProviderOptionsByName,
|
|
64
|
-
TModelSizeByName
|
|
65
|
-
> {
|
|
66
|
-
readonly name: string
|
|
67
|
-
|
|
68
|
-
protected client: OpenAI_SDK
|
|
69
|
-
protected clientConfig: OpenAICompatibleClientConfig
|
|
70
|
-
|
|
71
|
-
constructor(
|
|
72
|
-
config: OpenAICompatibleClientConfig,
|
|
73
|
-
model: TModel,
|
|
74
|
-
name: string = 'openai-compatible',
|
|
75
|
-
) {
|
|
76
|
-
super(config, model)
|
|
77
|
-
this.name = name
|
|
78
|
-
this.clientConfig = config
|
|
79
|
-
this.client = createOpenAICompatibleClient(config)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Create a new video generation job.
|
|
84
|
-
*
|
|
85
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
86
|
-
*/
|
|
87
|
-
async createVideoJob(
|
|
88
|
-
options: VideoGenerationOptions<TProviderOptions>,
|
|
89
|
-
): Promise<VideoJobResult> {
|
|
90
|
-
const { model, size, duration, modelOptions } = options
|
|
91
|
-
|
|
92
|
-
// Validate inputs
|
|
93
|
-
this.validateVideoSize(model, size)
|
|
94
|
-
const seconds = duration ?? (modelOptions as any)?.seconds
|
|
95
|
-
this.validateVideoSeconds(model, seconds)
|
|
96
|
-
|
|
97
|
-
// Build request
|
|
98
|
-
const request = this.buildRequest(options)
|
|
99
|
-
|
|
100
|
-
try {
|
|
101
|
-
options.logger.request(
|
|
102
|
-
`activity=video.create provider=${this.name} model=${model} size=${request.size ?? 'default'} seconds=${request.seconds ?? 'default'}`,
|
|
103
|
-
{ provider: this.name, model },
|
|
104
|
-
)
|
|
105
|
-
// The video API on the OpenAI SDK is still experimental and shipped on
|
|
106
|
-
// some SDK versions but not others; access through `videosClient` lets
|
|
107
|
-
// subclasses override the entry point or supply a polyfill without
|
|
108
|
-
// forcing every call site through `as any`.
|
|
109
|
-
const videosClient = this.getVideosClient()
|
|
110
|
-
const response = await videosClient.create(request)
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
jobId: response.id,
|
|
114
|
-
model,
|
|
115
|
-
}
|
|
116
|
-
} catch (error: any) {
|
|
117
|
-
options.logger.errors(`${this.name}.createVideoJob fatal`, {
|
|
118
|
-
error: toRunErrorPayload(error, `${this.name}.createVideoJob failed`),
|
|
119
|
-
source: `${this.name}.createVideoJob`,
|
|
120
|
-
})
|
|
121
|
-
if (error?.message?.includes('videos') || error?.code === 'invalid_api') {
|
|
122
|
-
throw new Error(
|
|
123
|
-
`Video generation API is not available. The API may require special access. ` +
|
|
124
|
-
`Original error: ${error.message}`,
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
throw error
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Returns the underlying OpenAI Videos resource. Pulled out as a protected
|
|
133
|
-
* accessor so subclasses targeting forks of the SDK can swap the access
|
|
134
|
-
* path without forcing each call site to cast through `any`.
|
|
135
|
-
*/
|
|
136
|
-
protected getVideosClient(): {
|
|
137
|
-
create: (req: Record<string, any>) => Promise<{ id: string }>
|
|
138
|
-
retrieve: (id: string) => Promise<{
|
|
139
|
-
id: string
|
|
140
|
-
status: string
|
|
141
|
-
progress?: number
|
|
142
|
-
url?: string
|
|
143
|
-
expires_at?: number
|
|
144
|
-
error?: { message?: string }
|
|
145
|
-
}>
|
|
146
|
-
downloadContent?: (id: string) => Promise<Response>
|
|
147
|
-
content?: (id: string) => Promise<unknown>
|
|
148
|
-
getContent?: (id: string) => Promise<unknown>
|
|
149
|
-
download?: (id: string) => Promise<unknown>
|
|
150
|
-
} {
|
|
151
|
-
return (this.client as unknown as { videos: any }).videos
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Get the current status of a video generation job.
|
|
156
|
-
*
|
|
157
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
158
|
-
*/
|
|
159
|
-
async getVideoStatus(jobId: string): Promise<VideoStatusResult> {
|
|
160
|
-
try {
|
|
161
|
-
const videosClient = this.getVideosClient()
|
|
162
|
-
const response = await videosClient.retrieve(jobId)
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
jobId,
|
|
166
|
-
status: this.mapStatus(response.status),
|
|
167
|
-
progress: response.progress,
|
|
168
|
-
error: response.error?.message,
|
|
169
|
-
}
|
|
170
|
-
} catch (error: any) {
|
|
171
|
-
if (error.status === 404) {
|
|
172
|
-
return {
|
|
173
|
-
jobId,
|
|
174
|
-
status: 'failed',
|
|
175
|
-
error: 'Job not found',
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
throw error
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Get the URL to download/view the generated video.
|
|
184
|
-
*
|
|
185
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
186
|
-
*/
|
|
187
|
-
async getVideoUrl(jobId: string): Promise<VideoUrlResult> {
|
|
188
|
-
try {
|
|
189
|
-
const videosClient = this.getVideosClient()
|
|
190
|
-
|
|
191
|
-
// Prefer retrieve() because many openai-compatible backends (and the
|
|
192
|
-
// aimock test harness) return the URL directly on the video resource
|
|
193
|
-
// and do not implement a separate /content endpoint. Subclasses can
|
|
194
|
-
// override this method if they need to download raw bytes via
|
|
195
|
-
// downloadContent()/content().
|
|
196
|
-
const videoInfo = await videosClient.retrieve(jobId)
|
|
197
|
-
if (videoInfo.url) {
|
|
198
|
-
return {
|
|
199
|
-
jobId,
|
|
200
|
-
url: videoInfo.url,
|
|
201
|
-
expiresAt: videoInfo.expires_at
|
|
202
|
-
? new Date(videoInfo.expires_at)
|
|
203
|
-
: undefined,
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// SDK download fall-through: try the various possible method names in
|
|
208
|
-
// decreasing order of modernity.
|
|
209
|
-
if (typeof videosClient.downloadContent === 'function') {
|
|
210
|
-
const contentResponse = await videosClient.downloadContent(jobId)
|
|
211
|
-
const videoBlob = await contentResponse.blob()
|
|
212
|
-
const buffer = await videoBlob.arrayBuffer()
|
|
213
|
-
warnIfLargeMediaBuffer(
|
|
214
|
-
buffer.byteLength,
|
|
215
|
-
'video.downloadContent',
|
|
216
|
-
this.name,
|
|
217
|
-
)
|
|
218
|
-
const base64 = arrayBufferToBase64(buffer)
|
|
219
|
-
const mimeType =
|
|
220
|
-
contentResponse.headers.get('content-type') || 'video/mp4'
|
|
221
|
-
return {
|
|
222
|
-
jobId,
|
|
223
|
-
url: `data:${mimeType};base64,${base64}`,
|
|
224
|
-
expiresAt: undefined,
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// The remaining SDK fall-throughs all return a binary payload
|
|
229
|
-
// (Blob/Response/ArrayBuffer-shaped), NOT an `{ url, expires_at }`
|
|
230
|
-
// object the way the bottom return assumed. Convert to a data URL
|
|
231
|
-
// here so the caller actually receives a usable URL.
|
|
232
|
-
let response: any
|
|
233
|
-
if (typeof videosClient.content === 'function') {
|
|
234
|
-
response = await videosClient.content(jobId)
|
|
235
|
-
} else if (typeof videosClient.getContent === 'function') {
|
|
236
|
-
response = await videosClient.getContent(jobId)
|
|
237
|
-
} else if (typeof videosClient.download === 'function') {
|
|
238
|
-
response = await videosClient.download(jobId)
|
|
239
|
-
} else {
|
|
240
|
-
// Last resort: raw fetch with auth header.
|
|
241
|
-
const baseUrl = this.clientConfig.baseURL || 'https://api.openai.com/v1'
|
|
242
|
-
const apiKey = this.clientConfig.apiKey
|
|
243
|
-
|
|
244
|
-
const contentResponse = await fetch(
|
|
245
|
-
`${baseUrl}/videos/${jobId}/content`,
|
|
246
|
-
{
|
|
247
|
-
method: 'GET',
|
|
248
|
-
headers: {
|
|
249
|
-
Authorization: `Bearer ${apiKey}`,
|
|
250
|
-
},
|
|
251
|
-
},
|
|
252
|
-
)
|
|
253
|
-
|
|
254
|
-
if (!contentResponse.ok) {
|
|
255
|
-
const contentType = contentResponse.headers.get('content-type')
|
|
256
|
-
if (contentType?.includes('application/json')) {
|
|
257
|
-
const errorData = await contentResponse.json().catch(() => ({}))
|
|
258
|
-
throw new Error(
|
|
259
|
-
errorData.error?.message ||
|
|
260
|
-
`Failed to get video content: ${contentResponse.status}`,
|
|
261
|
-
)
|
|
262
|
-
}
|
|
263
|
-
throw new Error(
|
|
264
|
-
`Failed to get video content: ${contentResponse.status}`,
|
|
265
|
-
)
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const videoBlob = await contentResponse.blob()
|
|
269
|
-
const buffer = await videoBlob.arrayBuffer()
|
|
270
|
-
warnIfLargeMediaBuffer(buffer.byteLength, 'video.fetch', this.name)
|
|
271
|
-
const base64 = arrayBufferToBase64(buffer)
|
|
272
|
-
const mimeType =
|
|
273
|
-
contentResponse.headers.get('content-type') || 'video/mp4'
|
|
274
|
-
|
|
275
|
-
return {
|
|
276
|
-
jobId,
|
|
277
|
-
url: `data:${mimeType};base64,${base64}`,
|
|
278
|
-
expiresAt: undefined,
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// The fall-through SDK methods produce a Blob-ish or fetch-`Response`-ish
|
|
283
|
-
// object. Read it as bytes and wrap in a data URL so callers see an
|
|
284
|
-
// actual playable URL instead of the API endpoint URL (which is what
|
|
285
|
-
// `response.url` would be on a fetch Response).
|
|
286
|
-
const fallthroughBlob =
|
|
287
|
-
typeof response?.blob === 'function'
|
|
288
|
-
? await response.blob()
|
|
289
|
-
: response instanceof Blob
|
|
290
|
-
? response
|
|
291
|
-
: null
|
|
292
|
-
if (!fallthroughBlob) {
|
|
293
|
-
throw new Error(
|
|
294
|
-
`Video content download via SDK fall-through returned an unexpected shape (no blob()). ` +
|
|
295
|
-
`Override getVideoUrl() in your subclass to handle this provider.`,
|
|
296
|
-
)
|
|
297
|
-
}
|
|
298
|
-
const fallthroughBuffer = await fallthroughBlob.arrayBuffer()
|
|
299
|
-
warnIfLargeMediaBuffer(
|
|
300
|
-
fallthroughBuffer.byteLength,
|
|
301
|
-
'video.sdkFallthrough',
|
|
302
|
-
this.name,
|
|
303
|
-
)
|
|
304
|
-
const fallthroughBase64 = arrayBufferToBase64(fallthroughBuffer)
|
|
305
|
-
const fallthroughMime =
|
|
306
|
-
(typeof response?.headers?.get === 'function'
|
|
307
|
-
? response.headers.get('content-type')
|
|
308
|
-
: undefined) ||
|
|
309
|
-
fallthroughBlob.type ||
|
|
310
|
-
'video/mp4'
|
|
311
|
-
return {
|
|
312
|
-
jobId,
|
|
313
|
-
url: `data:${fallthroughMime};base64,${fallthroughBase64}`,
|
|
314
|
-
expiresAt: undefined,
|
|
315
|
-
}
|
|
316
|
-
} catch (error: any) {
|
|
317
|
-
if (error.status === 404) {
|
|
318
|
-
throw new Error(`Video job not found: ${jobId}`)
|
|
319
|
-
}
|
|
320
|
-
if (error.status === 400) {
|
|
321
|
-
throw new Error(
|
|
322
|
-
`Video is not ready for download. Check status first. Job ID: ${jobId}`,
|
|
323
|
-
)
|
|
324
|
-
}
|
|
325
|
-
throw error
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
protected buildRequest(
|
|
330
|
-
options: VideoGenerationOptions<TProviderOptions>,
|
|
331
|
-
): Record<string, any> {
|
|
332
|
-
const { model, prompt, size, duration, modelOptions } = options
|
|
333
|
-
|
|
334
|
-
const request: Record<string, any> = {
|
|
335
|
-
model,
|
|
336
|
-
prompt,
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
if (size) {
|
|
340
|
-
request['size'] = size
|
|
341
|
-
} else if ((modelOptions as any)?.size) {
|
|
342
|
-
request['size'] = (modelOptions as any).size
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
const seconds = duration ?? (modelOptions as any)?.seconds
|
|
346
|
-
if (seconds !== undefined) {
|
|
347
|
-
request['seconds'] = String(seconds)
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
return request
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
protected validateVideoSize(_model: string, _size?: string): void {
|
|
354
|
-
// Default: no size validation — subclasses can override
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
protected validateVideoSeconds(
|
|
358
|
-
_model: string,
|
|
359
|
-
_seconds?: number | string,
|
|
360
|
-
): void {
|
|
361
|
-
// Default: no duration validation — subclasses can override
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
protected mapStatus(
|
|
365
|
-
apiStatus: string,
|
|
366
|
-
): 'pending' | 'processing' | 'completed' | 'failed' {
|
|
367
|
-
switch (apiStatus) {
|
|
368
|
-
case 'queued':
|
|
369
|
-
case 'pending':
|
|
370
|
-
return 'pending'
|
|
371
|
-
case 'processing':
|
|
372
|
-
case 'in_progress':
|
|
373
|
-
return 'processing'
|
|
374
|
-
case 'completed':
|
|
375
|
-
case 'succeeded':
|
|
376
|
-
return 'completed'
|
|
377
|
-
case 'failed':
|
|
378
|
-
case 'error':
|
|
379
|
-
case 'cancelled':
|
|
380
|
-
return 'failed'
|
|
381
|
-
default:
|
|
382
|
-
return 'processing'
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
package/src/types/config.ts
DELETED
package/src/utils/client.ts
DELETED