diff --git a/package-lock.json b/package-lock.json index 1ca63b1..8da557b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12898,37 +12898,6 @@ "dev": true, "license": "ISC" }, - "node_modules/html-dom-parser": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-5.1.1.tgz", - "integrity": "sha512-+o4Y4Z0CLuyemeccvGN4bAO20aauB2N9tFEAep5x4OW34kV4PTarBHm6RL02afYt2BMKcr0D2Agep8S3nJPIBg==", - "license": "MIT", - "dependencies": { - "domhandler": "5.0.3", - "htmlparser2": "10.0.0" - } - }, - "node_modules/html-react-parser": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-5.2.6.tgz", - "integrity": "sha512-qcpPWLaSvqXi+TndiHbCa+z8qt0tVzjMwFGFBAa41ggC+ZA5BHaMIeMJla9g3VSp4SmiZb9qyQbmbpHYpIfPOg==", - "license": "MIT", - "dependencies": { - "domhandler": "5.0.3", - "html-dom-parser": "5.1.1", - "react-property": "2.0.2", - "style-to-js": "1.1.17" - }, - "peerDependencies": { - "@types/react": "0.14 || 15 || 16 || 17 || 18 || 19", - "react": "0.14 || 15 || 16 || 17 || 18 || 19" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/html-to-image": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", @@ -17952,12 +17921,6 @@ "react": ">=18" } }, - "node_modules/react-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.2.tgz", - "integrity": "sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==", - "license": "MIT" - }, "node_modules/react-reconciler": { "version": "0.33.0", "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.33.0.tgz", diff --git a/src/ipc/handlers/pro_handlers.ts b/src/ipc/handlers/pro_handlers.ts index 6219f48..5e69d06 100644 --- a/src/ipc/handlers/pro_handlers.ts +++ b/src/ipc/handlers/pro_handlers.ts @@ -4,12 +4,19 @@ import { createLoggedHandler } from "./safe_handle"; import { readSettings } from "../../main/settings"; // Assuming settings are read this way import { UserBudgetInfo, UserBudgetInfoSchema } from "../ipc_types"; import { IS_TEST_BUILD } from "../utils/test_utils"; +import { z } from "zod"; + +export const UserInfoResponseSchema = z.object({ + usedCredits: z.number(), + totalCredits: z.number(), + budgetResetDate: z.string(), // ISO date string from API + userId: z.string(), +}); +export type UserInfoResponse = z.infer; const logger = log.scope("pro_handlers"); const handle = createLoggedHandler(logger); -const CONVERSION_RATIO = (10 * 3) / 2; - export function registerProHandlers() { // This method should try to avoid throwing errors because this is auxiliary // information and isn't critical to using the app @@ -36,7 +43,7 @@ export function registerProHandlers() { return null; } - const url = "https://llm-gateway.dyad.sh/user/info"; + const url = "https://api.dyad.sh/v1/user/info"; const headers = { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}`, @@ -57,21 +64,28 @@ export function registerProHandlers() { return null; } - const data = await response.json(); - const userInfoData = data["user_info"]; - const userId = userInfoData["user_id"]; + const rawData = await response.json(); + + // Validate the API response structure + const data = UserInfoResponseSchema.parse(rawData); + // Turn user_abc1234 => "****1234" // Preserve the last 4 characters so we can correlate bug reports // with the user. const redactedUserId = - userId.length > 8 ? "****" + userId.slice(-4) : ""; + data.userId.length > 8 ? "****" + data.userId.slice(-4) : ""; + logger.info("Successfully fetched user budget information."); - return UserBudgetInfoSchema.parse({ - usedCredits: userInfoData["spend"] * CONVERSION_RATIO, - totalCredits: userInfoData["max_budget"] * CONVERSION_RATIO, - budgetResetDate: new Date(userInfoData["budget_reset_at"]), + + // Transform to UserBudgetInfo format + const userBudgetInfo = UserBudgetInfoSchema.parse({ + usedCredits: data.usedCredits, + totalCredits: data.totalCredits, + budgetResetDate: new Date(data.budgetResetDate), redactedUserId: redactedUserId, }); + + return userBudgetInfo; } catch (error: any) { logger.error(`Error fetching user budget: ${error.message}`, error); return null;