Integrate Cloudflare Workers AI text-to-image into SD extension (#5434)
* feat: integrate Cloudflare Workers AI for text-to-image generation in SD extension Agent-Logs-Url: https://github.com/SillyTavern/SillyTavern/sessions/efc79e4d-2119-4cdb-8afb-f26e318a38ef Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com> * fix: address review - use oai_settings for account ID, sort dropdown alphabetically, remove Account ID input, move debug log Agent-Logs-Url: https://github.com/SillyTavern/SillyTavern/sessions/bf0dda38-df40-44f4-8a63-0c952b48905d Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com> * Clean-up diffs * feat: add refresh models button to Workers AI section Agent-Logs-Url: https://github.com/SillyTavern/SillyTavern/sessions/ab6b5e7a-84d2-44d1-9f6e-3d330de04ef1 Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com> * fix: revert unrelated package-lock.json changes Agent-Logs-Url: https://github.com/SillyTavern/SillyTavern/sessions/ab6b5e7a-84d2-44d1-9f6e-3d330de04ef1 Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com> * Fix models loading * refactor: update model refresh button ID and add class to select elements * Send formData to BFL models * fix: adjust use FormData condition * fix: validate Workers AI account ID before proceeding with image model loading --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com>
This commit is contained in:
@@ -99,6 +99,7 @@ const sources = {
|
||||
google: 'google',
|
||||
zai: 'zai',
|
||||
openrouter: 'openrouter',
|
||||
workersai: 'workersai',
|
||||
};
|
||||
const comfyTypes = {
|
||||
standard: 'standard',
|
||||
@@ -1747,6 +1748,9 @@ async function loadSamplers() {
|
||||
case sources.openrouter:
|
||||
samplers = ['N/A'];
|
||||
break;
|
||||
case sources.workersai:
|
||||
samplers = ['N/A'];
|
||||
break;
|
||||
}
|
||||
|
||||
for (const sampler of samplers) {
|
||||
@@ -1997,6 +2001,9 @@ async function loadModels() {
|
||||
case sources.openrouter:
|
||||
models = await loadOpenRouterModels();
|
||||
break;
|
||||
case sources.workersai:
|
||||
models = await loadWorkersAIImageModels();
|
||||
break;
|
||||
}
|
||||
|
||||
if (extension_settings.sd.source === sources.electronhub) {
|
||||
@@ -2124,6 +2131,33 @@ async function loadXAIModels() {
|
||||
];
|
||||
}
|
||||
|
||||
async function loadWorkersAIImageModels() {
|
||||
$('#sd_cf_workers_key').toggleClass('success', !!secret_state[SECRET_KEYS.WORKERS_AI]);
|
||||
|
||||
if (!secret_state[SECRET_KEYS.WORKERS_AI]) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!oai_settings.workers_ai_account_id) {
|
||||
toastr.warning('Workers AI account ID is required. Save it in the "API Connections" panel.', 'Image Generation');
|
||||
return [];
|
||||
}
|
||||
|
||||
const result = await fetch('/api/sd/workersai/models', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({
|
||||
account_id: oai_settings.workers_ai_account_id,
|
||||
}),
|
||||
});
|
||||
|
||||
if (result.ok) {
|
||||
return await result.json();
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
async function loadPollinationsModels() {
|
||||
$('#sd_pollinations_key').toggleClass('success', !!secret_state[SECRET_KEYS.POLLINATIONS]);
|
||||
|
||||
@@ -2609,6 +2643,9 @@ async function loadSchedulers() {
|
||||
case sources.openrouter:
|
||||
schedulers = ['N/A'];
|
||||
break;
|
||||
case sources.workersai:
|
||||
schedulers = ['N/A'];
|
||||
break;
|
||||
}
|
||||
|
||||
for (const scheduler of schedulers) {
|
||||
@@ -2729,6 +2766,9 @@ async function loadVaes() {
|
||||
case sources.openrouter:
|
||||
vaes = ['N/A'];
|
||||
break;
|
||||
case sources.workersai:
|
||||
vaes = ['N/A'];
|
||||
break;
|
||||
}
|
||||
|
||||
for (const vae of vaes) {
|
||||
@@ -3432,6 +3472,9 @@ async function sendGenerationRequest(generationType, prompt, additionalNegativeP
|
||||
case sources.openrouter:
|
||||
result = await generateOpenRouterImage(prefixedPrompt, signal);
|
||||
break;
|
||||
case sources.workersai:
|
||||
result = await generateWorkersAIImage(prefixedPrompt, negativePrompt, signal);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!result.data) {
|
||||
@@ -4748,6 +4791,33 @@ async function generateOpenRouterImage(prompt, signal) {
|
||||
throw new Error(text);
|
||||
}
|
||||
|
||||
async function generateWorkersAIImage(prompt, negativePrompt, signal) {
|
||||
const result = await fetch('/api/sd/workersai/generate', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
signal: signal,
|
||||
body: JSON.stringify({
|
||||
prompt: prompt,
|
||||
negative_prompt: negativePrompt,
|
||||
model: extension_settings.sd.model,
|
||||
width: extension_settings.sd.width,
|
||||
height: extension_settings.sd.height,
|
||||
steps: extension_settings.sd.steps,
|
||||
scale: extension_settings.sd.scale,
|
||||
seed: extension_settings.sd.seed >= 0 ? extension_settings.sd.seed : undefined,
|
||||
account_id: oai_settings.workers_ai_account_id,
|
||||
}),
|
||||
});
|
||||
|
||||
if (result.ok) {
|
||||
const data = await result.json();
|
||||
return { format: data?.format, data: data?.image };
|
||||
} else {
|
||||
const text = await result.text();
|
||||
throw new Error(text);
|
||||
}
|
||||
}
|
||||
|
||||
async function onComfyOpenWorkflowEditorClick() {
|
||||
let workflow = await (await fetch('/api/sd/comfy/workflow', {
|
||||
method: 'POST',
|
||||
@@ -5120,6 +5190,8 @@ function isValidState() {
|
||||
return secret_state[SECRET_KEYS.ZAI];
|
||||
case sources.openrouter:
|
||||
return secret_state[SECRET_KEYS.OPENROUTER];
|
||||
case sources.workersai:
|
||||
return !!oai_settings.workers_ai_account_id && secret_state[SECRET_KEYS.WORKERS_AI];
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -5879,6 +5951,9 @@ export async function init() {
|
||||
extension_settings.sd.google_duration = Number($(this).val());
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$('#sd_models_refresh').on('click', async () => {
|
||||
await loadModels();
|
||||
});
|
||||
$('#sd_electronhub_quality').on('change', function () {
|
||||
extension_settings.sd.electronhub_quality = String($(this).val());
|
||||
saveSettingsDebounced();
|
||||
@@ -5922,6 +5997,7 @@ export async function init() {
|
||||
[sources.aimlapi]: SECRET_KEYS.AIMLAPI,
|
||||
[sources.comfy]: SECRET_KEYS.COMFY_RUNPOD,
|
||||
[sources.pollinations]: SECRET_KEYS.POLLINATIONS,
|
||||
[sources.workersai]: SECRET_KEYS.WORKERS_AI,
|
||||
};
|
||||
const shouldReloadOptions = Object.entries(keySourceMap).some(([k, v]) => k === extension_settings.sd.source && v === key);
|
||||
if (!shouldReloadOptions) {
|
||||
|
||||
Reference in New Issue
Block a user