{debugBlur && blurError &&
@@ -275,6 +310,7 @@ export default function PhotoForm({
(loadingMessage && !formData[key] ? true : false) ||
isFieldGeneratingAi(key)}
type={type}
+ accessory={aiButtonForField(key)}
/>)}
,
- shouldAutoGenerateText?: boolean,
+ textFieldsToAutoGenerate?: AiAutoGeneratedField[],
} = {}) {
const [pending, setIsPending] = useState(false);
const [updatedTitle, setUpdatedTitle] = useState('');
const [hasTextContent, setHasTextContent] =
useState(photoForm ? formHasTextContent(photoForm) : false);
- const aiContent = useAiImageQueries(shouldAutoGenerateText);
+ const aiContent = useAiImageQueries(textFieldsToAutoGenerate);
return {
pending,
diff --git a/src/services/openai.ts b/src/services/openai.ts
index c71bc108..63502c8e 100644
--- a/src/services/openai.ts
+++ b/src/services/openai.ts
@@ -28,7 +28,13 @@ export const streamOpenAiImageQuery = async (
) => {
return safelyRunAdminServerAction(async () => {
if (ratelimit) {
- const { success } = await ratelimit.limit(RATE_LIMIT_IDENTIFIER);
+ let success = false;
+ try {
+ success = (await ratelimit.limit(RATE_LIMIT_IDENTIFIER)).success;
+ } catch (e: any) {
+ console.error('Failed to rate limit OpenAI', e);
+ throw new Error('Failed to rate limit OpenAI');
+ }
if (!success) {
console.error('OpenAI rate limit exceeded');
throw new Error('OpenAI rate limit exceeded');
diff --git a/src/site/SiteChecklistClient.tsx b/src/site/SiteChecklistClient.tsx
index 64a36404..5d4d52c7 100644
--- a/src/site/SiteChecklistClient.tsx
+++ b/src/site/SiteChecklistClient.tsx
@@ -43,9 +43,12 @@ export default function SiteChecklistClient({
isGeoPrivacyEnabled,
isPriorityOrderEnabled,
isAiTextGenerationEnabled,
+ aiTextAutoGeneratedFields,
+ hasAiTextAutoGeneratedFields,
isPublicApiEnabled,
isOgTextBottomAligned,
gridAspectRatio,
+ hasGridAspectRatio,
showRefreshButton,
secret,
}: ConfigChecklistStatus & {
@@ -299,6 +302,18 @@ export default function SiteChecklistClient({
{' '}
and connect to project in order to enable rate limiting
+
+ Comma-separated fields to auto-generate when
+ uploading photos. Accepted values: title, caption,
+ tags, description, all, or none (default is {'"all"'}).
+ {renderEnvVars(['AI_TEXT_AUTO_GENERATED_FIELDS'])}
+
Set environment variable to any number to enforce aspect ratio
{' '}
- (defaults to {'"1"'}, i.e., square)—set to {'"0"'} to disable:
+ (default is {'"1"'}, i.e., square)—set to {'"0"'} to disable:
{renderEnvVars(['NEXT_PUBLIC_GRID_ASPECT_RATIO'])}
Set environment variable to {'"BOTTOM"'} to
- keep OG image text bottom aligned (default is top):
+ keep OG image text bottom aligned (default is {'"top"'}):
{renderEnvVars(['NEXT_PUBLIC_OG_TEXT_ALIGNMENT'])}
diff --git a/src/site/config.ts b/src/site/config.ts
index 46101b31..4059cf05 100644
--- a/src/site/config.ts
+++ b/src/site/config.ts
@@ -1,3 +1,4 @@
+import { parseAiAutoGeneratedFieldsText } from '@/photo/ai';
import type { StorageType } from '@/services/storage';
import { makeUrlAbsolute, shortenUrl } from '@/utility/url';
@@ -94,6 +95,8 @@ export const BLUR_ENABLED = process.env.NEXT_PUBLIC_BLUR_DISABLED !== '1';
export const GEO_PRIVACY_ENABLED = process.env.NEXT_PUBLIC_GEO_PRIVACY === '1';
export const AI_TEXT_GENERATION_ENABLED =
Boolean(process.env.OPENAI_SECRET_KEY);
+export const AI_TEXT_AUTO_GENERATED_FIELDS = parseAiAutoGeneratedFieldsText(
+ process.env.AI_TEXT_AUTO_GENERATED_FIELDS);
export const PRIORITY_ORDER_ENABLED =
process.env.NEXT_PUBLIC_IGNORE_PRIORITY_ORDER !== '1';
export const PUBLIC_API_ENABLED = process.env.NEXT_PUBLIC_PUBLIC_API === '1';
@@ -135,10 +138,18 @@ export const CONFIG_CHECKLIST_STATUS = {
isBlurEnabled: BLUR_ENABLED,
isGeoPrivacyEnabled: GEO_PRIVACY_ENABLED,
isAiTextGenerationEnabled: AI_TEXT_GENERATION_ENABLED,
+ aiTextAutoGeneratedFields: process.env.AI_TEXT_AUTO_GENERATED_FIELDS
+ ? AI_TEXT_AUTO_GENERATED_FIELDS.length === 0
+ ? ['none']
+ : AI_TEXT_AUTO_GENERATED_FIELDS
+ : ['all'],
+ hasAiTextAutoGeneratedFields:
+ Boolean(process.env.AI_TEXT_AUTO_GENERATED_FIELDS),
isPriorityOrderEnabled: PRIORITY_ORDER_ENABLED,
isPublicApiEnabled: PUBLIC_API_ENABLED,
isOgTextBottomAligned: OG_TEXT_BOTTOM_ALIGNMENT,
gridAspectRatio: GRID_ASPECT_RATIO,
+ hasGridAspectRatio: Boolean(process.env.NEXT_PUBLIC_GRID_ASPECT_RATIO),
};
export type ConfigChecklistStatus = typeof CONFIG_CHECKLIST_STATUS;