Refactor getFastAPIUrl function to prioritize query parameter retrieval after environment checks

This commit is contained in:
sudipnext 2026-04-09 21:50:02 +05:45
parent 0f460d74f5
commit 8f776d9dee
7 changed files with 55 additions and 20 deletions

View file

@ -129,6 +129,7 @@ async function startServers(fastApiPort: number, nextjsPort: number) {
DALL_E_3_QUALITY: process.env.DALL_E_3_QUALITY,
GPT_IMAGE_1_5_QUALITY: process.env.GPT_IMAGE_1_5_QUALITY,
APP_DATA_DIRECTORY: appDataDir,
FASTAPI_PUBLIC_URL: process.env.NEXT_PUBLIC_FAST_API,
TEMP_DIRECTORY: tempDir,
USER_CONFIG_PATH: userConfigPath,
MIGRATE_DATABASE_ON_STARTUP: "True",

View file

@ -28,11 +28,12 @@ interface FastApiEnv {
DALL_E_3_QUALITY?: string,
GPT_IMAGE_1_5_QUALITY?: string,
APP_DATA_DIRECTORY?: string,
FASTAPI_PUBLIC_URL?: string,
TEMP_DIRECTORY?: string,
USER_CONFIG_PATH?: string,
MIGRATE_DATABASE_ON_STARTUP?: string,
/** Absolute path to the resolved LibreOffice executable discovered at startup. */
SOFFICE_PATH?: string,
/** Absolute path to the resolved LibreOffice executable discovered at startup. */
SOFFICE_PATH?: string,
/** Absolute path to the ImageMagick binary resolved at startup by imagemagick-check.ts. */
IMAGEMAGICK_BINARY?: string,
/** Absolute path to the bundled LiteParse runner script. */
@ -90,4 +91,4 @@ interface UserConfig {
interface IPCStatus {
success: boolean,
message?: string,
}
}

View file

@ -34,6 +34,7 @@ export function setupEnv(fastApiPort: number, nextjsPort: number) {
const { app } = require('electron');
process.env.APP_VERSION = app.getVersion();
process.env.NEXT_PUBLIC_FAST_API = `${localhost}:${fastApiPort}`;
process.env.FASTAPI_PUBLIC_URL = process.env.NEXT_PUBLIC_FAST_API;
process.env.TEMP_DIRECTORY = tempDir;
process.env.NEXT_PUBLIC_USER_CONFIG_PATH = userConfigPath;
process.env.NEXT_PUBLIC_URL = `${localhost}:${nextjsPort}`;

View file

@ -15,8 +15,8 @@ if __name__ == "__main__":
reload = args.reload == "true"
host = "127.0.0.1"
# Provide a predictable public URL for services that need absolute asset links.
os.environ.setdefault("FASTAPI_PUBLIC_URL", f"http://{host}:{args.port}")
# Always bind absolute asset generation to the active runtime port.
os.environ["FASTAPI_PUBLIC_URL"] = f"http://{host}:{args.port}"
uvicorn.run(
"api.main:app",

View file

@ -9,12 +9,6 @@ from utils.get_dynamic_models import get_presentation_outline_model_with_n_slide
from utils.llm_client_error_handler import handle_llm_client_exceptions
from utils.llm_provider import get_model
"""
Previously there was a dedicated search-query generation prompt constant.
Removed in favor of embedding short, actionable web-search steps into the
system prompt when web grounding is requested.
"""
def get_system_prompt(
tone: Optional[str] = None,
@ -49,7 +43,7 @@ def get_system_prompt(
slide_outline_structure = (
"Each slide content:\n"
" - Must have a ## title.\n"
" - Must have content either in multiple bullet points or table or both.\n"
# " - Must have content either in multiple bullet points or table or both.\n"
" - Must be in Markdown format.\n"
" - Don't use **bold** and __italic__ text."
" - First slide title must be the same as the presentation title."
@ -62,7 +56,7 @@ def get_system_prompt(
"Each slide content should contain the content for that slide.\n"
f"{verbosity_instruction}\n"
"Minimize repetitive content and make sure to use different words and phrases for different slides.\n"
"Include numerical data or tables if required or asked by the user.\n"
"Include numerical data, tables or code if required or asked by the user.\n"
"If 'auto-detect' is used, figure it out from the content/context.\n"
f"{title_slide_instruction}\n"
f"{toc_block}"

View file

@ -5,6 +5,7 @@ import * as z from "zod";
import * as Recharts from "recharts";
import * as Babel from "@babel/standalone";
import * as d3 from "d3";
import { resolveBackendAssetUrl } from "@/utils/api";
// import * as d3Cloud from "d3-cloud";
export interface CompiledLayout {
@ -17,6 +18,37 @@ export interface CompiledLayout {
schemaJSON: any;
}
function isLikelyBackendAssetPath(value: string): boolean {
if (!value) return false;
if (value.startsWith("file://")) return true;
if (value.startsWith("/app_data/") || value.startsWith("/static/")) return true;
if (value.startsWith("app_data/") || value.startsWith("static/")) return true;
return value.includes("/app_data/") || value.includes("/static/");
}
function normalizeLayoutAssetUrls<T>(value: T): T {
if (typeof value === "string") {
const trimmedValue = value.trim();
if (!isLikelyBackendAssetPath(trimmedValue)) {
return value;
}
return resolveBackendAssetUrl(trimmedValue) as T;
}
if (Array.isArray(value)) {
return value.map((item) => normalizeLayoutAssetUrls(item)) as T;
}
if (value && typeof value === "object") {
const normalizedEntries = Object.entries(value as Record<string, unknown>).map(
([key, item]) => [key, normalizeLayoutAssetUrls(item)]
);
return Object.fromEntries(normalizedEntries) as T;
}
return value;
}
/**
* Compiles a layout code string into a usable React component
*/
@ -101,11 +133,17 @@ export function compileCustomLayout(layoutCode: string): CompiledLayout | null {
return null;
}
const wrappedComponent: React.ComponentType<{ data: any }> = ({ data, ...props }) => {
const normalizedData = React.useMemo(() => normalizeLayoutAssetUrls(data), [data]);
return React.createElement(result.component, { ...(props as any), data: normalizedData });
};
wrappedComponent.displayName = `CompiledTemplateLayout(${result.layoutName || result.layoutId || "Custom"})`;
// Parse schema to get sample data
let sampleData: Record<string, any> = {};
if (result.Schema) {
try {
sampleData = result.Schema.parse({});
sampleData = normalizeLayoutAssetUrls(result.Schema.parse({}));
} catch (e) {
console.warn("Could not parse schema defaults:", e);
}
@ -113,7 +151,7 @@ export function compileCustomLayout(layoutCode: string): CompiledLayout | null {
const schemaJSON = z.toJSONSchema(result.Schema);
return {
component: result.component,
component: wrappedComponent,
layoutId: result.layoutId,
layoutName: result.layoutName,
layoutDescription: result.layoutDescription,

View file

@ -1,10 +1,5 @@
// Utility to get the FastAPI base URL
export function getFastAPIUrl(): string {
const queryFastApiUrl = getFastApiUrlFromQuery();
if (queryFastApiUrl) {
return queryFastApiUrl;
}
// Prefer Electron-preload env when available
if (typeof window !== "undefined" && (window as any).env?.NEXT_PUBLIC_FAST_API) {
return (window as any).env.NEXT_PUBLIC_FAST_API;
@ -15,6 +10,11 @@ export function getFastAPIUrl(): string {
return process.env.NEXT_PUBLIC_FAST_API;
}
const queryFastApiUrl = getFastApiUrlFromQuery();
if (queryFastApiUrl) {
return queryFastApiUrl;
}
// Safe Electron fallback to local FastAPI
return "http://127.0.0.1:8000";
}