UNPKG

koishi-plugin-gradio-service

Version:
526 lines (525 loc) 20.8 kB
import { Context, Schema, Service } from 'koishi'; export interface ApiData { label: string; parameter_name: string; parameter_default?: any; parameter_has_default?: boolean; type: { type: any; description: string; enum?: string[]; }; component: string; example_input?: any; python_type: { type: string; description: string; }; serializer: string; } export interface JsApiData { label: string; parameter_name: string; parameter_default?: any; parameter_has_default?: boolean; type: string; enum?: string[]; description: string; component: string; example_input?: any; serializer: string; python_type: { type: string; description: string; }; } export interface EndpointInfo<T extends ApiData | JsApiData> { parameters: T[]; returns: T[]; type?: DependencyTypes; } export interface ApiInfo<T extends ApiData | JsApiData> { named_endpoints: Record<string, EndpointInfo<T>>; unnamed_endpoints: Record<string, EndpointInfo<T>>; } export interface BlobRef { path: string[]; type: string | undefined; blob: Blob | File | false; } export type DataType = string | Buffer | Record<string, any> | any[]; export class Command { type: string; command: string; meta: { path: string; name: string; orig_path: string; }; fileData?: FileData; constructor(command: string, meta: { path: string; name: string; orig_path: string; }); } export type SubmitFunction = (endpoint: string | number, data?: unknown[] | Record<string, unknown>, event_data?: unknown, trigger_id?: number | null) => SubmitIterable<GradioEvent>; export type PredictFunction = (endpoint: string | number, data?: unknown[] | Record<string, unknown>, event_data?: unknown) => Promise<PredictReturn>; export type client_return = { config: Config | undefined; predict: PredictFunction; submit: SubmitFunction; viewApi: (_fetch: typeof fetch) => Promise<ApiInfo<JsApiData>>; }; export interface SubmitIterable<T> extends AsyncIterable<T> { [Symbol.asyncIterator](): AsyncIterator<T>; cancel: () => Promise<void>; } export type PredictReturn = { type: EventType; time: Date; data: unknown; endpoint: string; fn_index: number; }; export type SpaceStatus = SpaceStatusNormal | SpaceStatusError; export interface SpaceStatusNormal { status: 'sleeping' | 'running' | 'building' | 'error' | 'stopped' | 'starting'; detail: 'SLEEPING' | 'RUNNING' | 'RUNNING_BUILDING' | 'BUILDING' | 'APP_STARTING' | 'NOT_FOUND'; load_status: 'pending' | 'error' | 'complete' | 'generating'; message: string; } export interface SpaceStatusError { status: 'space_error' | 'paused'; detail: 'NO_APP_FILE' | 'CONFIG_ERROR' | 'BUILD_ERROR' | 'RUNTIME_ERROR' | 'PAUSED'; load_status: 'error'; message: string; discussions_enabled: boolean; } export type SpaceStatusCallback = (a: SpaceStatus) => void; export interface Config { auth_required?: true; analytics_enabled: boolean; connect_heartbeat: boolean; auth_message: string; components: ComponentMeta[]; css: string | null; js: string | null; head: string | null; dependencies: Dependency[]; dev_mode: boolean; enable_queue: boolean; show_error: boolean; layout: any; mode: 'blocks' | 'interface'; root: string; root_url?: string; theme: string; title: string; version: string; space_id: string | null; is_space: boolean; is_colab: boolean; show_api: boolean; stylesheets: string[]; path: string; protocol: 'sse_v3' | 'sse_v2.1' | 'sse_v2' | 'sse_v1' | 'sse' | 'ws'; max_file_size?: number; theme_hash?: number; username: string | null; api_prefix?: string; fill_height?: boolean; fill_width?: boolean; } export interface ComponentMeta { type: string; id: number; has_modes: boolean; props: SharedProps; instance?: any; component?: any; documentation?: Documentation; children?: ComponentMeta[]; parent?: ComponentMeta; value?: any; component_class_id: string; key: string | number | null; rendered_in?: number; } declare interface SharedProps { elem_id?: string; elem_classes?: string[]; components?: string[]; server_fns?: string[]; interactive: boolean; [key: string]: unknown; root_url?: string; } export interface Documentation { type?: TypeDescription; description?: TypeDescription; example_data?: string; } declare interface TypeDescription { input_payload?: string; response_object?: string; payload?: string; } export interface Dependency { id: number; targets: [number, string][]; inputs: number[]; outputs: number[]; backend_fn: boolean; js: string | null; scroll_to_output: boolean; trigger: 'click' | 'load' | string; max_batch_size: number; show_progress: 'full' | 'minimal' | 'hidden'; frontend_fn: ((...args: unknown[]) => Promise<unknown[]>) | null; status?: string; queue: boolean | null; every: number | null; batch: boolean; api_name: string | null; cancels: number[]; types: DependencyTypes; collects_event_data: boolean; pending_request?: boolean; trigger_after?: number; trigger_only_on_success?: boolean; trigger_mode: 'once' | 'multiple' | 'always_last'; final_event: Payload | null; show_api: boolean; zerogpu?: boolean; rendered_in: number | null; } export interface DependencyTypes { generator: boolean; cancel: boolean; } export interface Payload { fn_index: number; data: unknown[]; time?: Date; event_data?: unknown; trigger_id?: number | null; } export interface PostResponse { error?: string; [x: string]: any; } export interface UploadResponse { error?: string; files?: string[]; } export interface DuplicateOptions extends ClientOptions { private?: boolean; hardware?: string; timeout?: number; } export interface ClientOptions { hf_token?: `hf_${string}`; status_callback?: SpaceStatusCallback | null; auth?: [string, string] | null; with_null_state?: boolean; events?: EventType[]; proxyAgent?: string; headers?: Record<string, string>; } export interface FileData { name: string; orig_name?: string; size?: number; data: string; blob?: File; is_file?: boolean; mime_type?: string; alt_text?: string; } export type EventType = 'data' | 'status' | 'log' | 'render'; export interface EventMap { data: PayloadMessage; status: StatusMessage; log: LogMessage; render: RenderMessage; } export type GradioEvent = { [P in EventType]: EventMap[P]; }[EventType]; export interface Log { log: string; level: 'warning' | 'info'; } export interface Render { data: { components: any[]; layout: any; dependencies: Dependency[]; render_id: number; }; } export interface Status { queue: boolean; code?: string; success?: boolean; stage: 'pending' | 'error' | 'complete' | 'generating'; duration?: number; visible?: boolean; broken?: boolean; size?: number; position?: number; eta?: number; message?: string; progress_data?: { progress: number | null; index: number | null; length: number | null; unit: string | null; desc: string | null; }[]; time?: Date; changed_state_ids?: number[]; } export interface StatusMessage extends Status { type: 'status'; endpoint: string; fn_index: number; } export interface PayloadMessage extends Payload { type: 'data'; endpoint: string; fn_index: number; } export interface LogMessage extends Log { type: 'log'; endpoint: string; fn_index: number; duration: number | null; visible: boolean; } export interface RenderMessage extends Render { type: 'render'; endpoint: string; fn_index: number; } export const HOST_URL = "host"; export const API_URL = "predict/"; export const SSE_URL_V0 = "queue/join"; export const SSE_DATA_URL_V0 = "queue/data"; export const SSE_URL = "queue/data"; export const SSE_DATA_URL = "queue/join"; export const UPLOAD_URL = "upload"; export const LOGIN_URL = "login"; export const CONFIG_URL = "config"; export const API_INFO_URL = "info"; export const RUNTIME_URL = "runtime"; export const SLEEPTIME_URL = "sleeptime"; export const HEARTBEAT_URL = "heartbeat"; export const COMPONENT_SERVER_URL = "component_server"; export const RESET_URL = "reset"; export const CANCEL_URL = "cancel"; export const RAW_API_INFO_URL = "info?serialize=False"; export const SPACE_FETCHER_URL = "https://gradio-space-api-fetcher-v2.hf.space/api"; export const SPACE_URL = "https://hf.space/{}"; export const QUEUE_FULL_MSG = "This application is currently busy. Please try again. "; export const BROKEN_CONNECTION_MSG = "Connection errored out. "; export const CONFIG_ERROR_MSG = "Could not resolve app config. "; export const SPACE_STATUS_ERROR_MSG = "Could not get space status. "; export const API_INFO_ERROR_MSG = "Could not get API info. "; export const SPACE_METADATA_ERROR_MSG = "Space metadata could not be loaded. "; export const INVALID_URL_MSG = "Invalid URL. A full URL path is required."; export const UNAUTHORIZED_MSG = "Not authorized to access this space. "; export const INVALID_CREDENTIALS_MSG = "Invalid credentials. Could not login. "; export const MISSING_CREDENTIALS_MSG = "Login credentials are required to access this space."; export const NODEJS_FS_ERROR_MSG = "File system access is only available in Node.js environments"; export const ROOT_URL_ERROR_MSG = "Root URL not found in client config"; export const FILE_PROCESSING_ERROR_MSG = "Error uploading file"; export function getJwt(ctx: Context, space: string, token: `hf_${string}`, cookies?: string | null): Promise<string | false>; export function determineProtocol(endpoint: string): { ws_protocol: 'ws' | 'wss'; http_protocol: 'http:' | 'https:'; host: string; }; export const parseAndSetCookies: (cookieHeader: string) => string[]; export function getCookieHeader(httpProtocol: string, host: string, auth: [string, string], ctx: Context, hfToken?: `hf_${string}`): Promise<string | null>; export function resolveConfig(this: Client, endpoint: string): Promise<Config | undefined>; export function resolveCookies(this: Client): Promise<void>; export function mapNamesToIds(fns: Config['dependencies']): Record<string, number>; /** * This function is used to resolve the URL for making requests when the app has a root path. * The root path could be a path suffix like "/app" which is appended to the end of the base URL. Or * it could be a full URL like "https://abidlabs-test-client-replica--gqf2x.hf.space" which is used when hosting * Gradio apps on Hugging Face Spaces. * @param {string} base_url The base URL at which the Gradio server is hosted * @param {string} root_path The root path, which could be a path suffix (e.g. mounted in FastAPI app) or a full URL (e.g. hosted on Hugging Face Spaces) * @param {boolean} prioritize_base Whether to prioritize the base URL over the root path. This is used when both the base path and root paths are full URLs. For example, for fetching files the root path should be prioritized, but for making requests, the base URL should be prioritized. * @returns {string} the resolved URL */ export function resolveRoot(baseUrl: string, rootPath: string, prioritizeBase: boolean): string; export const RE_SPACE_NAME: RegExp; export const RE_SPACE_DOMAIN: RegExp; export function processEndpoint(ctx: Context, appReference: string, hfToken?: `hf_${string}`): Promise<{ space_id: string | false; host: string; ws_protocol: 'ws' | 'wss'; http_protocol: 'http:' | 'https:'; }>; export const joinUrls: (...urls: string[]) => string; export function transformAPIInfo(apiInfo: ApiInfo<ApiData>, config: Config, apiMap: Record<string, number>): ApiInfo<JsApiData>; export function getType(type: { type: any; description: string; }, component: string, serializer: string, signatureType: 'return' | 'parameter'): string | undefined; export function getDescription(type: { type: any; description: string; }, serializer: string): string; export function handleMessage(data: any, lastStatus: Status['stage']): { type: 'hash' | 'data' | 'update' | 'complete' | 'generating' | 'log' | 'none' | 'heartbeat' | 'unexpected_error'; data?: any; status?: Status; }; /** * Maps the provided `data` to the parameters defined by the `/info` endpoint response. * This allows us to support both positional and keyword arguments passed to the client * and ensures that all parameters are either directly provided or have default values assigned. * * @param {unknown[] | Record<string, unknown>} data - The input data for the function, * which can be either an array of values for positional arguments or an object * with key-value pairs for keyword arguments. * @param {JsApiData[]} parameters - Array of parameter descriptions retrieved from the * `/info` endpoint. * * @returns {unknown[]} - Returns an array of resolved data where each element corresponds * to the expected parameter from the API. The `parameter_default` value is used where * a value is not provided for a parameter, and optional parameters without defaults are * set to `undefined`. * * @throws {Error} - Throws an error: * - If more arguments are provided than are defined in the parameters. * * - If no parameter value is provided for a required parameter and no default value is defined. * - If an argument is provided that does not match any defined parameter. */ export const mapDataToParams: (data: unknown[] | Record<string, unknown>, endpointInfo: EndpointInfo<JsApiData | ApiData>) => unknown[]; export function viewApi(this: Client): Promise<any>; export function upload(this: Client, fileData: FileData[], rootUrl: string, uploadId?: string, maxFileSize?: number): Promise<(FileData | null)[] | null>; export function prepareFiles(files: File[], isStream?: boolean): Promise<FileData[]>; export class FileData { path: string; url?: string; orig_name?: string; size?: number; blob?: File; is_stream?: boolean; mime_type?: string; alt_text?: string; readonly meta: { _type: string; }; constructor({ path, url, orig_name, size, blob, is_stream, mime_type, alt_text }: { path: string; url?: string; orig_name?: string; size?: number; blob?: File; is_stream?: boolean; mime_type?: string; alt_text?: string; }); } export function updateObject(object: { [x: string]: any; }, newValue: any, stack: (string | number)[]): void; export function walkAndStoreBlobs(data: DataType, type?: string | undefined, path?: string[], root?: boolean, endpointInfo?: EndpointInfo<ApiData | JsApiData> | undefined): Promise<BlobRef[]>; export function skipQueue(id: number, config: Config): boolean; export function postMessage<Res = any>(message: any, origin: string): Promise<Res>; export function handleFile(file: File | string | Blob | Buffer): FileData | Blob | Command; /** * Handles the payload by filtering out state inputs and returning an array of resolved payload values. * We send null values for state inputs to the server, but we don't want to include them in the resolved payload. * * @param resolvedPayload - The resolved payload values received from the client or the server * @param dependency - The dependency object. * @param components - The array of component metadata. * @param withNullState - Optional. Specifies whether to include null values for state inputs. Default is false. * @returns An array of resolved payload values, filtered based on the dependency and component metadata. */ export function handlePayload(resolvedPayload: unknown[], dependency: Dependency, components: ComponentMeta[], type: 'input' | 'output', withNullState?: boolean): unknown[]; export function openStream(this: Client): Promise<void>; export function closeStream(streamStatus: { open: boolean; }, abortController: AbortController | null): void; export function applyDiffStream(pendingDiffStreams: Record<string, any[][]>, eventId: string, data: any): void; export function applyDiff(obj: any, diff: [string, (number | string)[], any][]): any; export function readableStream(ctx: Context, input: string, init?: RequestInit): EventSource; export function postData(this: Client, url: string, body: unknown, additionalHeaders?: any): Promise<[PostResponse, number]>; export function submit(this: Client, endpoint: string | number, data?: unknown[] | Record<string, unknown>, eventData?: unknown, triggerId?: number | null, allEvents?: boolean): SubmitIterable<GradioEvent>; export function predict(this: Client, endpoint: string | number, data?: unknown[] | Record<string, unknown>): Promise<PredictReturn>; declare class GradioClientService extends Service { ctx: Context; config: GradioClientService.Config; constructor(ctx: Context, config: GradioClientService.Config); connect(url: string, options?: ClientOptions): Promise<Client>; } declare module 'koishi' { interface Context { gradio: GradioClientService; } } export const inject: {}; declare namespace GradioClientService { interface Config { baseURL: string; } const Config: Schema<Schemastery.ObjectS<{ baseURL: Schema<string, string>; }>, Schemastery.ObjectT<{ baseURL: Schema<string, string>; }>>; const name = "gradio-service"; } export default GradioClientService; export function uploadFiles(this: Client, rootUrl: string, files: (Blob | File)[], uploadId?: string): Promise<UploadResponse>; export function handleBlob(this: Client, endpoint: string, data: unknown[], apiInfo: EndpointInfo<JsApiData | ApiData>): Promise<unknown[]>; export function processLocalFileCommands(client: Client, data: unknown[]): Promise<void>; export class Client { ctx: Context; appReference: string; options: ClientOptions; apiPrefix: string; config: Config | undefined; apiInfo: ApiInfo<JsApiData> | undefined; apiMap: Record<string, number>; session_hash: string; jwt: string | false; lastStatus: Record<string, Status['stage']>; private cookies; private _resolveConfig; private resolveCookie; viewApi: () => Promise<ApiInfo<JsApiData>>; openStream: () => Promise<void>; postData: (url: string, data: unknown, headers?: Headers) => Promise<[PostResponse, number]>; submit: (endpoint: string | number, data: unknown[] | Record<string, unknown> | undefined, event_data?: unknown, trigger_id?: number | null, all_events?: boolean) => SubmitIterable<GradioEvent>; predict: (endpoint: string | number, data: unknown[] | Record<string, unknown> | undefined, event_data?: unknown) => Promise<PredictReturn>; uploadFiles: (root_url: string, files: (Blob | File)[], upload_id?: string) => Promise<UploadResponse>; upload: (file_data: FileData[], root_url: string, upload_id?: string, max_file_size?: number) => Promise<(FileData | null)[] | null>; handleBlob: (endpoint: string, data: unknown[], endpoint_info: EndpointInfo<ApiData | JsApiData>) => Promise<any[]>; streamStatus: { open: boolean; }; pendingStreamMessages: Record<string, any[][]>; pendingDiffStreams: Record<string, any[][]>; eventCallbacks: Record<string, (data?: unknown) => Promise<void>>; unclosedEvents: Set<string>; abortController: AbortController | null; streamInstance: EventSource | null; constructor(ctx: Context, appReference: string, options?: ClientOptions); init(): Promise<void>; resolveConfig(): Promise<Config>; private _configSuccess; stream(url: URL): EventSource; setCookies(cookies: string): void; static connect(ctx: Context, url: string, options?: ClientOptions): Promise<Client>; close(): void; }