flow / src /lib /types.ts
mrfakename's picture
Faster first paint, HF theme, embedded sign-in, bucket sync, commit to repo
c9f1455 verified
Raw History Blame Contribute Delete
8.39 kB
import type { Edge, Node } from "@xyflow/react";
/** Port data types, derived from Gradio component kinds. */
export type DataType =
| "text"
| "number"
| "boolean"
| "image"
| "audio"
| "video"
| "file"
| "gallery"
| "json"
| "any";
export type Category = "Inputs" | "Utilities" | "Spaces" | "Functions";
export type WidgetValue = string | number | boolean;
export type WidgetDef =
| { kind: "text"; id: string; label: string; default: string; placeholder?: string }
| { kind: "textarea"; id: string; label: string; default: string; placeholder?: string; /** Always show the expanded editor (notes, prompts). */ block?: boolean }
| { kind: "number"; id: string; label: string; default: number; min?: number; max?: number; step?: number; precision?: number }
| { kind: "slider"; id: string; label: string; default: number; min: number; max: number; step?: number; precision?: number }
| { kind: "seed"; id: string; label: string; default: number }
| { kind: "select"; id: string; label: string; default: string; options: readonly string[]; /** Raw choice values when the Space uses non-string choices (numbers, booleans), parallel to `options`. */ raw?: readonly (string | number | boolean)[] }
| { kind: "toggle"; id: string; label: string; default: boolean }
/** A file input: value is a URL, or `local:<id>` for a file picked in the browser. */
| { kind: "file"; id: string; label: string; default: string; accept: DataType };
export interface Port {
id: string;
label: string;
type: DataType;
/** Inputs only: how the value is entered when nothing is wired in. */
widget?: WidgetDef;
/** Inputs only: the Gradio component this maps to (for payload shaping). */
component?: string;
optional?: boolean;
}
export interface SpaceRef {
id: string;
apiName: string;
/** Gradio dependency id (fn_index) for the queue protocol. */
fnIndex: number;
triggerId: number | null;
host: string;
apiPrefix: string;
/** Component ids of outputs, in order. */
outputComponents: string[];
/**
* The queue protocol wants one value per dependency input component, but /info lists only the
* ones that take a value (State, buttons and the like are skipped). inputSlots[i] is the port
* index that fills dependency input i, or null for a component that gets no value.
*/
inputSlots?: (number | null)[];
/** outputSlots[k]: which entry of the returned data list is port k (State outputs are skipped). */
outputSlots?: number[];
}
export interface NodeDef {
type: string;
title: string;
category: Category;
description: string;
inputs: Port[];
outputs: Port[];
/** Pure widgets (not wirable), used by input nodes. */
widgets: WidgetDef[];
width?: number;
/** Colour accent; defaults to the first output type. */
accent?: DataType;
/** Set for nodes that call a Space endpoint. */
space?: SpaceRef;
/** Set for input nodes: which widget value is exposed on the single output. */
emits?: string;
/** Simulated cost is gone; 0 marks nodes that never execute (groups, notes). */
cost?: number;
}
export type NodeStatus = "idle" | "queued" | "running" | "done" | "error";
export type NodeMode = "always" | "bypass" | "never";
/** A file produced by a Space, as returned in its output payload. */
export interface FileRef {
url: string;
name?: string;
mime?: string;
}
export type OutputValue = string | number | boolean | FileRef | FileRef[] | null | Record<string, unknown> | unknown[];
export interface CanvasNodeData extends Record<string, unknown> {
defType: string;
title?: string;
values: Record<string, WidgetValue>;
collapsed?: boolean;
mode: NodeMode;
status: NodeStatus;
progress: number;
/** True while `progress` is extrapolated from past run times rather than reported by the Space. */
progressEstimated?: boolean;
/** Short live status, e.g. queue rank or ETA. */
statusText?: string;
error?: string;
/** Results of the last run, keyed by output port id. */
outputs?: Record<string, OutputValue>;
/** Hash of the inputs that produced `outputs`; lets unchanged nodes skip. */
cacheKey?: string;
/** Pinned in place: can't be dragged. */
locked?: boolean;
/** Colour tag (a key of NODE_COLORS). */
color?: string;
/** Free-form note shown under the header. */
note?: string;
/** Group nodes only: the reusable function this group was made from. */
fnId?: string;
/** Group nodes only, derived for display: ports shown while collapsed. */
groupPorts?: { inputs: GroupPort[]; outputs: GroupPort[] };
}
export type CanvasNode = Node<CanvasNodeData, "space" | "group">;
export type CanvasEdge = Edge<{ type: DataType; flowing?: boolean }, "typed">;
/** One line of the run log; the copilot reads these to diagnose failures. */
export interface LogEntry {
t: number;
level: "info" | "warn" | "error";
node?: string;
msg: string;
}
export interface HistoryItem {
id: string;
workflow: string;
finishedAt: number;
durationMs: number;
nodes: number;
status: "done" | "cancelled" | "error";
thumb?: string;
error?: string;
/** The graph as it was when the run finished, outputs included, so it can be restored. */
graph?: GraphSnapshot;
/** Set when this run was one cell of a batch / sweep. */
batch?: BatchRef;
/** Which widget values this run set before starting (seeds, the swept text). */
vary?: VaryRef[];
}
/** Where a run sits in its batch grid: rows are sweep lines, columns are seed variations. */
export interface BatchRef {
id: string;
index: number;
count: number;
rows: number;
cols: number;
row: number;
col: number;
/** What the rows / columns vary ("prompt", "seed"). */
rowLabel?: string;
colLabel?: string;
}
export interface VaryRef {
nodeId: string;
widgetId: string;
label: string;
value: WidgetValue;
}
export interface GraphSnapshot {
nodes: CanvasNode[];
edges: CanvasEdge[];
order: string[];
}
export interface QueueItem {
id: string;
workflow: string;
queuedAt: number;
/** Run only these nodes and what they depend on. */
targets?: string[];
/** Widget values to set just before this item runs (batch runs and sweeps). */
apply?: { nodeId: string; widgetId: string; value: WidgetValue }[];
/** Ignore cached outputs on the targets so they call their Space again. */
force?: boolean;
batch?: BatchRef;
}
export type ViewMode = "canvas" | "pipeline";
export interface GroupPort extends Port {
nodeId: string;
portId: string;
}
export interface FunctionDef {
id: string;
name: string;
description: string;
nodes: CanvasNode[];
edges: CanvasEdge[];
}
export type SpaceStage = "RUNNING" | "SLEEPING" | "BUILDING" | "PAUSED" | "STOPPED" | "RUNTIME_ERROR" | "NO_APP_FILE" | "CONFIG_ERROR" | "BUILD_ERROR" | "DELETING" | "APP_STARTING" | "UNKNOWN";
export interface SpaceSummary {
id: string;
author: string;
name: string;
title: string;
emoji: string;
likes: number;
sdk?: string;
stage: SpaceStage;
hardware: string | null;
zeroGpu: boolean;
subdomain: string;
shortDescription?: string;
/** Card gradient colours from the Space README, as Hugging Face shows them. */
colorFrom?: string;
colorTo?: string;
private?: boolean;
}
/** A Space added to the workflow, with the node defs derived from its API. */
export interface SpaceEntry {
summary: SpaceSummary;
host: string;
apiPrefix: string;
version?: string;
defs: NodeDef[];
status: "loading" | "ready" | "error";
error?: string;
loadedAt?: number;
}
export interface WorkflowTemplate {
id: string;
name: string;
description: string;
/** Space ids that must be loaded before the graph can be built. */
spaces: string[];
build: (defsOf: (spaceId: string) => NodeDef[]) => { nodes: CanvasNode[]; edges: CanvasEdge[] };
}
/** The on-disk workflow file. */
export interface WorkflowFile {
version: 1;
/** Stable id of the saved document (cloud sync key). Absent in older files. */
id?: string;
/** ms epoch of the last edit that was saved. */
updatedAt?: number;
/** Changed by the user (not just a template as loaded). */
edited?: boolean;
name: string;
nodes: CanvasNode[];
edges: CanvasEdge[];
order: string[];
functions: FunctionDef[];
/** Schema snapshot so the graph renders before live schemas arrive. */
spaces: SpaceEntry[];
}