From 28d8bfdd228217394477a4bd515e6458b6e66c19 Mon Sep 17 00:00:00 2001 From: Kwaroran Date: Wed, 25 Dec 2024 21:06:52 +0900 Subject: [PATCH] Fix nativeFetch and comfy --- src/lang/en.ts | 1 + src/lib/Setting/Pages/OtherBotSettings.svelte | 20 ++++++++- src/ts/globalApi.svelte.ts | 41 +++++++---------- src/ts/process/stableDiff.ts | 44 ++++++++++++++----- 4 files changed, 67 insertions(+), 39 deletions(-) diff --git a/src/lang/en.ts b/src/lang/en.ts index 3dca20d2..c6793efa 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -173,6 +173,7 @@ export const languageEnglish = { autoTranslateCachedOnly: "If enabled, it will automatically translate only the text that the user has translated previously.", presetChain: "If it is not blank, the preset will be changed and applied randomly every time when user sends a message in the preset list in this input. preset list should be seperated by comma, for example, `preset1,preset2`.", legacyMediaFindings: "If enabled, it will use the old method to find media assets, without using the additional search algorithm.", + comfyWorkflow: "Put the API workflow of comfy UI. you can get your API workflow in comfy UI by pressing the 'Workflow > Export (API)' button. you must also put {{risu_prompt}} in you workflow text. the {{risu_prompt}} will be replaced with the prompt provided by the Risu.", }, setup: { chooseProvider: "Choose AI Provider", diff --git a/src/lib/Setting/Pages/OtherBotSettings.svelte b/src/lib/Setting/Pages/OtherBotSettings.svelte index d728821a..d91ab531 100644 --- a/src/lib/Setting/Pages/OtherBotSettings.svelte +++ b/src/lib/Setting/Pages/OtherBotSettings.svelte @@ -77,8 +77,13 @@ Novel AI Dall-E Stability API - ComfyUI Fal.ai + ComfyUI + + + {#if DBState.db.sdProvider === 'comfy'} + ComfyUI (Legacy) + {/if} {#if DBState.db.sdProvider === 'webui'} @@ -277,8 +282,19 @@ {/if} {/if} + {#if DBState.db.sdProvider === 'comfyui'} + ComfyUI {language.providerURL} + + + Workflow + + + Timeout (sec) + + {/if} + {#if DBState.db.sdProvider === 'comfy'} - The first image generated by the prompt will be selected. + The first image generated by the prompt will be selected. {#if !isTauri} "Please run comfyUI with --enable-cors-header." {/if} diff --git a/src/ts/globalApi.svelte.ts b/src/ts/globalApi.svelte.ts index d4483664..d4ef02cd 100644 --- a/src/ts/globalApi.svelte.ts +++ b/src/ts/globalApi.svelte.ts @@ -1821,20 +1821,18 @@ const pipeFetchLog = (fetchLogIndex: number, readableStream: ReadableStream; - headers: Headers; - status: number; - json: () => Promise; - text: () => Promise; - arrayBuffer: () => Promise; -}> { +}):Promise { + + console.log(arg.body,'body') + if(arg.body === undefined && (arg.method === 'POST' || arg.method === 'PUT') ){ + throw new Error('Body is required for POST and PUT requests') + } const jsonizer = (body:ReadableStream) => { return async () => { @@ -1876,9 +1874,9 @@ export async function fetchNative(url:string, arg:{ let realBody:Uint8Array if(arg.method === 'GET' || arg.method === 'DELETE'){ - realBody = new Uint8Array(0) + realBody = undefined } - if(typeof arg.body === 'string'){ + else if(typeof arg.body === 'string'){ realBody = new TextEncoder().encode(arg.body) } else if(arg.body instanceof Uint8Array){ @@ -1990,18 +1988,15 @@ export async function fetchNative(url:string, arg:{ throw new Error(error) } - return { - body: readableStream, + return new Response(readableStream, { headers: new Headers(resHeaders), - status: status, - json: jsonizer(readableStream), - text: textizer(readableStream), - arrayBuffer: arrayBufferizer(readableStream) - } + status: status + }) } else if(throughProxy){ + const r = await fetch(hubURL + `/proxy2`, { body: realBody, headers: arg.useRisuTk ? { @@ -2018,14 +2013,10 @@ export async function fetchNative(url:string, arg:{ signal: arg.signal }) - return { - body: pipeFetchLog(fetchLogIndex, r.body), + return new Response(r.body, { headers: r.headers, - status: r.status, - json: jsonizer(r.body), - text: textizer(r.body), - arrayBuffer: arrayBufferizer(r.body) - } + status: r.status + }) } else{ return await fetch(url, { diff --git a/src/ts/process/stableDiff.ts b/src/ts/process/stableDiff.ts index 59ef8d14..724968ce 100644 --- a/src/ts/process/stableDiff.ts +++ b/src/ts/process/stableDiff.ts @@ -2,7 +2,7 @@ import { get } from "svelte/store" import { getDatabase, type character } from "../storage/database.svelte" import { requestChatData } from "./request" import { alertError } from "../alert" -import { globalFetch, readImage } from "../globalApi.svelte" +import { fetchNative, globalFetch, readImage } from "../globalApi.svelte" import { CharEmotion } from "../stores.svelte" import type { OpenAIChat } from "./index.svelte" import { processZip } from "./processzip" @@ -415,12 +415,14 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n } - if(db.sdProvider === 'comfy'){ + + if(db.sdProvider === 'comfy' || db.sdProvider === 'comfyui'){ + const legacy = db.sdProvider === 'comfy' // Legacy Comfy mode const {workflow, posNodeID, posInputName, negNodeID, negInputName} = db.comfyConfig const baseUrl = new URL(db.comfyUiUrl) const createUrl = (pathname: string, params: Record = {}) => { - const url = new URL(pathname, baseUrl) + const url = db.comfyUiUrl.endsWith('/api') ? new URL(`${db.comfyUiUrl}${pathname}`) : new URL(pathname, baseUrl) url.search = new URLSearchParams(params).toString() return url.toString() } @@ -437,8 +439,27 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n try { const prompt = JSON.parse(workflow) - prompt[posNodeID].inputs[posInputName] = genPrompt - prompt[negNodeID].inputs[negInputName] = neg + if(legacy){ + prompt[posNodeID].inputs[posInputName] = genPrompt + prompt[negNodeID].inputs[negInputName] = neg + } + else{ + //search all nodes for the prompt and negative prompt + const keys = Object.keys(prompt) + for(let i = 0; i < keys.length; i++){ + const node = prompt[keys[i]] + const inputKeys = Object.keys(node.inputs) + for(let j = 0; j < inputKeys.length; j++){ + let input = node.inputs[inputKeys[j]] + if(typeof input === 'string'){ + input = input.replaceAll('{{risu_prompt}}', genPrompt) + input = input.replaceAll('{{risu_neg}}', neg) + } + + node.inputs[inputKeys[j]] = input + } + } + } const { prompt_id: id } = await fetchWrapper(createUrl('/prompt'), { method: 'POST', @@ -451,9 +472,10 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n const startTime = Date.now() const timeout = db.comfyConfig.timeout * 1000 - while (!(item = (await (await fetch(createUrl('/history'), { + while (!(item = (await (await fetchNative(createUrl('/history'), { headers: { 'Content-Type': 'application/json' }, - method: 'GET'})).json())[id])) { + method: 'GET' + })).json())[id])) { console.log("Checking /history...") if (Date.now() - startTime >= timeout) { alertError("Error: Image generation took longer than expected."); @@ -463,13 +485,14 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n } // Check history until the generation is complete. const genImgInfo = Object.values(item.outputs).flatMap((output: any) => output.images)[0]; - const imgResponse = await fetch(createUrl('/view', { + const imgResponse = await fetchNative(createUrl('/view', { filename: genImgInfo.filename, subfolder: genImgInfo.subfolder, type: genImgInfo.type }), { headers: { 'Content-Type': 'application/json' }, - method: 'GET'}) + method: 'GET' + }) const img64 = Buffer.from(await imgResponse.arrayBuffer()).toString('base64') if(returnSdData === 'inlay'){ @@ -552,7 +575,6 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n if(db.falModel === 'fal-ai/flux-pro'){ delete body.enable_safety_checker } - console.log(body) const res = await globalFetch('https://fal.run/' + model, { headers: { @@ -563,8 +585,6 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n body: body }) - console.log(res) - if(!res.ok){ alertError(JSON.stringify(res.data)) return false