Skip to content

Commit d2c94ea

Browse files
committed
Merge branch 'main' into feat-Oauth2-google-support
2 parents 4c66b8f + aae0892 commit d2c94ea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+4569
-400
lines changed

.github/workflows/autofix.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ name: autofix.ci
22

33
on:
44
pull_request:
5-
push:
65
branches: [ "main" ]
76

87
permissions:

.github/workflows/backend-ci.yml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
name: Backend CI
1+
name: backend
22
on:
3-
push:
4-
branches: [ main ]
5-
paths:
6-
- 'backend/**'
7-
- 'codefox-common/**'
83
pull_request:
94
branches: [ main ]
105
paths:
@@ -13,7 +8,7 @@ on:
138
workflow_dispatch:
149
jobs:
1510
build:
16-
name: Install and Build Backend
11+
name: build
1712
runs-on: ubuntu-latest
1813

1914
steps:

.github/workflows/frontend-ci.yml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
name: Frontend CI
1+
name: frontend
22
on:
3-
push:
4-
branches: [ main ]
5-
paths:
6-
- 'frontend/**'
7-
- 'codefox-common/**'
83
pull_request:
94
branches: [ main ]
105
paths:
@@ -13,7 +8,7 @@ on:
138
workflow_dispatch:
149
jobs:
1510
build:
16-
name: Install and Build Frontend
11+
name: build
1712
runs-on: ubuntu-latest
1813

1914
steps:

.github/workflows/llm-server.yml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
name: LLM Server CI
1+
name: llm
22
on:
3-
push:
4-
branches: [ main ]
5-
paths:
6-
- 'llm-server/**'
7-
- 'codefox-common/**'
83
pull_request:
94
branches: [ main ]
105
paths:
@@ -13,7 +8,7 @@ on:
138
workflow_dispatch:
149
jobs:
1510
build:
16-
name: Install and Build LLM Server
11+
name: build
1712
runs-on: ubuntu-latest
1813

1914
steps:

backend/.env.example

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,24 @@ MAIL_FROM=noreply@example.com
3232
MAIL_PORT=587
3333
MAIL_DOMAIN=your_net
3434

35+
# github app
36+
GITHUB_ENABLED=true # set false to disable GitHub
37+
GITHUB_APP_ID="GITHUB_APP_ID"
38+
GITHUB_PRIVATE_KEY_PATH="YOUR_PATH"
39+
GITHUB_CLIENT_ID="GITHUB_CLIENT_ID"
40+
GITHUB_CLIENT_SECRET="GITHUB_CLIENT_SECRET"
41+
GITHUB_WEBHOOK_SECRET="GITHUB_WEBHOOK_SECRET"
42+
CALLBACK="CALLBACK"
43+
44+
# Database Configuration
45+
USE_REMOTE_DB=false
46+
DB_TYPE=
47+
DB_HOST=
48+
DB_PORT=0
49+
DB_USERNAME=
50+
DB_NAME=
51+
DB_REGION=us-east-2
52+
3553
## Google OAuth
3654
GOOGLE_CLIENT_ID=YOUR_CLIENT_ID
3755
GOOGLE_SECRET=Your_SECRET

backend/package.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"@huggingface/transformers": "latest",
3434
"@nestjs-modules/mailer": "^2.0.2",
3535
"@nestjs/apollo": "^12.2.0",
36-
"@nestjs/axios": "^3.0.3",
36+
"@nestjs/axios": "^3.1.3",
3737
"@nestjs/common": "^10.0.0",
3838
"@nestjs/config": "^3.2.3",
3939
"@nestjs/core": "^10.0.0",
@@ -42,11 +42,15 @@
4242
"@nestjs/passport": "^11.0.5",
4343
"@nestjs/platform-express": "^10.0.0",
4444
"@nestjs/typeorm": "^10.0.2",
45+
"@octokit/auth-app": "^7.1.5",
46+
"@octokit/webhooks": "^13.7.5",
4547
"@types/bcrypt": "^5.0.2",
4648
"@types/fs-extra": "^11.0.4",
4749
"@types/normalize-path": "^3.0.2",
4850
"@types/toposort": "^2.0.7",
49-
"axios": "^1.7.7",
51+
"archiver": "^7.0.1",
52+
"axios": "^1.8.3",
53+
"aws-sdk": "^2.1692.0",
5054
"bcrypt": "^5.1.1",
5155
"class-transformer": "^0.5.1",
5256
"class-validator": "^0.14.1",
@@ -59,16 +63,20 @@
5963
"graphql-subscriptions": "^2.0.0",
6064
"graphql-upload-minimal": "^1.6.1",
6165
"graphql-ws": "^5.16.0",
66+
"jsonwebtoken": "^9.0.2",
6267
"lodash": "^4.17.21",
6368
"markdown-to-txt": "^2.0.1",
6469
"nodemailer": "^6.10.0",
6570
"normalize-path": "^3.0.0",
71+
"octokit": "^4.1.2",
6672
"openai": "^4.77.0",
6773
"p-queue-es5": "^6.0.2",
6874
"passport": "^0.7.0",
6975
"passport-google-oauth20": "^2.0.0",
76+
"pg": "^8.14.1",
7077
"reflect-metadata": "^0.2.2",
7178
"rxjs": "^7.8.1",
79+
"simple-git": "^3.27.0",
7280
"sqlite3": "^5.1.7",
7381
"subscriptions-transport-ws": "^0.11.0",
7482
"toposort": "^2.0.2",

backend/src/app.module.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
22
import { Module } from '@nestjs/common';
3-
import { ConfigModule } from '@nestjs/config';
3+
import { ConfigModule, ConfigService } from '@nestjs/config';
4+
import { EnvironmentVariables } from './config/env.validation';
45
import { GraphQLModule } from '@nestjs/graphql';
56
import { TypeOrmModule } from '@nestjs/typeorm';
67
import { join } from 'path';
@@ -16,14 +17,18 @@ import { APP_INTERCEPTOR } from '@nestjs/core';
1617
import { LoggingInterceptor } from 'src/interceptor/LoggingInterceptor';
1718
import { PromptToolModule } from './prompt-tool/prompt-tool.module';
1819
import { MailModule } from './mail/mail.module';
20+
import { GitHubModule } from './github/github.module';
21+
import { AppConfigService } from './config/config.service';
22+
import { getDatabaseConfig } from './database.config';
1923

20-
// TODO(Sma1lboy): move to a separate file
21-
function isProduction(): boolean {
22-
return process.env.NODE_ENV === 'production';
23-
}
2424
@Module({
2525
imports: [
26-
ConfigModule.forRoot({ isGlobal: true }),
26+
ConfigModule.forRoot({
27+
isGlobal: true,
28+
validate: (config: Record<string, unknown>) => {
29+
return Object.assign(new EnvironmentVariables(), config);
30+
},
31+
}),
2732
GraphQLModule.forRoot<ApolloDriverConfig>({
2833
driver: ApolloDriver,
2934
autoSchemaFile: join(process.cwd(), '../frontend/src/graphql/schema.gql'),
@@ -35,11 +40,11 @@ function isProduction(): boolean {
3540
},
3641
context: ({ req, res }) => ({ req, res }),
3742
}),
38-
TypeOrmModule.forRoot({
39-
type: 'sqlite',
40-
database: join(process.cwd(), './database.db'),
41-
synchronize: !isProduction(),
42-
entities: [__dirname + '/**/*.model{.ts,.js}'],
43+
TypeOrmModule.forRootAsync({
44+
imports: [ConfigModule],
45+
useFactory: (config: ConfigService<EnvironmentVariables>) =>
46+
getDatabaseConfig(new AppConfigService(config)),
47+
inject: [ConfigService],
4348
}),
4449
InitModule,
4550
UserModule,
@@ -50,13 +55,16 @@ function isProduction(): boolean {
5055
PromptToolModule,
5156
MailModule,
5257
TypeOrmModule.forFeature([User]),
58+
GitHubModule,
5359
],
5460
providers: [
5561
AppResolver,
62+
AppConfigService,
5663
{
5764
provide: APP_INTERCEPTOR,
5865
useClass: LoggingInterceptor,
5966
},
6067
],
68+
exports: [AppConfigService],
6169
})
6270
export class AppModule {}

backend/src/auth/auth.module.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,28 @@ import { TypeOrmModule } from '@nestjs/typeorm';
33
import { Menu } from './menu/menu.model';
44
import { JwtModule } from '@nestjs/jwt';
55
import { Role } from './role/role.model';
6-
import { ConfigModule, ConfigService } from '@nestjs/config';
76
import { AuthService } from './auth.service';
87
import { User } from 'src/user/user.model';
8+
import { AppConfigService } from 'src/config/config.service';
99
import { AuthResolver } from './auth.resolver';
1010
import { RefreshToken } from './refresh-token/refresh-token.model';
1111
import { JwtCacheModule } from 'src/jwt-cache/jwt-cache.module';
1212
import { MailModule } from 'src/mail/mail.module';
1313
import { GoogleStrategy } from './oauth/GoogleStrategy';
1414
import { GoogleController } from './google.controller';
15+
import { AppConfigModule } from 'src/config/config.module';
1516

1617
@Module({
1718
imports: [
18-
ConfigModule,
19+
AppConfigModule,
1920
TypeOrmModule.forFeature([Role, Menu, User, RefreshToken]),
2021
JwtModule.registerAsync({
21-
imports: [ConfigModule],
22-
useFactory: async (configService: ConfigService) => ({
23-
secret: configService.get<string>('JWT_SECRET'),
22+
imports: [AppConfigModule],
23+
useFactory: async (config: AppConfigService) => ({
24+
secret: config.jwtSecret,
2425
signOptions: { expiresIn: '24h' },
2526
}),
26-
inject: [ConfigService],
27+
inject: [AppConfigService],
2728
}),
2829
JwtCacheModule,
2930
MailModule,

backend/src/auth/auth.service.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
NotFoundException,
66
UnauthorizedException,
77
} from '@nestjs/common';
8-
import { ConfigService } from '@nestjs/config';
8+
import { AppConfigService } from 'src/config/config.service';
99
import { JwtService } from '@nestjs/jwt';
1010
import { InjectRepository } from '@nestjs/typeorm';
1111
import { LoginUserInput } from 'src/user/dto/login-user.input';
@@ -34,7 +34,7 @@ export class AuthService {
3434
private userRepository: Repository<User>,
3535
private jwtService: JwtService,
3636
private jwtCacheService: JwtCacheService,
37-
private configService: ConfigService,
37+
private configService: AppConfigService,
3838
private mailService: MailService,
3939
@InjectRepository(Menu)
4040
private menuRepository: Repository<Menu>,
@@ -43,10 +43,7 @@ export class AuthService {
4343
@InjectRepository(RefreshToken)
4444
private refreshTokenRepository: Repository<RefreshToken>,
4545
) {
46-
// Read the MAIL_ENABLED environment variable, default to 'true'
47-
this.isMailEnabled =
48-
this.configService.get<string>('MAIL_ENABLED', 'false').toLowerCase() ===
49-
'true';
46+
this.isMailEnabled = this.configService.isMailEnabled;
5047
}
5148

5249
async confirmEmail(token: string): Promise<EmailConfirmationResponse> {
@@ -220,7 +217,7 @@ export class AuthService {
220217
);
221218

222219
const refreshTokenEntity = await this.createRefreshToken(user);
223-
this.jwtCacheService.storeAccessToken(refreshTokenEntity.token);
220+
this.jwtCacheService.storeAccessToken(accessToken);
224221

225222
return {
226223
accessToken,

backend/src/chat/chat.controller.ts

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,6 @@ export class ChatController {
2222
@GetAuthToken() userId: string,
2323
) {
2424
try {
25-
// Save user's message first
26-
await this.chatService.saveMessage(
27-
chatDto.chatId,
28-
chatDto.message,
29-
MessageRole.User,
30-
);
31-
3225
if (chatDto.stream) {
3326
// Streaming response
3427
res.setHeader('Content-Type', 'text/event-stream');
@@ -39,6 +32,7 @@ export class ChatController {
3932
chatId: chatDto.chatId,
4033
message: chatDto.message,
4134
model: chatDto.model,
35+
role: MessageRole.User,
4236
});
4337

4438
let fullResponse = '';
@@ -51,13 +45,6 @@ export class ChatController {
5145
}
5246
}
5347

54-
// Save the complete message
55-
await this.chatService.saveMessage(
56-
chatDto.chatId,
57-
fullResponse,
58-
MessageRole.Assistant,
59-
);
60-
6148
res.write('data: [DONE]\n\n');
6249
res.end();
6350
} else {
@@ -66,15 +53,8 @@ export class ChatController {
6653
chatId: chatDto.chatId,
6754
message: chatDto.message,
6855
model: chatDto.model,
56+
role: MessageRole.User,
6957
});
70-
71-
// Save the complete message
72-
await this.chatService.saveMessage(
73-
chatDto.chatId,
74-
response,
75-
MessageRole.Assistant,
76-
);
77-
7858
res.json({ content: response });
7959
}
8060
} catch (error) {

backend/src/chat/chat.model.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ class ChatCompletionDelta {
7575

7676
@ObjectType('ChatCompletionChoiceType')
7777
class ChatCompletionChoice {
78-
@Field()
79-
index: number;
78+
@Field({ nullable: true })
79+
index: number | null;
8080

81-
@Field(() => ChatCompletionDelta)
82-
delta: ChatCompletionDelta;
81+
@Field(() => ChatCompletionDelta, { nullable: true })
82+
delta: ChatCompletionDelta | null;
8383

8484
@Field({ nullable: true })
8585
finishReason: string | null;
@@ -90,14 +90,14 @@ export class ChatCompletionChunk {
9090
@Field()
9191
id: string;
9292

93-
@Field()
94-
object: string;
93+
@Field({ nullable: true })
94+
object: string | null;
9595

96-
@Field()
97-
created: number;
96+
@Field({ nullable: true })
97+
created: number | null;
9898

99-
@Field()
100-
model: string;
99+
@Field({ nullable: true })
100+
model: string | null;
101101

102102
@Field({ nullable: true })
103103
systemFingerprint: string | null;

backend/src/chat/chat.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ import { UserService } from 'src/user/user.service';
1111
import { PubSub } from 'graphql-subscriptions';
1212
import { JwtCacheModule } from 'src/jwt-cache/jwt-cache.module';
1313
import { UploadModule } from 'src/upload/upload.module';
14+
import { GitHubModule } from 'src/github/github.module';
1415

1516
@Module({
1617
imports: [
1718
TypeOrmModule.forFeature([Chat, User]),
1819
AuthModule,
1920
JwtCacheModule,
2021
UploadModule,
22+
GitHubModule,
2123
],
2224
controllers: [ChatController],
2325
providers: [

0 commit comments

Comments
 (0)