sushilideaclan01's picture
remove the variations option
4a56a0b
import apiClient from "./client";
import type {
GenerateResponse,
BatchResponse,
MatrixGenerateResponse,
TestingMatrixResponse,
AnglesResponse,
ConceptsResponse,
CompatibleConceptsResponse,
AngleInfo,
ConceptInfo,
DbStatsResponse,
AdsListResponse,
AdCreativeDB,
HealthResponse,
ApiRootResponse,
ImageCorrectResponse,
ImageRegenerateResponse,
ModelsListResponse,
LoginResponse,
Niche,
CreativeAnalysisResponse,
CreativeModifyResponse,
FileUploadResponse,
ModificationMode,
CreativeAnalysisData,
MotivatorGenerateRequest,
MotivatorGenerateResponse,
} from "../../types/api";
// Health & Info
export const getHealth = async (): Promise<HealthResponse> => {
const response = await apiClient.get<HealthResponse>("/health");
return response.data;
};
export const getApiInfo = async (): Promise<ApiRootResponse> => {
const response = await apiClient.get<ApiRootResponse>("/");
return response.data;
};
// Generation Endpoints
export const generateAd = async (params: {
niche: Niche;
num_images: number;
image_model?: string | null;
target_audience?: string | null;
offer?: string | null;
use_trending?: boolean;
trending_context?: string | null;
}): Promise<GenerateResponse> => {
const response = await apiClient.post<GenerateResponse>("/generate", params);
return response.data;
};
export const generateBatch = async (params: {
niche: Niche;
count: number;
image_model?: string | null;
method?: "standard" | "matrix" | null;
target_audience?: string | null;
offer?: string | null;
}): Promise<BatchResponse> => {
const response = await apiClient.post<BatchResponse>("/generate/batch", params);
return response.data;
};
// Matrix Endpoints
export const generateMatrixAd = async (params: {
niche: Niche;
angle_key?: string | null;
concept_key?: string | null;
custom_angle?: string | null;
custom_concept?: string | null;
num_images: number;
image_model?: string | null;
target_audience?: string | null;
offer?: string | null;
core_motivator?: string;
}): Promise<MatrixGenerateResponse> => {
const response = await apiClient.post<MatrixGenerateResponse>("/matrix/generate", params);
return response.data;
};
export const generateMotivators = async (
params: MotivatorGenerateRequest
): Promise<MotivatorGenerateResponse> => {
const response = await apiClient.post<MotivatorGenerateResponse>(
"/api/motivator/generate",
{ ...params, count: params.count ?? 6 }
);
return response.data;
};
// Extensive Endpoints (async job pattern to avoid connection timeout on HF Spaces)
const EXTENSIVE_POLL_INTERVAL_MS = 5500;
const EXTENSIVE_POLL_TIMEOUT_MS = 20 * 60 * 1000; // 20 minutes
export const getExtensiveJobStatus = async (jobId: string): Promise<{ job_id: string; status: "running" | "completed" | "failed"; error?: string }> => {
const response = await apiClient.get(`/extensive/status/${jobId}`);
return response.data;
};
export const getExtensiveJobResult = async (jobId: string): Promise<BatchResponse> => {
const response = await apiClient.get<BatchResponse>(`/extensive/result/${jobId}`);
return response.data;
};
export const generateExtensiveAd = async (params: {
niche: Niche;
custom_niche?: string | null;
target_audience?: string | null;
offer?: string | null;
num_images: number;
image_model?: string | null;
num_strategies: number;
}): Promise<BatchResponse> => {
const requestParams = {
niche: params.niche,
num_images: params.num_images || 1,
num_strategies: params.num_strategies || 1,
...(params.custom_niche && { custom_niche: params.custom_niche }),
...(params.target_audience && { target_audience: params.target_audience }),
...(params.offer && { offer: params.offer }),
...(params.image_model && { image_model: params.image_model }),
};
const response = await apiClient.post<{ job_id: string; message?: string }>("/extensive/generate", requestParams);
const jobId = response.data?.job_id;
if (!jobId) {
throw new Error("Server did not return a job ID");
}
const deadline = Date.now() + EXTENSIVE_POLL_TIMEOUT_MS;
for (;;) {
const status = await getExtensiveJobStatus(jobId);
if (status.status === "completed") {
return getExtensiveJobResult(jobId);
}
if (status.status === "failed") {
throw new Error(status.error || "Extensive generation failed");
}
if (Date.now() >= deadline) {
throw new Error("Extensive generation timed out. Try fewer strategies or images.");
}
await new Promise((r) => setTimeout(r, EXTENSIVE_POLL_INTERVAL_MS));
}
};
export const generateTestingMatrix = async (params: {
niche: Niche;
angle_count: number;
concept_count: number;
strategy: "balanced" | "top_performers" | "diverse";
}): Promise<TestingMatrixResponse> => {
const response = await apiClient.post<TestingMatrixResponse>("/matrix/testing", params);
return response.data;
};
export const getAllAngles = async (): Promise<AnglesResponse> => {
const response = await apiClient.get<AnglesResponse>("/matrix/angles");
return response.data;
};
export const getAllConcepts = async (): Promise<ConceptsResponse> => {
const response = await apiClient.get<ConceptsResponse>("/matrix/concepts");
return response.data;
};
export const getAngle = async (angleKey: string): Promise<AngleInfo> => {
const response = await apiClient.get<AngleInfo>(`/matrix/angle/${angleKey}`);
return response.data;
};
export const getConcept = async (conceptKey: string): Promise<ConceptInfo> => {
const response = await apiClient.get<ConceptInfo>(`/matrix/concept/${conceptKey}`);
return response.data;
};
export const getCompatibleConcepts = async (angleKey: string): Promise<CompatibleConceptsResponse> => {
const response = await apiClient.get<CompatibleConceptsResponse>(`/matrix/compatible/${angleKey}`);
return response.data;
};
// Refine custom angle or concept using AI
export const refineCustomAngleOrConcept = async (params: {
text: string;
type: "angle" | "concept";
niche: Niche;
goal?: string;
}): Promise<{ status: string; type: "angle" | "concept"; refined?: any; error?: string }> => {
const response = await apiClient.post("/matrix/refine-custom", params);
return response.data;
};
// Database Endpoints
export const getDbStats = async (): Promise<DbStatsResponse> => {
const response = await apiClient.get<DbStatsResponse>("/db/stats");
return response.data;
};
export const listAds = async (params?: {
niche?: string | null;
generation_method?: string | null;
limit?: number;
offset?: number;
}): Promise<AdsListResponse> => {
const response = await apiClient.get<AdsListResponse>("/db/ads", { params });
return response.data;
};
export const getAd = async (adId: string): Promise<AdCreativeDB> => {
const response = await apiClient.get<AdCreativeDB>(`/db/ad/${adId}`);
return response.data;
};
export const deleteAd = async (adId: string): Promise<{ success: boolean; deleted_id: string }> => {
const response = await apiClient.delete<{ success: boolean; deleted_id: string }>(`/db/ad/${adId}`);
return response.data;
};
// Strategies
export const getStrategies = async (niche: Niche): Promise<any> => {
const response = await apiClient.get(`/strategies/${niche}`);
return response.data;
};
// Image Correction Endpoints
export const correctImage = async (params: {
image_id: string;
image_url?: string;
user_instructions?: string;
auto_analyze?: boolean;
}): Promise<ImageCorrectResponse> => {
const response = await apiClient.post<ImageCorrectResponse>("/api/correct", params);
return response.data;
};
// Image Regeneration Endpoints
export const regenerateImage = async (params: {
image_id: string;
image_model?: string | null;
preview_only?: boolean;
}): Promise<ImageRegenerateResponse> => {
const response = await apiClient.post<ImageRegenerateResponse>("/api/regenerate", {
...params,
preview_only: params.preview_only ?? true, // Default to preview mode
});
return response.data;
};
// Confirm Image Selection after Regeneration
export const confirmImageSelection = async (params: {
image_id: string;
selection: "new" | "original";
new_image_url?: string | null;
new_r2_url?: string | null;
new_filename?: string | null;
new_model?: string | null;
new_seed?: number | null;
}): Promise<{ status: string; message: string; selection: string; new_image_url?: string }> => {
const response = await apiClient.post("/api/regenerate/confirm", params);
return response.data;
};
// Get Available Image Models
export const getImageModels = async (): Promise<ModelsListResponse> => {
const response = await apiClient.get<ModelsListResponse>("/api/models");
return response.data;
};
// Auth Endpoints
export const login = async (username: string, password: string): Promise<LoginResponse> => {
const response = await apiClient.post<LoginResponse>("/auth/login", {
username,
password,
});
return response.data;
};
// Edit Ad Copy Endpoint
export const editAdCopy = async (params: {
ad_id: string;
field: "title" | "headline" | "primary_text" | "description" | "body_story" | "cta";
value: string;
mode: "manual" | "ai";
user_suggestion?: string;
}): Promise<{ edited_value: string; success: boolean }> => {
const response = await apiClient.post<{ edited_value: string; success: boolean }>("/db/ad/edit", params);
return response.data;
};
// Download Image Endpoint (proxy to avoid CORS)
export const downloadImageProxy = async (params: {
image_url?: string;
image_id?: string;
}): Promise<Blob> => {
const response = await apiClient.get("/api/download-image", {
params,
responseType: "blob",
});
return response.data as Blob;
};
// Creative Modifier Endpoints
// Upload a creative image
export const uploadCreative = async (file: File): Promise<FileUploadResponse> => {
const formData = new FormData();
formData.append("file", file);
const response = await apiClient.post<FileUploadResponse>(
"/api/creative/upload",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
},
}
);
return response.data;
};
// Analyze a creative image (via URL)
export const analyzeCreativeByUrl = async (params: {
image_url: string;
}): Promise<CreativeAnalysisResponse> => {
const response = await apiClient.post<CreativeAnalysisResponse>(
"/api/creative/analyze",
params
);
return response.data;
};
// Analyze a creative image (via file upload)
export const analyzeCreativeByFile = async (
file: File
): Promise<CreativeAnalysisResponse> => {
const formData = new FormData();
formData.append("file", file);
const response = await apiClient.post<CreativeAnalysisResponse>(
"/api/creative/analyze/upload",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
},
}
);
return response.data;
};
// Modify a creative with new angle/concept
export const modifyCreative = async (params: {
image_url: string;
analysis?: CreativeAnalysisData | null;
angle?: string;
concept?: string;
mode: ModificationMode;
image_model?: string | null;
user_prompt?: string;
}): Promise<CreativeModifyResponse> => {
const response = await apiClient.post<CreativeModifyResponse>(
"/api/creative/modify",
params
);
return response.data;
};
// Bulk Export Endpoint
export const exportBulkAds = async (adIds: string[]): Promise<Blob> => {
const response = await apiClient.post(
"/api/export/bulk",
{ ad_ids: adIds },
{ responseType: "blob" }
);
return response.data as Blob;
};