Skip to content

Commit 32bd769

Browse files
🎨 Auto format and update with pre-commit
1 parent 776b86e commit 32bd769

File tree

7 files changed

+69
-18
lines changed

7 files changed

+69
-18
lines changed

backend/app/core/logging.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ def setup_logging() -> None:
1313
"disable_existing_loggers": False,
1414
"formatters": {
1515
"standard": {
16-
"format": (
17-
"%(asctime)s | %(levelname)s | %(name)s | %(message)s"
18-
)
16+
"format": ("%(asctime)s | %(levelname)s | %(name)s | %(message)s")
1917
}
2018
},
2119
"handlers": {
@@ -33,4 +31,3 @@ def setup_logging() -> None:
3331
},
3432
}
3533
)
36-

backend/app/services/template_ai_service.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,15 @@ def _extract_text_from_gemini_response(payload: dict[str, Any]) -> str:
8484
return text
8585

8686

87-
def _gemini_generate_json(*, system_prompt: str, user_payload: dict[str, Any]) -> dict[str, Any]:
87+
def _gemini_generate_json(
88+
*, system_prompt: str, user_payload: dict[str, Any]
89+
) -> dict[str, Any]:
8890
api_key = settings.GEMINI_API_KEY
8991
if not api_key:
9092
raise GeminiResponseError("GEMINI_API_KEY is not configured")
9193

9294
model = settings.GEMINI_MODEL.strip() or "gemini-2.5-flash-lite"
93-
url = (
94-
f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent"
95-
)
95+
url = f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent"
9696

9797
request_body = {
9898
"systemInstruction": {"parts": [{"text": system_prompt}]},
@@ -266,7 +266,9 @@ def _normalize_extract_output(
266266
if isinstance(raw_conf_value, (int, float)):
267267
confidence[variable] = max(0.0, min(1.0, float(raw_conf_value)))
268268
else:
269-
confidence[variable] = 0.0 if is_missing_value(coerced, config.type) else 0.5
269+
confidence[variable] = (
270+
0.0 if is_missing_value(coerced, config.type) else 0.5
271+
)
270272

271273
raw_note = raw_notes.get(variable)
272274
if isinstance(raw_note, str) and raw_note.strip():
@@ -364,7 +366,9 @@ def extract_variables(
364366
raw = _gemini_generate_json(
365367
system_prompt=EXTRACT_SYSTEM_PROMPT, user_payload=payload
366368
)
367-
normalized = _normalize_extract_output(raw=raw, variables_schema=variables_schema)
369+
normalized = _normalize_extract_output(
370+
raw=raw, variables_schema=variables_schema
371+
)
368372
logger.info(
369373
"AI extract provider=gemini model=%s variables=%s missing_required=%s",
370374
settings.GEMINI_MODEL,
@@ -393,7 +397,9 @@ def _render_with_gemini(
393397
"values": values,
394398
"style": style or {},
395399
}
396-
raw = _gemini_generate_json(system_prompt=RENDER_SYSTEM_PROMPT, user_payload=payload)
400+
raw = _gemini_generate_json(
401+
system_prompt=RENDER_SYSTEM_PROMPT, user_payload=payload
402+
)
397403
output_text = raw.get("output_text")
398404
if not isinstance(output_text, str) or not output_text.strip():
399405
raise GeminiResponseError("Gemini render response missing output_text")

frontend/src/client/schemas.gen.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,19 @@ export const GenerationsPublicSchema = {
289289
title: 'GenerationsPublic'
290290
} as const;
291291

292+
export const GoogleLoginRequestSchema = {
293+
properties: {
294+
id_token: {
295+
type: 'string',
296+
minLength: 1,
297+
title: 'Id Token'
298+
}
299+
},
300+
type: 'object',
301+
required: ['id_token'],
302+
title: 'GoogleLoginRequest'
303+
} as const;
304+
292305
export const HTTPValidationErrorSchema = {
293306
properties: {
294307
detail: {

frontend/src/client/sdk.gen.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import type { CancelablePromise } from './core/CancelablePromise';
44
import { OpenAPI } from './core/OpenAPI';
55
import { request as __request } from './core/request';
6-
import type { GenerateExtractVariablesData, GenerateExtractVariablesResponse, GenerateRenderTemplateData, GenerateRenderTemplateResponse, GenerationsReadGenerationsData, GenerationsReadGenerationsResponse, GenerationsCreateGenerationData, GenerationsCreateGenerationResponse, GenerationsReadGenerationData, GenerationsReadGenerationResponse, GenerationsUpdateGenerationData, GenerationsUpdateGenerationResponse, ItemsReadItemsData, ItemsReadItemsResponse, ItemsCreateItemData, ItemsCreateItemResponse, ItemsReadItemData, ItemsReadItemResponse, ItemsUpdateItemData, ItemsUpdateItemResponse, ItemsDeleteItemData, ItemsDeleteItemResponse, LoginLoginAccessTokenData, LoginLoginAccessTokenResponse, LoginTestTokenResponse, LoginRecoverPasswordData, LoginRecoverPasswordResponse, LoginResetPasswordData, LoginResetPasswordResponse, LoginRecoverPasswordHtmlContentData, LoginRecoverPasswordHtmlContentResponse, PrivateCreateUserData, PrivateCreateUserResponse, TemplatesReadTemplatesData, TemplatesReadTemplatesResponse, TemplatesCreateTemplateData, TemplatesCreateTemplateResponse, TemplatesReadTemplateData, TemplatesReadTemplateResponse, TemplatesUpdateTemplateData, TemplatesUpdateTemplateResponse, TemplatesReadTemplateVersionsData, TemplatesReadTemplateVersionsResponse, TemplatesCreateTemplateVersionData, TemplatesCreateTemplateVersionResponse, UsersReadUsersData, UsersReadUsersResponse, UsersCreateUserData, UsersCreateUserResponse, UsersReadUserMeResponse, UsersDeleteUserMeResponse, UsersUpdateUserMeData, UsersUpdateUserMeResponse, UsersUpdatePasswordMeData, UsersUpdatePasswordMeResponse, UsersRegisterUserData, UsersRegisterUserResponse, UsersReadUserByIdData, UsersReadUserByIdResponse, UsersUpdateUserData, UsersUpdateUserResponse, UsersDeleteUserData, UsersDeleteUserResponse, UtilsTestEmailData, UtilsTestEmailResponse, UtilsHealthCheckResponse } from './types.gen';
6+
import type { GenerateExtractVariablesData, GenerateExtractVariablesResponse, GenerateRenderTemplateData, GenerateRenderTemplateResponse, GenerationsReadGenerationsData, GenerationsReadGenerationsResponse, GenerationsCreateGenerationData, GenerationsCreateGenerationResponse, GenerationsReadGenerationData, GenerationsReadGenerationResponse, GenerationsUpdateGenerationData, GenerationsUpdateGenerationResponse, ItemsReadItemsData, ItemsReadItemsResponse, ItemsCreateItemData, ItemsCreateItemResponse, ItemsReadItemData, ItemsReadItemResponse, ItemsUpdateItemData, ItemsUpdateItemResponse, ItemsDeleteItemData, ItemsDeleteItemResponse, LoginLoginAccessTokenData, LoginLoginAccessTokenResponse, LoginLoginGoogleData, LoginLoginGoogleResponse, LoginTestTokenResponse, LoginRecoverPasswordData, LoginRecoverPasswordResponse, LoginResetPasswordData, LoginResetPasswordResponse, LoginRecoverPasswordHtmlContentData, LoginRecoverPasswordHtmlContentResponse, PrivateCreateUserData, PrivateCreateUserResponse, TemplatesReadTemplatesData, TemplatesReadTemplatesResponse, TemplatesCreateTemplateData, TemplatesCreateTemplateResponse, TemplatesReadTemplateData, TemplatesReadTemplateResponse, TemplatesUpdateTemplateData, TemplatesUpdateTemplateResponse, TemplatesReadTemplateVersionsData, TemplatesReadTemplateVersionsResponse, TemplatesCreateTemplateVersionData, TemplatesCreateTemplateVersionResponse, UsersReadUsersData, UsersReadUsersResponse, UsersCreateUserData, UsersCreateUserResponse, UsersReadUserMeResponse, UsersDeleteUserMeResponse, UsersUpdateUserMeData, UsersUpdateUserMeResponse, UsersUpdatePasswordMeData, UsersUpdatePasswordMeResponse, UsersRegisterUserData, UsersRegisterUserResponse, UsersReadUserByIdData, UsersReadUserByIdResponse, UsersUpdateUserData, UsersUpdateUserResponse, UsersDeleteUserData, UsersDeleteUserResponse, UtilsTestEmailData, UtilsTestEmailResponse, UtilsHealthCheckResponse } from './types.gen';
77

88
export class GenerateService {
99
/**
@@ -263,6 +263,26 @@ export class LoginService {
263263
});
264264
}
265265

266+
/**
267+
* Login Google
268+
* Google ID token login. Validates token with Google and returns local JWT.
269+
* @param data The data for the request.
270+
* @param data.requestBody
271+
* @returns Token Successful Response
272+
* @throws ApiError
273+
*/
274+
public static loginGoogle(data: LoginLoginGoogleData): CancelablePromise<LoginLoginGoogleResponse> {
275+
return __request(OpenAPI, {
276+
method: 'POST',
277+
url: '/api/v1/login/google',
278+
body: data.requestBody,
279+
mediaType: 'application/json',
280+
errors: {
281+
422: 'Validation Error'
282+
}
283+
});
284+
}
285+
266286
/**
267287
* Test Token
268288
* Test access token

frontend/src/client/types.gen.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ export type GenerationUpdate = {
6969
output_text?: (string | null);
7070
};
7171

72+
export type GoogleLoginRequest = {
73+
id_token: string;
74+
};
75+
7276
export type HTTPValidationError = {
7377
detail?: Array<ValidationError>;
7478
};
@@ -352,6 +356,12 @@ export type LoginLoginAccessTokenData = {
352356

353357
export type LoginLoginAccessTokenResponse = (Token);
354358

359+
export type LoginLoginGoogleData = {
360+
requestBody: GoogleLoginRequest;
361+
};
362+
363+
export type LoginLoginGoogleResponse = (Token);
364+
355365
export type LoginTestTokenResponse = (UserPublic);
356366

357367
export type LoginRecoverPasswordData = {

frontend/src/lib/googleIdentity.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ let googleScriptPromise: Promise<void> | null = null
2525

2626
export const loadGoogleIdentityScript = () => {
2727
if (typeof window === "undefined") {
28-
return Promise.reject(new Error("Google Identity is only available in browser"))
28+
return Promise.reject(
29+
new Error("Google Identity is only available in browser"),
30+
)
2931
}
3032

3133
const existing = (window as GoogleWindow).google?.accounts?.id
@@ -94,4 +96,3 @@ export const renderGoogleSignInButton = async ({
9496
width: Math.max(container.clientWidth || 320, 240),
9597
})
9698
}
97-

frontend/src/routes/login.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { z } from "zod"
1010

1111
import type { Body_login_login_access_token as AccessToken } from "@/client"
1212
import { AuthLayout } from "@/components/Common/AuthLayout"
13-
import { Separator } from "@/components/ui/separator"
1413
import {
1514
Form,
1615
FormControl,
@@ -22,6 +21,7 @@ import {
2221
import { Input } from "@/components/ui/input"
2322
import { LoadingButton } from "@/components/ui/loading-button"
2423
import { PasswordInput } from "@/components/ui/password-input"
24+
import { Separator } from "@/components/ui/separator"
2525
import useAuth, { isLoggedIn } from "@/hooks/useAuth"
2626
import { renderGoogleSignInButton } from "@/lib/googleIdentity"
2727

@@ -89,14 +89,16 @@ function Login() {
8989
}).catch((error) => {
9090
if (cancelled) return
9191
setGoogleInitError(
92-
error instanceof Error ? error.message : "Failed to initialize Google login",
92+
error instanceof Error
93+
? error.message
94+
: "Failed to initialize Google login",
9395
)
9496
})
9597

9698
return () => {
9799
cancelled = true
98100
}
99-
}, [googleClientId, googleLoginMutation])
101+
}, [googleLoginMutation])
100102

101103
return (
102104
<AuthLayout>
@@ -175,7 +177,9 @@ function Login() {
175177
<div className="grid gap-2">
176178
<div
177179
ref={googleButtonRef}
178-
className={googleLoginMutation.isPending ? "opacity-70" : ""}
180+
className={
181+
googleLoginMutation.isPending ? "opacity-70" : ""
182+
}
179183
/>
180184
{googleLoginMutation.isPending ? (
181185
<p className="text-center text-xs text-muted-foreground">

0 commit comments

Comments
 (0)