ts / dist / esm / jobs.js
558 words
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { configError, jobFailed } from './errors.js';
import * as http from './http.js';
/** POST /jobs — Enqueue a job (202 with the queued job). */
export const enqueue = (client, spec) => http.post(client, '/jobs', { body: spec });
/** GET /jobs/{id} — Job status: queued/processing/succeeded/failed. */
export const get = (client, id) => http.get(client, '/jobs/{id}', { params: { id } });
/** GET /jobs/{id}/result — Job result. 409 while still running, 410 once expired (24h). */
export const getResult = (client, id) => http.get(client, '/jobs/{id}/result', { params: { id } });
// ---------------------------------------------------------------------------
// Payload builders (one per job type). Options merge first, so `type` and
// the primary input can never be overridden.
/** Check up to 100 domains in one job. */
export const domainAvailabilityBulk = (domains) => ({
    type: 'domain-availability-bulk',
    domains: [...domains],
});
/** Embed INPUT text (`model` defaults server-side). */
export const embedding = (input, options = {}) => ({
    ...options,
    type: 'embedding',
    input,
});
/** Chat completion over MESSAGES. */
export const llmChat = (messages, options = {}) => ({ ...options, type: 'llm-chat', messages: [...messages] });
/** Raw completion of PROMPT. */
export const llmRawCompletion = (prompt, options = {}) => ({ ...options, type: 'llm-raw-completion', prompt });
/** NLP analysis of INPUT text. */
export const nlpAnalyze = (input, options = {}) => ({
    ...options,
    type: 'nlp-analyze',
    input,
});
/** Language detection of INPUT text. */
export const nlpDetectLanguage = (input) => ({
    type: 'nlp-detect-language',
    input,
});
const MIME_TYPES = {
    '.png': 'image/png',
    '.jpg': 'image/jpeg',
    '.jpeg': 'image/jpeg',
    '.webp': 'image/webp',
    '.gif': 'image/gif',
};
const guessMime = (path) => {
    const lower = path.toLowerCase();
    return Object.entries(MIME_TYPES).find(([ext]) => lower.endsWith(ext))?.[1];
};
const toBase64 = (bytes) => {
    let binary = '';
    for (let i = 0; i < bytes.length; i += 0x8000) {
        binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
    }
    return btoa(binary);
};
/** OpenAI-style text content part. */
export const textPart = (text) => ({ type: 'text', text });
/**
 * OpenAI-style image_url content part from SOURCE (a file path or bytes),
 * embedded as a base64 data URL. The MIME type is sniffed from a path's
 * extension (png/jpg/jpeg/webp/gif) or passed explicitly.
 */
export const imagePart = async (source, mimeType) => {
    const mime = mimeType ?? (typeof source === 'string' ? guessMime(source) : undefined);
    if (!mime)
        throw configError('Cannot guess image MIME type; pass it explicitly', { source });
    const bytes = typeof source === 'string' ? new Uint8Array(await (await import('node:fs/promises')).readFile(source)) : source;
    return { type: 'image_url', image_url: { url: `data:${mime};base64,${toBase64(bytes)}` } };
};
/** A user message whose content is TEXT plus any IMAGE-PARTS (from `imagePart`). */
export const userMessage = (text, ...imageParts) => ({
    role: 'user',
    content: [textPart(text), ...imageParts],
});
const TERMINAL = new Set(['succeeded', 'failed']);
/**
 * Enqueue SPEC, poll until the job reaches a terminal status, then fetch
 * and return the result. Throws a jobFailed error with the failed job, or a
 * timeout error when the deadline passes first.
 */
export const run = async (client, spec, options = {}) => {
    const { job } = await enqueue(client, spec);
    const id = job.id;
    const { job: final } = await http.pollUntil(() => get(client, id), (r) => TERMINAL.has(r.job.status), {
        intervalMs: options.intervalMs,
        timeoutMs: options.timeoutMs ?? 120000,
        message: `Timed out waiting for job ${id}`,
        sleep: client.sleep,
    });
    if (final.status === 'succeeded')
        return getResult(client, id);
    throw jobFailed(`Job ${id} failed`, final);
};

static mirror of HEAD · about · clone: git clone https://ird.cod-sursa.ro/ts.git