imageGeneration.ts 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /**
  2. * Image generation helper using internal ImageService
  3. *
  4. * Example usage:
  5. * const { url: imageUrl } = await generateImage({
  6. * prompt: "A serene landscape with mountains"
  7. * });
  8. *
  9. * For editing:
  10. * const { url: imageUrl } = await generateImage({
  11. * prompt: "Add a rainbow to this landscape",
  12. * originalImages: [{
  13. * url: "https://example.com/original.jpg",
  14. * mimeType: "image/jpeg"
  15. * }]
  16. * });
  17. */
  18. import { storagePut } from "server/storage";
  19. import { ENV } from "./env";
  20. export type GenerateImageOptions = {
  21. prompt: string;
  22. originalImages?: Array<{
  23. url?: string;
  24. b64Json?: string;
  25. mimeType?: string;
  26. }>;
  27. };
  28. export type GenerateImageResponse = {
  29. url?: string;
  30. };
  31. export async function generateImage(
  32. options: GenerateImageOptions
  33. ): Promise<GenerateImageResponse> {
  34. if (!ENV.forgeApiUrl) {
  35. throw new Error("BUILT_IN_FORGE_API_URL is not configured");
  36. }
  37. if (!ENV.forgeApiKey) {
  38. throw new Error("BUILT_IN_FORGE_API_KEY is not configured");
  39. }
  40. // Build the full URL by appending the service path to the base URL
  41. const baseUrl = ENV.forgeApiUrl.endsWith("/")
  42. ? ENV.forgeApiUrl
  43. : `${ENV.forgeApiUrl}/`;
  44. const fullUrl = new URL(
  45. "images.v1.ImageService/GenerateImage",
  46. baseUrl
  47. ).toString();
  48. const response = await fetch(fullUrl, {
  49. method: "POST",
  50. headers: {
  51. accept: "application/json",
  52. "content-type": "application/json",
  53. "connect-protocol-version": "1",
  54. authorization: `Bearer ${ENV.forgeApiKey}`,
  55. },
  56. body: JSON.stringify({
  57. prompt: options.prompt,
  58. original_images: options.originalImages || [],
  59. }),
  60. });
  61. if (!response.ok) {
  62. const detail = await response.text().catch(() => "");
  63. throw new Error(
  64. `Image generation request failed (${response.status} ${response.statusText})${detail ? `: ${detail}` : ""}`
  65. );
  66. }
  67. const result = (await response.json()) as {
  68. image: {
  69. b64Json: string;
  70. mimeType: string;
  71. };
  72. };
  73. const base64Data = result.image.b64Json;
  74. const buffer = Buffer.from(base64Data, "base64");
  75. // Save to S3
  76. const { url } = await storagePut(
  77. `generated/${Date.now()}.png`,
  78. buffer,
  79. result.image.mimeType
  80. );
  81. return {
  82. url,
  83. };
  84. }