feat(sd): Add Z.AI GLM-Image model support (#5012) * feat(sd): Add Z.AI GLM-Image model support Add the new GLM-Image model to the Z.AI image generation source: - Add 'glm-image' to the model dropdown with friendly display name - Handle GLM-Image's requirement for dimensions in multiples of 32 (vs CogView's multiples of 16) - Show quality dropdown for GLM-Image (supports standard/hd) The GLM-Image model uses the same API endpoint as CogView but has different dimension constraints. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(sd): Enhance Z.AI GLM-Image support - Use regex for GLM-Image model detection (futureproofing) - Skip 2^21 pixel limit for GLM-Image (CogView-specific) - Add Z.AI recommended resolutions (1280x1280, 1568x1056, etc.) - Add "Use Coding API" toggle for GLM Coding Plan users - Add better error logging for image fetch debugging Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(sd): Address PR review feedback for Z.AI GLM-Image - Remove custom zai_coding_api setting, use existing oai_settings.zai_endpoint - Always use Common API for image generation (avoids rate limits) - Keep ZAI_ENDPOINT import for consistency with other extensions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: always use Common API for Z.AI image generation Removes conditional endpoint selection since we decided to always use Common API for image generation (Coding API has stricter rate limits). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * It's not only cogview anymore * Remove unused param from request payload * Remove redundant debug logs * Loosen the check on image quality data attribute * Bring back coding API notice --------- Co-authored-by: mschienbein <mschienbein@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>

bce1372ed4551391d7b5c0e0f418149acc413246

Mooki <m@schienbein.dev>

Signed
3 files changed, +35 -14Ignore whitespace
public/scripts/extensions/stable-diffusion/index.js+31 -11
@@ -979,6 +979,13 @@ const resolutionOptions = {
979979 sd_res_1024x1536: { width: 1024, height: 1536, name: '1024x1536 (2:3, ChatGPT)' },
980980 sd_res_1024x1792: { width: 1024, height: 1792, name: '1024x1792 (4:7, DALL-E)' },
981981 sd_res_1792x1024: { width: 1792, height: 1024, name: '1792x1024 (7:4, DALL-E)' },
982+ sd_res_1280x1280: { width: 1280, height: 1280, name: '1280x1280 (1:1, Z.AI)' },
983+ sd_res_1568x1056: { width: 1568, height: 1056, name: '1568x1056 (3:2, Z.AI)' },
984+ sd_res_1056x1568: { width: 1056, height: 1568, name: '1056x1568 (2:3, Z.AI)' },
985+ sd_res_1472x1088: { width: 1472, height: 1088, name: '1472x1088 (4:3, Z.AI)' },
986+ sd_res_1088x1472: { width: 1088, height: 1472, name: '1088x1472 (3:4, Z.AI)' },
987+ sd_res_1728x960: { width: 1728, height: 960, name: '1728x960 (16:9, Z.AI)' },
988+ sd_res_960x1728: { width: 960, height: 1728, name: '960x1728 (9:16, Z.AI)' },
982989};
983990
984991function onResolutionChange() {
@@ -2297,7 +2304,12 @@ async function loadGoogleModels() {
22972304}
22982305
22992306async function loadZaiModels() {
2300- return ['cogview-4-250304', 'cogvideox-3', 'viduq1-text'].map(name => ({ value: name, text: name }));
2307+ return [
2308+ { value: 'glm-image', text: 'GLM-Image' },
2309+ { value: 'cogview-4-250304', text: 'CogView-4' },
2310+ { value: 'cogvideox-3', text: 'CogVideoX-3' },
2311+ { value: 'viduq1-text', text: 'Viduq1-Text' },
2312+ ];
23012313}
23022314
23032315async function loadOpenRouterModels() {
@@ -4268,6 +4280,7 @@ async function generateGoogleImage(prompt, negativePrompt, signal) {
42684280 * @returns {Promise<{format: string, data: string}>} A promise that resolves when the image generation and processing are complete.
42694281 */
42704282async function generateZaiImage(prompt, signal) {
4283+ // Video generation models (CogVideoX, Viduq1)
42714284 if (/(cogvideox|vidu)/.test(extension_settings.sd.model)) {
42724285 const videoParams = {};
42734286 if (/cogvideox/.test(extension_settings.sd.model)) {
@@ -4298,16 +4311,23 @@ async function generateZaiImage(prompt, signal) {
42984311 const text = await videoResult.text();
42994312 throw new Error(text);
43004313 } else {
4301- // Round width and height to nearest multiple of 16, and clamp to 512-2048 range
4314+ // Image generation models (GLM-Image, CogView)
4302- let width = clamp(Math.round(extension_settings.sd.width / 16) * 16, 512, 2048);
4315+ // GLM-Image requires multiples of 32, CogView requires multiples of 16
4303- let height = clamp(Math.round(extension_settings.sd.height / 16) * 16, 512, 2048);
4316+ const isGlmImage = /glm-image/.test(extension_settings.sd.model);
4304-
4317+ const multiple = isGlmImage ? 32 : 16;
4305- // Make sure the pixel count does not exceed 2^21px
4318+
4306- while ((width * height) > Math.pow(2, 21)) {
4319+ // Round width and height to nearest multiple and clamp to 512-2048 range
4307- if (width >= height) {
4320+ let width = clamp(Math.round(extension_settings.sd.width / multiple) * multiple, 512, 2048);
4308- width -= 16;
4321+ let height = clamp(Math.round(extension_settings.sd.height / multiple) * multiple, 512, 2048);
4309- } else {
4322+
4310- height -= 16;
4323+ // CogView has a 2^21px pixel count limit, GLM-Image does not
4324+ if (!isGlmImage) {
4325+ while ((width * height) > Math.pow(2, 21)) {
4326+ if (width >= height) {
4327+ width -= multiple;
4328+ } else {
4329+ height -= multiple;
4330+ }
43114331 }
43124332 }
43134333
public/scripts/extensions/stable-diffusion/settings.html+2 -2
@@ -58,7 +58,7 @@
5858 <option value="horde">Stable Horde</option>
5959 <option value="togetherai">TogetherAI</option>
6060 <option value="xai">xAI (Grok)</option>
6161 <option value="zai">Z.AI (CogView)</option>
6262 </select>
6363 <div data-sd-source="auto">
6464 <label for="sd_auto_url">SD Web UI URL</label>
@@ -187,7 +187,7 @@
187187 <option value="high" data-i18n="High">High</option>
188188 </select>
189189 </div>
190190 <div data-sd-model="dall-e-3,cogview-4,glm-image,cogvideox" class="flex1">
191191 <label for="sd_openai_quality" data-i18n="Image Quality">Image Quality</label>
192192 <select id="sd_openai_quality">
193193 <option value="standard" data-i18n="Standard">Standard</option>
src/endpoints/stable-diffusion.js+2 -1
@@ -1758,6 +1758,7 @@ zai.post('/generate', async (request, response) => {
17581758
17591759 console.debug('Z.AI image request:', request.body);
17601760
1761+ // Always use Common API for image generation (Coding API has stricter rate limits)
17611762 const generateResponse = await fetch('https://api.z.ai/api/paas/v4/images/generations', {
17621763 method: 'POST',
17631764 headers: {
@@ -1790,7 +1791,7 @@ zai.post('/generate', async (request, response) => {
17901791
17911792 const imageResponse = await fetch(url);
17921793 if (!imageResponse.ok) {
17931794 console.warn('Z.AI image fetch returned an error. Status:', imageResponse.status, imageResponse.statusText);
17941795 return response.sendStatus(500);
17951796 }
17961797