refactor(media): share the ComfyUI JSON request helpers
Queue, interrupt and prompt requests now go through one JSON helper, so the cancel path reads like the rest of the client. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u
This commit is contained in:
parent
4217e4b4af
commit
3b97805f20
@ -75,6 +75,7 @@ export interface ComfyUiProvider extends ImageGenerationProvider, VideoGeneratio
|
||||
}
|
||||
|
||||
type MediaKind = "image" | "video";
|
||||
type ReadBody<T> = (response: Response, signal: AbortSignal) => Promise<T>;
|
||||
|
||||
interface OutputFile {
|
||||
filename: string;
|
||||
@ -259,20 +260,18 @@ class ComfyUiClient implements ComfyUiProvider {
|
||||
}
|
||||
|
||||
private async submit(graph: ComfyWorkflow, signal: AbortSignal): Promise<string> {
|
||||
const body = JSON.stringify({ prompt: graph, client_id: this.clientId });
|
||||
return this.send("prompt", { method: "POST", headers: JSON_HEADERS, body }, signal, {
|
||||
read: async (response, readSignal) => {
|
||||
if (response.status === 400) {
|
||||
const rejection = await readJson(response, readSignal).catch(() => undefined);
|
||||
throw new Error(describeWorkflowRejection(rejection));
|
||||
}
|
||||
const result = await readOkJson(response, readSignal);
|
||||
const promptId = isRecord(result) ? result.prompt_id : undefined;
|
||||
if (typeof promptId !== "string" || !promptId) {
|
||||
throw new Error("ComfyUI did not accept the workflow");
|
||||
}
|
||||
return promptId;
|
||||
},
|
||||
const payload = { prompt: graph, client_id: this.clientId };
|
||||
return this.postJson("prompt", payload, signal, async (response, readSignal) => {
|
||||
if (response.status === 400) {
|
||||
const rejection = await readJson(response, readSignal).catch(() => undefined);
|
||||
throw new Error(describeWorkflowRejection(rejection));
|
||||
}
|
||||
const result = await readOkJson(response, readSignal);
|
||||
const promptId = isRecord(result) ? result.prompt_id : undefined;
|
||||
if (typeof promptId !== "string" || !promptId) {
|
||||
throw new Error("ComfyUI did not accept the workflow");
|
||||
}
|
||||
return promptId;
|
||||
});
|
||||
}
|
||||
|
||||
@ -291,29 +290,20 @@ class ComfyUiClient implements ComfyUiProvider {
|
||||
|
||||
/** Best effort: drops the prompt from the queue, or interrupts it when it is ours and running. */
|
||||
private async cancelPrompt(promptId: string): Promise<void> {
|
||||
const options = { timeoutMs: CANCEL_TIMEOUT_MS, read: discardBody };
|
||||
try {
|
||||
const body = JSON.stringify({ delete: [promptId] });
|
||||
await this.send("queue", { method: "POST", headers: JSON_HEADERS, body }, undefined, options);
|
||||
const queue = await this.send(
|
||||
await this.postJson(
|
||||
"queue",
|
||||
{ headers: { Accept: "application/json" } },
|
||||
{ delete: [promptId] },
|
||||
undefined,
|
||||
{
|
||||
timeoutMs: CANCEL_TIMEOUT_MS,
|
||||
read: readOkJson,
|
||||
},
|
||||
discardBody,
|
||||
CANCEL_TIMEOUT_MS,
|
||||
);
|
||||
const queue = await this.getJson("queue", undefined, CANCEL_TIMEOUT_MS);
|
||||
const running =
|
||||
isRecord(queue) && Array.isArray(queue.queue_running) ? queue.queue_running : [];
|
||||
if (running.some((entry) => Array.isArray(entry) && entry[1] === promptId)) {
|
||||
const interrupt = JSON.stringify({ prompt_id: promptId });
|
||||
await this.send(
|
||||
"interrupt",
|
||||
{ method: "POST", headers: JSON_HEADERS, body: interrupt },
|
||||
undefined,
|
||||
options,
|
||||
);
|
||||
const interrupt = { prompt_id: promptId };
|
||||
await this.postJson("interrupt", interrupt, undefined, discardBody, CANCEL_TIMEOUT_MS);
|
||||
}
|
||||
} catch {
|
||||
// The prompt then finishes on its own; nothing waits for it.
|
||||
@ -379,10 +369,20 @@ class ComfyUiClient implements ComfyUiProvider {
|
||||
});
|
||||
}
|
||||
|
||||
private getJson(path: string, signal: AbortSignal | undefined): Promise<unknown> {
|
||||
return this.send(path, { headers: { Accept: "application/json" } }, signal, {
|
||||
read: readOkJson,
|
||||
});
|
||||
private getJson(path: string, signal: AbortSignal | undefined, timeoutMs?: number) {
|
||||
const init = { headers: { Accept: "application/json" } };
|
||||
return this.send(path, init, signal, { timeoutMs, read: readOkJson });
|
||||
}
|
||||
|
||||
private postJson<T>(
|
||||
path: string,
|
||||
payload: unknown,
|
||||
signal: AbortSignal | undefined,
|
||||
read: ReadBody<T>,
|
||||
timeoutMs?: number,
|
||||
): Promise<T> {
|
||||
const init = { method: "POST", headers: JSON_HEADERS, body: JSON.stringify(payload) };
|
||||
return this.send(path, init, signal, { timeoutMs, read });
|
||||
}
|
||||
|
||||
/** One request, with the timeout covering the response body too. */
|
||||
@ -394,10 +394,7 @@ class ComfyUiClient implements ComfyUiProvider {
|
||||
body?: string | Uint8Array<ArrayBuffer>;
|
||||
},
|
||||
signal: AbortSignal | undefined,
|
||||
options: {
|
||||
timeoutMs?: number;
|
||||
read: (response: Response, signal: AbortSignal) => Promise<T>;
|
||||
},
|
||||
options: { timeoutMs?: number; read: ReadBody<T> },
|
||||
): Promise<T> {
|
||||
const timeout = AbortSignal.timeout(options.timeoutMs ?? REQUEST_TIMEOUT_MS);
|
||||
const requestSignal = signal ? AbortSignal.any([signal, timeout]) : timeout;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user