@@ -15,11 +15,11 @@ import { SubscriptionStatus } from '../payment/plans';
1515import { ensureArgsSchemaOrThrowHttpError } from '../server/validation' ;
1616
1717const openAi = getOpenAi ( ) ;
18- function getOpenAi ( ) : OpenAI | null {
18+ function getOpenAi ( ) : OpenAI {
1919 if ( process . env . OPENAI_API_KEY ) {
2020 return new OpenAI ( { apiKey : process . env . OPENAI_API_KEY } ) ;
2121 } else {
22- return null ;
22+ throw new Error ( 'OpenAI API key is not set' ) ;
2323 }
2424}
2525
@@ -38,12 +38,11 @@ export const generateGptResponse: GenerateGptResponse<GenerateGptResponseInput,
3838 throw new HttpError ( 401 , 'Only authenticated users are allowed to perform this operation' ) ;
3939 }
4040
41- const { hours } = ensureArgsSchemaOrThrowHttpError ( generateGptResponseInputSchema , rawArgs ) ;
42-
4341 if ( ! isEligibleForResponse ( context . user ) ) {
4442 throw new HttpError ( 402 , 'User has not paid or is out of credits' ) ;
4543 }
4644
45+ const { hours } = ensureArgsSchemaOrThrowHttpError ( generateGptResponseInputSchema , rawArgs ) ;
4746 const tasks = await context . entities . Task . findMany ( {
4847 where : {
4948 user : {
@@ -53,16 +52,19 @@ export const generateGptResponse: GenerateGptResponse<GenerateGptResponseInput,
5352 } ) ;
5453
5554 console . log ( 'Calling open AI api' ) ;
56- const dailyPlanJson = await getDailyPlanFromGpt ( tasks , hours ) ;
57- if ( dailyPlanJson === null ) {
55+ const generatedSchedule = await generateScheduleWithGpt ( tasks , hours ) ;
56+ if ( generatedSchedule === null ) {
5857 throw new HttpError ( 500 , 'Encountered a problem in communication with OpenAI' ) ;
5958 }
6059
61- // TODO: Do I need a try catch now that I'm saving a response and
62- // decrementing credits in a transaction?
63-
64- // NOTE: I changed this up, first I do the request, and then I decrement
65- // credits. Is that dangerous? Protecting from it could be too complicated
60+ // We decrement the credits after using up tokens to get a daily plan
61+ // from Chat GPT.
62+ //
63+ // This way, users don't feel cheated if something goes wrong.
64+ // On the flipside, users can theoretically abuse this and spend more
65+ // credits than they have, but the damage should be pretty limited.
66+ //
67+ // Think about which option you prefer for you and edit the code accordingly.
6668 const decrementCredit = context . entities . User . update ( {
6769 where : { id : context . user . id } ,
6870 data : {
@@ -75,15 +77,14 @@ export const generateGptResponse: GenerateGptResponse<GenerateGptResponseInput,
7577 const createResponse = context . entities . GptResponse . create ( {
7678 data : {
7779 user : { connect : { id : context . user . id } } ,
78- content : dailyPlanJson ,
80+ content : JSON . stringify ( generatedSchedule ) ,
7981 } ,
8082 } ) ;
8183
8284 console . log ( 'Decrementing credits and saving response' ) ;
8385 prisma . $transaction ( [ decrementCredit , createResponse ] ) ;
8486
85- // TODO: Can this ever fail?
86- return JSON . parse ( dailyPlanJson ) ;
87+ return generatedSchedule ;
8788} ;
8889
8990function isEligibleForResponse ( user : User ) {
@@ -205,11 +206,7 @@ export const getAllTasksByUser: GetAllTasksByUser<void, Task[]> = async (_args,
205206} ;
206207//#endregion
207208
208- async function getDailyPlanFromGpt ( tasks : Task [ ] , hours : string ) : Promise < string | null > {
209- if ( openAi === null ) {
210- return null ;
211- }
212-
209+ async function generateScheduleWithGpt ( tasks : Task [ ] , hours : string ) : Promise < GeneratedSchedule | null > {
213210 const parsedTasks = tasks . map ( ( { description, time } ) => ( {
214211 description,
215212 time,
@@ -294,5 +291,5 @@ async function getDailyPlanFromGpt(tasks: Task[], hours: string): Promise<string
294291 } ) ;
295292
296293 const gptResponse = completion ?. choices [ 0 ] ?. message ?. tool_calls ?. [ 0 ] ?. function . arguments ;
297- return gptResponse ?? null ;
294+ return gptResponse !== undefined ? JSON . parse ( gptResponse ) : null ;
298295}
0 commit comments