diff --git a/src/lib/Setting/Pages/OtherBotSettings.svelte b/src/lib/Setting/Pages/OtherBotSettings.svelte
index 5cc25c17..6a9154b3 100644
--- a/src/lib/Setting/Pages/OtherBotSettings.svelte
+++ b/src/lib/Setting/Pages/OtherBotSettings.svelte
@@ -46,6 +46,7 @@
Novel AI
Dall-E
Stability API
+ ComfyUI
{#if $DataBase.sdProvider === 'webui'}
@@ -243,6 +244,28 @@
{/if}
{/if}
+
+ {#if $DataBase.sdProvider === 'comfy'}
+ The first image generated by the prompt will be selected.
+ {#if !isTauri}
+ "Please run comfyUI with --enable-cors-header."
+ {/if}
+ ComfyUI {language.providerURL}
+
+ Workflow
+
+
+ Positive Text Node: ID
+
+ Positive Text Node: Input Field Name
+
+ Negative Text Node: ID
+
+ Positive Text Node: Input Field Name
+
+ Timeout (sec)
+
+ {/if}
@@ -370,4 +393,4 @@
{/if}
-
\ No newline at end of file
+
diff --git a/src/ts/process/stableDiff.ts b/src/ts/process/stableDiff.ts
index aadd9705..fea4138c 100644
--- a/src/ts/process/stableDiff.ts
+++ b/src/ts/process/stableDiff.ts
@@ -413,6 +413,80 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n
return returnSdData
+ }
+ if(db.sdProvider === 'comfy'){
+ 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)
+ url.search = new URLSearchParams(params).toString()
+ return url.toString()
+ }
+
+ const fetchWrapper = async (url: string, options = {}) => {
+ console.log(url)
+ const response = await globalFetch(url, options)
+ if (!response.ok) {
+ console.log(JSON.stringify(response.data))
+ throw new Error(JSON.stringify(response.data))
+ }
+ return response.data
+ }
+
+ try {
+ const prompt = JSON.parse(workflow)
+ prompt[posNodeID].inputs[posInputName] = genPrompt
+ prompt[negNodeID].inputs[negInputName] = neg
+
+ const { prompt_id: id } = await fetchWrapper(createUrl('/prompt'), {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: { 'prompt': prompt }
+ })
+ console.log(`prompt id: ${id}`)
+
+ let item
+
+ const startTime = Date.now()
+ const timeout = db.comfyConfig.timeout * 1000
+ while (!(item = (await (await fetch(createUrl('/history'), {
+ headers: { 'Content-Type': 'application/json' },
+ method: 'GET'})).json())[id])) {
+ console.log("Checking /history...")
+ if (Date.now() - startTime >= timeout) {
+ alertError("Error: Image generation took longer than expected.");
+ return false
+ }
+ await new Promise(r => setTimeout(r, 1000))
+ } // 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', {
+ filename: genImgInfo.filename,
+ subfolder: genImgInfo.subfolder,
+ type: genImgInfo.type
+ }), {
+ headers: { 'Content-Type': 'application/json' },
+ method: 'GET'})
+ const img64 = Buffer.from(await imgResponse.arrayBuffer()).toString('base64')
+
+ if(returnSdData === 'inlay'){
+ return `data:image/png;base64,${img64}`
+ }
+ else {
+ let charemotions = get(CharEmotion)
+ const img = `data:image/png;base64,${img64}`
+ const emos:[string, string,number][] = [[img, img, Date.now()]]
+ charemotions[currentChar.chaId] = emos
+ CharEmotion.set(charemotions)
+ }
+
+ return returnSdData
+ } catch (error) {
+ alertError(error)
+ return false
+ }
}
return ''
-}
\ No newline at end of file
+}
diff --git a/src/ts/storage/database.ts b/src/ts/storage/database.ts
index 73e2d7ef..070812ee 100644
--- a/src/ts/storage/database.ts
+++ b/src/ts/storage/database.ts
@@ -419,6 +419,16 @@ export function setDatabase(data:Database){
data.stabilityModel ??= 'sd3-large'
data.stabllityStyle ??= ''
data.legacyTranslation ??= false
+ data.comfyUiUrl ??= 'http://localhost:8188'
+ data.comfyConfig ??= {
+ workflow: '',
+ posNodeID: '',
+ posInputName: 'text',
+ negNodeID: '',
+ negInputName: 'text',
+ timeout: 30
+ }
+
changeLanguage(data.language)
DataBase.set(data)
}
@@ -695,6 +705,8 @@ export interface Database{
stabilityKey: string
stabllityStyle: string
legacyTranslation: boolean
+ comfyConfig: ComfyConfig
+ comfyUiUrl: string
}
export interface customscript{
@@ -967,6 +979,16 @@ interface NAIImgConfig{
InfoExtracted:number,
RefStrength:number
}
+
+interface ComfyConfig{
+ workflow:string,
+ posNodeID: string,
+ posInputName:string,
+ negNodeID: string,
+ negInputName:string,
+ timeout: number
+}
+
export type FormatingOrderItem = 'main'|'jailbreak'|'chats'|'lorebook'|'globalNote'|'authorNote'|'lastChat'|'description'|'postEverything'|'personaPrompt'
export interface Chat{
@@ -1486,4 +1508,4 @@ export async function importPreset(f:{
pre.name ??= "Imported"
db.botPresets.push(pre)
setDatabase(db)
-}
\ No newline at end of file
+}