n8n-nodes-aimlapi
Version:
Custom n8n node for integrating with the AI/ML API platform (AIMLAPI) to interact with LLMs and multimodal AI models such as chat completion endpoints.
309 lines • 10.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractAudioOutputs = extractAudioOutputs;
exports.extractVideoOutputs = extractVideoOutputs;
exports.resolveGenerationResponse = resolveGenerationResponse;
const promises_1 = require("timers/promises");
const request_1 = require("./request");
const SUCCESS_STATUSES = new Set([
'succeeded',
'success',
'completed',
'done',
'ready',
'finished',
]);
const FAILURE_STATUSES = new Set([
'failed',
'error',
'cancelled',
'canceled',
'timeout',
'timed_out',
'expired',
]);
const DEFAULT_POLL_INTERVAL = 2000;
const DEFAULT_MAX_ATTEMPTS = 60;
function collectObjects(root) {
const collected = [];
const visited = new Set();
const stack = [root];
while (stack.length > 0) {
const value = stack.pop();
if (!value || typeof value !== 'object') {
continue;
}
if (visited.has(value)) {
continue;
}
visited.add(value);
if (Array.isArray(value)) {
stack.push(...value);
continue;
}
const objectValue = value;
collected.push(objectValue);
for (const entry of Object.values(objectValue)) {
stack.push(entry);
}
}
return collected;
}
function normalizeStatus(value) {
if (typeof value === 'string' && value.trim() !== '') {
return value.trim().toLowerCase();
}
return undefined;
}
function extractStatus(payload) {
const candidates = collectObjects(payload);
for (const candidate of candidates) {
const status = normalizeStatus(candidate.status ??
candidate.state ??
candidate.task_status ??
candidate.job_status ??
candidate.stage ??
(candidate.task && typeof candidate.task === 'object'
? candidate.task.status
: undefined));
if (status) {
return status;
}
}
return undefined;
}
function extractGenerationId(payload) {
const candidates = collectObjects(payload);
for (const candidate of candidates) {
const ids = [
candidate.generation_id,
candidate.generationId,
candidate.id,
candidate.task_id,
candidate.taskId,
candidate.job_id,
candidate.jobId,
];
for (const id of ids) {
if (typeof id === 'string' && id.trim() !== '') {
return id;
}
}
}
return undefined;
}
function extractErrorMessage(payload) {
const candidates = collectObjects(payload);
for (const candidate of candidates) {
if (typeof candidate.error === 'string' && candidate.error.trim() !== '') {
return candidate.error;
}
if (candidate.error && typeof candidate.error === 'object') {
const errorObject = candidate.error;
const message = (typeof errorObject.message === 'string' && errorObject.message) ||
(typeof errorObject.error === 'string' && errorObject.error);
if (message) {
return message;
}
}
if (typeof candidate.message === 'string' && candidate.message.trim() !== '') {
return candidate.message;
}
}
return undefined;
}
function isSuccessfulStatus(status) {
if (!status) {
return false;
}
return SUCCESS_STATUSES.has(status);
}
function isFailureStatus(status) {
if (!status) {
return false;
}
return FAILURE_STATUSES.has(status);
}
function pushIfMediaObject(target, candidate) {
const url = candidate.url ??
candidate.audio_url ??
candidate.audioUrl ??
candidate.video_url ??
candidate.videoUrl;
const base64 = candidate.b64_json ??
candidate.base64 ??
candidate.audio_base64 ??
candidate.audioBase64 ??
candidate.data ??
candidate.bytes;
if (typeof url === 'string' || typeof base64 === 'string') {
target.push(candidate);
}
}
function extractAudioOutputsFromObject(objectValue, outputs, visited) {
if (visited.has(objectValue)) {
return;
}
visited.add(objectValue);
if (Array.isArray(objectValue)) {
for (const entry of objectValue) {
if (entry && typeof entry === 'object') {
extractAudioOutputsFromObject(entry, outputs, visited);
}
}
return;
}
if (objectValue.audio_file && typeof objectValue.audio_file === 'object') {
extractAudioOutputsFromObject(objectValue.audio_file, outputs, visited);
}
if (objectValue.audio_files && Array.isArray(objectValue.audio_files)) {
for (const entry of objectValue.audio_files) {
if (entry && typeof entry === 'object') {
extractAudioOutputsFromObject(entry, outputs, visited);
}
}
}
if (objectValue.audio && typeof objectValue.audio === 'object') {
extractAudioOutputsFromObject(objectValue.audio, outputs, visited);
}
if (objectValue.tracks && Array.isArray(objectValue.tracks)) {
for (const entry of objectValue.tracks) {
if (entry && typeof entry === 'object') {
extractAudioOutputsFromObject(entry, outputs, visited);
}
}
}
if (objectValue.files && Array.isArray(objectValue.files)) {
for (const entry of objectValue.files) {
if (entry && typeof entry === 'object') {
extractAudioOutputsFromObject(entry, outputs, visited);
}
}
}
if (typeof objectValue.url === 'string' ||
typeof objectValue.b64_json === 'string' ||
typeof objectValue.base64 === 'string') {
pushIfMediaObject(outputs, objectValue);
}
for (const value of Object.values(objectValue)) {
if (value && typeof value === 'object') {
extractAudioOutputsFromObject(value, outputs, visited);
}
}
}
function extractVideoOutputsFromObject(objectValue, outputs, visited) {
if (visited.has(objectValue)) {
return;
}
visited.add(objectValue);
if (Array.isArray(objectValue)) {
for (const entry of objectValue) {
if (entry && typeof entry === 'object') {
extractVideoOutputsFromObject(entry, outputs, visited);
}
}
return;
}
if (objectValue.video && typeof objectValue.video === 'object') {
extractVideoOutputsFromObject(objectValue.video, outputs, visited);
}
if (objectValue.videos && Array.isArray(objectValue.videos)) {
for (const entry of objectValue.videos) {
if (entry && typeof entry === 'object') {
extractVideoOutputsFromObject(entry, outputs, visited);
}
}
}
if (objectValue.assets && Array.isArray(objectValue.assets)) {
for (const entry of objectValue.assets) {
if (entry && typeof entry === 'object') {
extractVideoOutputsFromObject(entry, outputs, visited);
}
}
}
if (objectValue.output && typeof objectValue.output === 'object') {
extractVideoOutputsFromObject(objectValue.output, outputs, visited);
}
if (typeof objectValue.url === 'string') {
pushIfMediaObject(outputs, objectValue);
}
for (const value of Object.values(objectValue)) {
if (value && typeof value === 'object') {
extractVideoOutputsFromObject(value, outputs, visited);
}
}
}
function extractAudioOutputs(payload) {
const outputs = [];
const visited = new Set();
if (payload && typeof payload === 'object') {
extractAudioOutputsFromObject(payload, outputs, visited);
}
return outputs;
}
function extractVideoOutputs(payload) {
const outputs = [];
const visited = new Set();
if (payload && typeof payload === 'object') {
extractVideoOutputsFromObject(payload, outputs, visited);
}
return outputs;
}
function hasMediaPayload(payload, mediaType) {
if (mediaType === 'audio') {
return extractAudioOutputs(payload).length > 0;
}
return extractVideoOutputs(payload).length > 0;
}
function assertNotFailed(payload) {
const status = extractStatus(payload);
if (isFailureStatus(status)) {
const reason = extractErrorMessage(payload);
const suffix = reason ? `: ${reason}` : '';
throw new Error(`Generation failed with status "${status}"${suffix}`);
}
}
function shouldPoll(payload, mediaType) {
const generationId = extractGenerationId(payload);
if (!generationId) {
return { poll: false };
}
const status = extractStatus(payload);
const hasMedia = hasMediaPayload(payload, mediaType);
assertNotFailed(payload);
if (isSuccessfulStatus(status) && hasMedia) {
return { poll: false, generationId };
}
if (!status && hasMedia) {
return { poll: false, generationId };
}
return { poll: true, generationId };
}
async function pollForGeneration(context, baseURL, path, generationId, options) {
const pollInterval = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL;
const maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
let latest;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
if (attempt > 0) {
await (0, promises_1.setTimeout)(pollInterval);
}
const requestOptions = (0, request_1.createRequestOptions)(baseURL, path, 'GET', {
qs: { generation_id: generationId },
});
latest = await context.helpers.httpRequestWithAuthentication.call(context, 'aimlApi', requestOptions);
assertNotFailed(latest);
const pollState = shouldPoll(latest, options.mediaType);
if (!pollState.poll) {
return latest;
}
}
throw new Error(`Timed out while waiting for generation to complete (generation_id: ${generationId})`);
}
async function resolveGenerationResponse(context, baseURL, path, initial, options) {
const pollState = shouldPoll(initial, options.mediaType);
if (!pollState.poll || !pollState.generationId) {
return initial;
}
return pollForGeneration(context, baseURL, path, pollState.generationId, options);
}
//# sourceMappingURL=generation.js.map