UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

122 lines • 4.52 kB
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= import { sleep } from "../../utils/abort.js"; import { ApiError } from "../api/errors.js"; class DifyHttpError extends ApiError { retryAfter; constructor(status, retryAfter) { super(`Dify request failed with status ${String(status)}`, status); this.retryAfter = retryAfter; } } function isRetryable(error) { if (error instanceof DifyHttpError) { return error.status === 429 || (error.status >= 500 && error.status < 600); } return true; } function retryDelayMs(error, attempt, maxDelay) { if (error instanceof DifyHttpError && error.retryAfter !== null) { const parsed = Number.parseFloat(error.retryAfter); if (!Number.isNaN(parsed)) { return Math.min(maxDelay, Math.max(0, parsed)) * 1000; } } return Math.min(maxDelay, 2 ** (attempt - 1)) * 1000; } async function requestOnce(accessor, method, endpoint, options) { const response = await accessor.request(method, endpoint, options); if (!response.ok) { throw new DifyHttpError(response.status, response.headers.get('Retry-After')); } const payload = await response.json(); if (payload === null || typeof payload !== 'object' || Array.isArray(payload)) { throw new Error('Dify response must be a JSON object'); } return payload; } async function difyRequest(accessor, method, endpoint, options = {}) { const attempts = accessor.config.retryAttempts; let lastError; for (let attempt = 1; attempt <= attempts; attempt++) { try { return await requestOnce(accessor, method, endpoint, options); } catch (err) { lastError = err; if (attempt >= attempts || !isRetryable(err)) throw err; await sleep(retryDelayMs(err, attempt, accessor.config.retryMaxDelay)); } } throw lastError; } function difyGet(accessor, endpoint, params) { return difyRequest(accessor, 'GET', endpoint, params !== undefined ? { params } : {}); } export function difyPost(accessor, endpoint, json) { return difyRequest(accessor, 'POST', endpoint, { json }); } function asRecordList(value) { if (!Array.isArray(value)) return []; const out = []; for (const item of value) { if (item !== null && typeof item === 'object' && !Array.isArray(item)) { out.push(item); } } return out; } function isVisibleDocument(document) { return (document.enabled === true && document.indexing_status === 'completed' && document.archived === false); } export async function listAllDocuments(accessor) { const documents = []; let page = 1; for (;;) { const payload = await difyGet(accessor, `/datasets/${accessor.config.datasetId}/documents`, { page, limit: 100, }); for (const document of asRecordList(payload.data)) { if (isVisibleDocument(document)) documents.push(document); } if (payload.has_more !== true) return documents; page += 1; } } export async function* iterSegmentPages(accessor, documentId) { let page = 1; for (;;) { const payload = await difyGet(accessor, `/datasets/${accessor.config.datasetId}/documents/${documentId}/segments`, { page, limit: 100, status: 'completed', enabled: 'true' }); yield asRecordList(payload.data); if (payload.has_more !== true) return; page += 1; } } export async function getDocumentSegments(accessor, documentId) { const segments = []; for await (const pageSegments of iterSegmentPages(accessor, documentId)) { for (const item of pageSegments) segments.push(item); } return segments; } //# sourceMappingURL=client.js.map