| 1642 | 1642 | $('#sd_model').val(extension_settings.sd.model).trigger('change'); |
| 1643 | 1643 | } |
| 1644 | 1644 | } |
| 1645 | + |
| 1645 | 1646 | async function generateStabilityImage(prompt, negativePrompt) { |
| 1646 | | - let endpoint; |
| 1647 | + const payload = { |
| 1648 | + prompt: prompt, |
| 1649 | + negative_prompt: negativePrompt, |
| 1650 | + width: extension_settings.sd.width, |
| 1651 | + height: extension_settings.sd.height, |
| 1652 | + seed: extension_settings.sd.seed >= 0 ? extension_settings.sd.seed : undefined, |
| 1653 | + style_preset: extension_settings.sd.stability_style_preset, |
| 1654 | + output_format: extension_settings.sd.stability_output_format, |
| 1655 | + }; |
| 1656 | + |
| 1657 | + const formData = new FormData(); |
| 1658 | + for (const [key, value] of Object.entries(payload)) { |
| 1659 | + if (value !== undefined) { |
| 1660 | + formData.append(key, String(value)); |
| 1661 | + } |
| 1662 | + } |
| 1663 | + |
| 1664 | + let apiUrl; |
| 1647 | 1665 | switch (extension_settings.sd.model) { |
| 1648 | 1666 | case 'stable-image-ultra': |
| 1649 | 1667 | endpointapiUrl = 'https://api.stability.ai/v2beta/stable-image/generate/ultra'; |
| 1650 | 1668 | break; |
| 1651 | 1669 | case 'stable-image-core': |
| 1652 | 1670 | endpointapiUrl = 'https://api.stability.ai/v2beta/stable-image/generate/core'; |
| 1653 | 1671 | break; |
| 1654 | 1672 | case 'stable-diffusion-3': |
| 1655 | 1673 | endpointapiUrl = 'https://api.stability.ai/v2beta/stable-image/generate/sd3'; |
| 1656 | 1674 | break; |
| 1657 | 1675 | default: |
| 1658 | 1676 | throw new Error('Invalid Stability AI model selected'); |
| 1659 | 1677 | } |
| 1660 | 1678 | |
| 1661 | | - const result = await fetch('/api/sd/stability/generate', { |
| 1679 | + try { |
| 1680 | + const response = await fetch(apiUrl, { |
| 1662 | 1681 | method: 'POST', |
| 1663 | | - headers: getRequestHeaders(), |
| 1682 | + headers: { |
| 1664 | | - body: JSON.stringify({ |
| 1683 | + 'Authorization': `Bearer ${extension_settings.sd.stability_key}`, |
| 1665 | | - key: extension_settings.sd.stability_key, |
| 1684 | + 'Accept': 'image/*', |
| 1666 | | - endpoint: endpoint, |
| 1685 | + }, |
| 1667 | 1686 | promptbody: promptformData, |
| 1668 | | - negative_prompt: negativePrompt, |
| 1669 | | - seed: extension_settings.sd.seed >= 0 ? extension_settings.sd.seed : undefined, |
| 1670 | | - style_preset: extension_settings.sd.stability_style_preset, |
| 1671 | | - aspect_ratio: extension_settings.sd.stability_aspect_ratio, |
| 1672 | | - }), |
| 1673 | 1687 | }); |
| 1674 | 1688 | |
| 1675 | 1689 | if (result!response.ok) { |
| 1676 | 1690 | const dataerrorText = await resultresponse.jsontext(); |
| 1677 | | - return { format: extension_settings.sd.stability_output_format, data: data.image }; |
| 1691 | + throw new Error(`HTTP ${response.status}: ${errorText}`); |
| 1678 | | - } else { |
| 1692 | + } |
| 1679 | | - const text = await result.text(); |
| 1693 | + |
| 1680 | | - throw new Error(text); |
| 1694 | + const arrayBuffer = await response.arrayBuffer(); |
| 1695 | + const base64Image = arrayBufferToBase64(arrayBuffer); |
| 1696 | + |
| 1697 | + return { |
| 1698 | + format: extension_settings.sd.stability_output_format, |
| 1699 | + data: base64Image, |
| 1700 | + }; |
| 1701 | + } catch (error) { |
| 1702 | + console.error('Error generating image with Stability AI:', error); |
| 1703 | + throw error; |
| 1704 | + } |
| 1705 | +} |
| 1706 | + |
| 1707 | +function arrayBufferToBase64(buffer) { |
| 1708 | + let binary = ''; |
| 1709 | + const bytes = new Uint8Array(buffer); |
| 1710 | + const len = bytes.byteLength; |
| 1711 | + for (let i = 0; i < len; i++) { |
| 1712 | + binary += String.fromCharCode(bytes[i]); |
| 1681 | 1713 | } |
| 1714 | + return btoa(binary); |
| 1682 | 1715 | } |
| 1683 | 1716 | |
| 1684 | 1717 | |