diff --git a/.eslintrc.js b/.eslintrc.js index 32600e5c..3319753f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,4 @@ +/* eslint-disable no-undef */ module.exports = { root: true, parser: '@typescript-eslint/parser', diff --git a/backend/src/build-system/handlers/ux/sitemap-structure/sms-page.ts b/backend/src/build-system/handlers/ux/sitemap-structure/sms-page.ts index 9b54dbd1..5969c004 100644 --- a/backend/src/build-system/handlers/ux/sitemap-structure/sms-page.ts +++ b/backend/src/build-system/handlers/ux/sitemap-structure/sms-page.ts @@ -3,7 +3,10 @@ import { BuilderContext } from 'src/build-system/context'; import { BuildHandler, BuildResult } from 'src/build-system/types'; import { prompts } from './prompt'; import { removeCodeBlockFences } from 'src/build-system/utils/strings'; -import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper'; +import { + batchChatSyncWithClock, + chatSyncWithClocker, +} from 'src/build-system/utils/handler-helper'; import { MessageInterface } from 'src/common/model-provider/types'; import { MissingConfigurationError, @@ -71,7 +74,12 @@ export class Level2UXSitemapStructureHandler implements BuildHandler { ], })); - const refinedSections = await modelProvider.batchChatSync(requests); + const refinedSections = await batchChatSyncWithClock( + context, + 'generate page-by-page by sections', + this.id, + requests, + ); // TODO: deal with chat clocker // Combine the refined sections into the final document diff --git a/backend/src/build-system/monitor.ts b/backend/src/build-system/monitor.ts index 24c60ffd..9de2d42e 100644 --- a/backend/src/build-system/monitor.ts +++ b/backend/src/build-system/monitor.ts @@ -1,8 +1,8 @@ import { Logger } from '@nestjs/common'; import { BuildNode, BuildStep, BuildSequence } from './types'; import { ProjectEventLogger } from './logger'; -import { ModelProvider } from 'src/common/model-provider'; import { MessageInterface } from 'src/common/model-provider/types'; +import { OpenAIModelProvider } from 'src/common/model-provider/openai-model-provider'; /** * Metrics for sequence, step, and node execution */ @@ -89,7 +89,7 @@ export class BuildMonitor { private sequenceMetrics: Map = new Map(); private static timeRecorders: Map = new Map(); - private static model = ModelProvider.getInstance(); + private static model = OpenAIModelProvider.getInstance(); private constructor() { this.logger = new Logger('BuildMonitor'); diff --git a/backend/src/build-system/utils/handler-helper.ts b/backend/src/build-system/utils/handler-helper.ts index e99bbe62..f6313b16 100644 --- a/backend/src/build-system/utils/handler-helper.ts +++ b/backend/src/build-system/utils/handler-helper.ts @@ -17,3 +17,27 @@ export async function chatSyncWithClocker( BuildMonitor.timeRecorder(duration, id, step, inputContent, modelResponse); return modelResponse; } + +export async function batchChatSyncWithClock( + context: BuilderContext, + step: string, + id: string, + inputs: ChatInput[], +): Promise { + const startTime = new Date(); + const modelResponses = await context.model.batchChatSync(inputs); + const endTime = new Date(); + const duration = endTime.getTime() - startTime.getTime(); + + const inputContent = inputs + .map((input) => input.messages.map((m) => m.content).join('')) + .join(''); + BuildMonitor.timeRecorder( + duration, + id, + step, + inputContent, + modelResponses.join(''), + ); + return modelResponses; +} diff --git a/codefox-docs/src/components/HomepageFeatures/index.tsx b/codefox-docs/src/components/HomepageFeatures/index.tsx index 7e72738d..2c8e5924 100644 --- a/codefox-docs/src/components/HomepageFeatures/index.tsx +++ b/codefox-docs/src/components/HomepageFeatures/index.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ import clsx from 'clsx'; import Heading from '@theme/Heading'; import styles from './styles.module.css'; diff --git a/frontend/src/graphql/type.tsx b/frontend/src/graphql/type.tsx index 316b0a97..e769a61f 100644 --- a/frontend/src/graphql/type.tsx +++ b/frontend/src/graphql/type.tsx @@ -1,22 +1,41 @@ -import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql'; +import { + GraphQLResolveInfo, + GraphQLScalarType, + GraphQLScalarTypeConfig, +} from 'graphql'; import { gql } from '@apollo/client'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { [_ in K]?: never }; -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -export type RequireFields = Omit & { [P in K]-?: NonNullable }; +export type Exact = { + [K in keyof T]: T[K]; +}; +export type MakeOptional = Omit & { + [SubKey in K]?: Maybe; +}; +export type MakeMaybe = Omit & { + [SubKey in K]: Maybe; +}; +export type MakeEmpty< + T extends { [key: string]: unknown }, + K extends keyof T, +> = { [_ in K]?: never }; +export type Incremental = + | T + | { + [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never; + }; +export type RequireFields = Omit & { + [P in K]-?: NonNullable; +}; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } + ID: { input: string; output: string }; + String: { input: string; output: string }; + Boolean: { input: boolean; output: boolean }; + Int: { input: number; output: number }; + Float: { input: number; output: number }; /** Date custom scalar type */ - Date: { input: Date; output: Date; } + Date: { input: Date; output: Date }; }; export type Chat = { @@ -113,59 +132,48 @@ export type Mutation = { upsertProject: Project; }; - export type MutationClearChatHistoryArgs = { chatId: Scalars['String']['input']; }; - export type MutationCreateChatArgs = { newChatInput: NewChatInput; }; - export type MutationDeleteChatArgs = { chatId: Scalars['String']['input']; }; - export type MutationDeleteProjectArgs = { projectId: Scalars['String']['input']; }; - export type MutationLoginArgs = { input: LoginUserInput; }; - export type MutationRegisterUserArgs = { input: RegisterUserInput; }; - export type MutationRemovePackageFromProjectArgs = { packageId: Scalars['String']['input']; projectId: Scalars['String']['input']; }; - export type MutationTriggerChatStreamArgs = { input: ChatInputType; }; - export type MutationUpdateChatTitleArgs = { updateChatTitleInput: UpdateChatTitleInput; }; - export type MutationUpdateProjectPathArgs = { newPath: Scalars['String']['input']; projectId: Scalars['String']['input']; }; - export type MutationUpsertProjectArgs = { upsertProjectInput: UpsertProjectInput; }; @@ -212,22 +220,18 @@ export type Query = { me: User; }; - export type QueryCheckTokenArgs = { input: CheckTokenInput; }; - export type QueryGetChatDetailsArgs = { chatId: Scalars['String']['input']; }; - export type QueryGetChatHistoryArgs = { chatId: Scalars['String']['input']; }; - export type QueryGetProjectDetailsArgs = { projectId: Scalars['String']['input']; }; @@ -238,21 +242,15 @@ export type RegisterUserInput = { username: Scalars['String']['input']; }; -export type Role = - | 'Assistant' - | 'System' - | 'User'; +export type Role = 'Assistant' | 'System' | 'User'; -export type StreamStatus = - | 'DONE' - | 'STREAMING'; +export type StreamStatus = 'DONE' | 'STREAMING'; export type Subscription = { __typename: 'Subscription'; chatStream?: Maybe; }; - export type SubscriptionChatStreamArgs = { input: ChatInputType; }; @@ -284,11 +282,12 @@ export type ResolversObject = WithIndex; export type ResolverTypeWrapper = Promise | T; - export type ResolverWithResolve = { resolve: ResolverFn; }; -export type Resolver = ResolverFn | ResolverWithResolve; +export type Resolver = + | ResolverFn + | ResolverWithResolve; export type ResolverFn = ( parent: TParent, @@ -311,9 +310,25 @@ export type SubscriptionResolveFn = ( info: GraphQLResolveInfo ) => TResult | Promise; -export interface SubscriptionSubscriberObject { - subscribe: SubscriptionSubscribeFn<{ [key in TKey]: TResult }, TParent, TContext, TArgs>; - resolve?: SubscriptionResolveFn; +export interface SubscriptionSubscriberObject< + TResult, + TKey extends string, + TParent, + TContext, + TArgs, +> { + subscribe: SubscriptionSubscribeFn< + { [key in TKey]: TResult }, + TParent, + TContext, + TArgs + >; + resolve?: SubscriptionResolveFn< + TResult, + { [key in TKey]: TResult }, + TContext, + TArgs + >; } export interface SubscriptionResolverObject { @@ -321,12 +336,26 @@ export interface SubscriptionResolverObject { resolve: SubscriptionResolveFn; } -export type SubscriptionObject = +export type SubscriptionObject< + TResult, + TKey extends string, + TParent, + TContext, + TArgs, +> = | SubscriptionSubscriberObject | SubscriptionResolverObject; -export type SubscriptionResolver = - | ((...args: any[]) => SubscriptionObject) +export type SubscriptionResolver< + TResult, + TKey extends string, + TParent = {}, + TContext = {}, + TArgs = {}, +> = + | (( + ...args: any[] + ) => SubscriptionObject) | SubscriptionObject; export type TypeResolveFn = ( @@ -335,11 +364,20 @@ export type TypeResolveFn = ( info: GraphQLResolveInfo ) => Maybe | Promise>; -export type IsTypeOfResolverFn = (obj: T, context: TContext, info: GraphQLResolveInfo) => boolean | Promise; +export type IsTypeOfResolverFn = ( + obj: T, + context: TContext, + info: GraphQLResolveInfo +) => boolean | Promise; export type NextResolverFn = () => Promise; -export type DirectiveResolverFn = ( +export type DirectiveResolverFn< + TResult = {}, + TParent = {}, + TContext = {}, + TArgs = {}, +> = ( next: NextResolverFn, parent: TParent, args: TArgs, @@ -347,8 +385,6 @@ export type DirectiveResolverFn TResult | Promise; - - /** Mapping between all available schema types and the resolvers types */ export type ResolversTypes = ResolversObject<{ Boolean: ResolverTypeWrapper; @@ -409,51 +445,96 @@ export type ResolversParentTypes = ResolversObject<{ User: User; }>; -export type ChatResolvers = ResolversObject<{ +export type ChatResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['Chat'] = ResolversParentTypes['Chat'], +> = ResolversObject<{ createdAt?: Resolver; id?: Resolver; isActive?: Resolver; isDeleted?: Resolver; - messages?: Resolver>, ParentType, ContextType>; + messages?: Resolver< + Maybe>, + ParentType, + ContextType + >; title?: Resolver, ParentType, ContextType>; updatedAt?: Resolver; user?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }>; -export type ChatCompletionChoiceTypeResolvers = ResolversObject<{ - delta?: Resolver; - finishReason?: Resolver, ParentType, ContextType>; +export type ChatCompletionChoiceTypeResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['ChatCompletionChoiceType'] = ResolversParentTypes['ChatCompletionChoiceType'], +> = ResolversObject<{ + delta?: Resolver< + ResolversTypes['ChatCompletionDeltaType'], + ParentType, + ContextType + >; + finishReason?: Resolver< + Maybe, + ParentType, + ContextType + >; index?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }>; -export type ChatCompletionChunkTypeResolvers = ResolversObject<{ - choices?: Resolver, ParentType, ContextType>; +export type ChatCompletionChunkTypeResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['ChatCompletionChunkType'] = ResolversParentTypes['ChatCompletionChunkType'], +> = ResolversObject<{ + choices?: Resolver< + Array, + ParentType, + ContextType + >; created?: Resolver; id?: Resolver; model?: Resolver; object?: Resolver; status?: Resolver; - systemFingerprint?: Resolver, ParentType, ContextType>; + systemFingerprint?: Resolver< + Maybe, + ParentType, + ContextType + >; __isTypeOf?: IsTypeOfResolverFn; }>; -export type ChatCompletionDeltaTypeResolvers = ResolversObject<{ +export type ChatCompletionDeltaTypeResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['ChatCompletionDeltaType'] = ResolversParentTypes['ChatCompletionDeltaType'], +> = ResolversObject<{ content?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; }>; -export interface DateScalarConfig extends GraphQLScalarTypeConfig { +export interface DateScalarConfig + extends GraphQLScalarTypeConfig { name: 'Date'; } -export type LoginResponseResolvers = ResolversObject<{ +export type LoginResponseResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['LoginResponse'] = ResolversParentTypes['LoginResponse'], +> = ResolversObject<{ accessToken?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }>; -export type MenuResolvers = ResolversObject<{ +export type MenuResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['Menu'] = ResolversParentTypes['Menu'], +> = ResolversObject<{ createdAt?: Resolver; id?: Resolver; isActive?: Resolver; @@ -465,7 +546,11 @@ export type MenuResolvers; }>; -export type MessageResolvers = ResolversObject<{ +export type MessageResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['Message'] = ResolversParentTypes['Message'], +> = ResolversObject<{ content?: Resolver; createdAt?: Resolver; id?: Resolver; @@ -477,34 +562,108 @@ export type MessageResolvers; }>; -export type MutationResolvers = ResolversObject<{ - clearChatHistory?: Resolver>; - createChat?: Resolver>; - deleteChat?: Resolver>; - deleteProject?: Resolver>; - login?: Resolver>; - registerUser?: Resolver>; - removePackageFromProject?: Resolver>; - triggerChatStream?: Resolver>; - updateChatTitle?: Resolver, ParentType, ContextType, RequireFields>; - updateProjectPath?: Resolver>; - upsertProject?: Resolver>; +export type MutationResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['Mutation'] = ResolversParentTypes['Mutation'], +> = ResolversObject<{ + clearChatHistory?: Resolver< + ResolversTypes['Boolean'], + ParentType, + ContextType, + RequireFields + >; + createChat?: Resolver< + ResolversTypes['Chat'], + ParentType, + ContextType, + RequireFields + >; + deleteChat?: Resolver< + ResolversTypes['Boolean'], + ParentType, + ContextType, + RequireFields + >; + deleteProject?: Resolver< + ResolversTypes['Boolean'], + ParentType, + ContextType, + RequireFields + >; + login?: Resolver< + ResolversTypes['LoginResponse'], + ParentType, + ContextType, + RequireFields + >; + registerUser?: Resolver< + ResolversTypes['User'], + ParentType, + ContextType, + RequireFields + >; + removePackageFromProject?: Resolver< + ResolversTypes['Boolean'], + ParentType, + ContextType, + RequireFields< + MutationRemovePackageFromProjectArgs, + 'packageId' | 'projectId' + > + >; + triggerChatStream?: Resolver< + ResolversTypes['Boolean'], + ParentType, + ContextType, + RequireFields + >; + updateChatTitle?: Resolver< + Maybe, + ParentType, + ContextType, + RequireFields + >; + updateProjectPath?: Resolver< + ResolversTypes['Boolean'], + ParentType, + ContextType, + RequireFields + >; + upsertProject?: Resolver< + ResolversTypes['Project'], + ParentType, + ContextType, + RequireFields + >; }>; -export type ProjectResolvers = ResolversObject<{ +export type ProjectResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['Project'] = ResolversParentTypes['Project'], +> = ResolversObject<{ createdAt?: Resolver; id?: Resolver; isActive?: Resolver; isDeleted?: Resolver; path?: Resolver; projectName?: Resolver; - projectPackages?: Resolver>, ParentType, ContextType>; + projectPackages?: Resolver< + Maybe>, + ParentType, + ContextType + >; updatedAt?: Resolver; userId?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }>; -export type ProjectPackagesResolvers = ResolversObject<{ +export type ProjectPackagesResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['ProjectPackages'] = ResolversParentTypes['ProjectPackages'], +> = ResolversObject<{ content?: Resolver; createdAt?: Resolver; id?: Resolver; @@ -515,24 +674,74 @@ export type ProjectPackagesResolvers; }>; -export type QueryResolvers = ResolversObject<{ - checkToken?: Resolver>; - getAvailableModelTags?: Resolver>, ParentType, ContextType>; - getChatDetails?: Resolver, ParentType, ContextType, RequireFields>; - getChatHistory?: Resolver, ParentType, ContextType, RequireFields>; +export type QueryResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['Query'] = ResolversParentTypes['Query'], +> = ResolversObject<{ + checkToken?: Resolver< + ResolversTypes['Boolean'], + ParentType, + ContextType, + RequireFields + >; + getAvailableModelTags?: Resolver< + Maybe>, + ParentType, + ContextType + >; + getChatDetails?: Resolver< + Maybe, + ParentType, + ContextType, + RequireFields + >; + getChatHistory?: Resolver< + Array, + ParentType, + ContextType, + RequireFields + >; getHello?: Resolver; - getProjectDetails?: Resolver>; - getUserChats?: Resolver>, ParentType, ContextType>; - getUserProjects?: Resolver, ParentType, ContextType>; + getProjectDetails?: Resolver< + ResolversTypes['Project'], + ParentType, + ContextType, + RequireFields + >; + getUserChats?: Resolver< + Maybe>, + ParentType, + ContextType + >; + getUserProjects?: Resolver< + Array, + ParentType, + ContextType + >; logout?: Resolver; me?: Resolver; }>; -export type SubscriptionResolvers = ResolversObject<{ - chatStream?: SubscriptionResolver, "chatStream", ParentType, ContextType, RequireFields>; +export type SubscriptionResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['Subscription'] = ResolversParentTypes['Subscription'], +> = ResolversObject<{ + chatStream?: SubscriptionResolver< + Maybe, + 'chatStream', + ParentType, + ContextType, + RequireFields + >; }>; -export type UserResolvers = ResolversObject<{ +export type UserResolvers< + ContextType = any, + ParentType extends + ResolversParentTypes['User'] = ResolversParentTypes['User'], +> = ResolversObject<{ chats?: Resolver, ParentType, ContextType>; createdAt?: Resolver; email?: Resolver; @@ -559,4 +768,3 @@ export type Resolvers = ResolversObject<{ Subscription?: SubscriptionResolvers; User?: UserResolvers; }>; - diff --git a/frontend/src/test/projectApi.spec.ts b/frontend/src/test/projectApi.spec.ts deleted file mode 100644 index 3b61505a..00000000 --- a/frontend/src/test/projectApi.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { - getUserProjects, - getProjectDetails, - deleteProject, - upsertProject, - removePackageFromProject, -} from '../app/api/project/route'; - -describe('Project API', () => { - let projectId: string; - let packageId: string; - - it('should upsert a project', async () => { - const upsertProjectInput = { - projectName: 'Test Project', - projectPackages: ['Package 1', 'Package 2'], - }; - const project = await upsertProject(upsertProjectInput); - expect(project).toHaveProperty('id'); - projectId = project.id; - console.log('Project id is: ' + projectId); - packageId = project.projectPackages[0].id; - }); - - it('should get user projects', async () => { - const projects = await getUserProjects(); - expect(Array.isArray(projects)).toBe(true); - expect(projects.length).toBeGreaterThan(0); - }); - - it('should get project details', async () => { - const projectDetails = await getProjectDetails(projectId); - expect(projectDetails).toHaveProperty('id', projectId); - }); - - it('should remove a package from project', async () => { - const removed = await removePackageFromProject(projectId, packageId); - expect(removed).toBe(true); - }); - - it('should delete a project', async () => { - const deleted = await deleteProject(projectId); - expect(deleted).toBe(true); - }); -}); - -// Remove the expect function declaration diff --git a/package.json b/package.json index 132744e7..75d59a95 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "lint": "eslint . --ext .js,.ts,.tsx", "format": "prettier --write .", "dev:backend": "turbo dev:backend", - "test": "turbo test" + "test": "turbo test", + "fix": "eslint . --ext .js,.ts,.tsx --fix" }, "postinstall": "pnpm --filter codefox-common run build", "keywords": [],