Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit fa172bd

Browse files
Fix: AI conversation & LSN (#322)
* Fix: triage not opening * Fix: supertokens cookie domain * Fix: Change LSN calculation * Fix: AI agent syncing --------- Co-authored-by: Manoj K <saimanoj58@gmail.com>
1 parent 86a2cd0 commit fa172bd

File tree

20 files changed

+278
-141
lines changed

20 files changed

+278
-141
lines changed

actions/slack/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ export function convertSlackMessageToTiptapJson(
474474
content.push(
475475
...attachmentUrls.map((attachment) => ({
476476
type: attachment.fileType.startsWith('image/')
477-
? 'image'
477+
? 'imageExtension'
478478
: 'fileExtension',
479479
attrs: {
480480
src: attachment.publicURL,

apps/server/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
"ai": "^3.4.3",
8686
"axios": "^1.6.7",
8787
"bcrypt": "5.1.1",
88+
"body-parser": "^1.20.3",
8889
"bull": "^4.12.2",
8990
"cache-manager": "^5.7.6",
9091
"chalk": "^4.1.2",
@@ -117,7 +118,7 @@
117118
"rxjs": "7.8.1",
118119
"simple-oauth2": "^5.0.0",
119120
"socket.io": "^4.7.5",
120-
"supertokens-node": "^16.7.1",
121+
"supertokens-node": "^21.0.0",
121122
"turndown": "^7.2.0",
122123
"typesense": "^1.7.2",
123124
"uuid": "^10.0.0",
@@ -132,6 +133,7 @@
132133
"@tegonhq/eslint-config": "workspace:*",
133134
"@tegonhq/typescript-config": "workspace:*",
134135
"@types/bcrypt": "5.0.2",
136+
"@types/body-parser": "^1.19.5",
135137
"@types/chance": "1.1.6",
136138
"@types/cookie": "^0.6.0",
137139
"@types/express": "4.17.21",

apps/server/src/main.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { ValidationPipe, VersioningType } from '@nestjs/common';
22
import { ConfigService } from '@nestjs/config';
33
import { HttpAdapterHost, NestFactory } from '@nestjs/core';
4+
import * as bodyParser from 'body-parser';
45
import { PrismaClientExceptionFilter } from 'nestjs-prisma';
56
import supertokens from 'supertokens-node';
67

78
import type { CorsConfig } from 'common/configs/config.interface';
89

10+
import { SupertokensExceptionFilter } from 'modules/auth/auth.filter';
911
import { LoggerService } from 'modules/logger/logger.service';
1012
import ReplicationService from 'modules/replication/replication.service';
1113
import { TriggerdevService } from 'modules/triggerdev/triggerdev.service';
@@ -25,6 +27,8 @@ async function bootstrap() {
2527
// Validation
2628
app.useGlobalPipes(new ValidationPipe({}));
2729

30+
app.use(bodyParser.json({ limit: '50mb' })); // Adjust limit as required
31+
2832
// Initiate replication service
2933
const replicationService = app.get(ReplicationService);
3034
replicationService.init();
@@ -38,7 +42,10 @@ async function bootstrap() {
3842

3943
// Prisma Client Exception Filter for unhandled exceptions
4044
const { httpAdapter } = app.get(HttpAdapterHost);
41-
app.useGlobalFilters(new PrismaClientExceptionFilter(httpAdapter));
45+
app.useGlobalFilters(
46+
new PrismaClientExceptionFilter(httpAdapter),
47+
new SupertokensExceptionFilter(),
48+
);
4249

4350
const configService = app.get(ConfigService);
4451
const corsConfig = configService.get<CorsConfig>('cors');

apps/server/src/modules/auth/supertokens/supertokens.config.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { MailerService } from '@nestjs-modules/mailer';
2-
import jwt from 'supertokens-node/lib/build/recipe/jwt';
32
import { TypePasswordlessEmailDeliveryInput } from 'supertokens-node/lib/build/recipe/passwordless/types';
3+
import jwt from 'supertokens-node/recipe/jwt';
44
import Passwordless from 'supertokens-node/recipe/passwordless';
55
import Session from 'supertokens-node/recipe/session';
66
import UserRoles from 'supertokens-node/recipe/userroles';
@@ -27,11 +27,16 @@ export const recipeList = (
2727
usersService: UsersService,
2828
mailerService: MailerService,
2929
) => {
30+
const isProd = process.env.NODE_ENV === 'production';
31+
const cookieSettings = isProd
32+
? { cookieDomain: '.tegon.ai', olderCookieDomain: '', cookieSecure: true }
33+
: {};
34+
3035
return [
3136
jwt.init(),
3237
UserRoles.init(),
3338
Session.init({
34-
cookieSecure: true,
39+
...cookieSettings,
3540
override: {
3641
functions(originalImplementation) {
3742
return {

apps/server/src/modules/issues/issues.interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export const filterKeyReplacers: Record<FilterKey, string> = {
7272
[FilterKeyEnum.dueDate]: 'dueDate',
7373
[FilterKeyEnum.createdAt]: 'createdAt',
7474
[FilterKeyEnum.updatedAt]: 'updatedAt',
75+
[FilterKeyEnum.project]: 'projectId',
7576
[BooleanFilterKeyEnum.isParent]: 'parent',
7677
[BooleanFilterKeyEnum.isSubIssue]: 'subIssue',
7778
[BooleanFilterKeyEnum.isBlocked]: IssueRelationType.BLOCKED,

apps/server/src/modules/projects/projects.controller.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Delete,
55
Param,
66
Post,
7+
Get,
78
UseGuards,
89
} from '@nestjs/common';
910
import {
@@ -27,6 +28,12 @@ import { ProjectsService } from './projects.service';
2728
export class ProjectsController {
2829
constructor(private projects: ProjectsService) {}
2930

31+
@Get()
32+
@UseGuards(AuthGuard)
33+
async getProjects(@Workspace() workspace: string) {
34+
return await this.projects.getProjects(workspace);
35+
}
36+
3037
@Post()
3138
@UseGuards(AuthGuard)
3239
async createProject(

apps/server/src/modules/projects/projects.service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ export class ProjectsService {
1616
private issuesService: IssuesService,
1717
) {}
1818

19+
async getProjects(workspaceId: string) {
20+
return await this.prisma.project.findMany({
21+
where: {
22+
workspaceId,
23+
},
24+
});
25+
}
26+
1927
async createProject(createProjectDto: CreateProjectDto, workspaceId: string) {
2028
return await this.prisma.project.create({
2129
data: {

apps/server/src/modules/replication/replication.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ export default class ReplicationService {
254254
ModelNameEnum.Conversation,
255255
ModelNameEnum.ConversationHistory,
256256
].includes(modelName)
257-
? syncActionData.data.userId
257+
? (syncActionData.data.recipientId ?? syncActionData.data.userId)
258258
: syncActionData.workspaceId;
259259

260260
this.syncGateway.wss

apps/server/src/modules/sync-actions/sync-actions.utils.ts

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,16 @@ export function convertToActionType(action: string): SyncActionTypeEnum {
1515
}
1616

1717
export function convertLsnToInt(lsn: string) {
18+
// Convert timestamp to milliseconds since epoch
19+
const timestampMs = new Date().getTime();
20+
21+
// Use LSN as a secondary sort key for events in the same millisecond
1822
const [logFileNumber, byteOffset] = lsn.split('/');
19-
const hexString = logFileNumber + byteOffset;
20-
return parseInt(hexString, 16);
23+
const lsnValue = parseInt(logFileNumber + byteOffset, 16);
24+
25+
// Combine timestamp and LSN
26+
// Multiply timestamp by 1000 to leave room for LSN as sub-millisecond ordering
27+
return BigInt(timestampMs) * 1000n + BigInt(lsnValue % 1000);
2128
}
2229

2330
export async function getWorkspaceId(
@@ -197,20 +204,40 @@ export async function getModelData(
197204
},
198205
},
199206
ConversationHistory: {
200-
findUnique: () => {
207+
findUnique: async () => {
201208
if (userId) {
202-
return prisma.conversationHistory.findFirst({
203-
where: {
204-
id: modelId,
205-
conversation: {
206-
userId,
209+
const conversationHistory =
210+
await prisma.conversationHistory.findFirst({
211+
where: {
212+
id: modelId,
213+
conversation: {
214+
userId,
215+
},
207216
},
208-
},
209-
});
217+
include: {
218+
conversation: true,
219+
},
220+
});
221+
222+
return {
223+
...conversationHistory,
224+
recipientId: conversationHistory.conversation.userId,
225+
};
210226
}
211-
return prisma.conversationHistory.findUnique({
212-
where: { id: modelId },
213-
});
227+
228+
const conversationHistory = await prisma.conversationHistory.findUnique(
229+
{
230+
where: { id: modelId },
231+
include: {
232+
conversation: true,
233+
},
234+
},
235+
);
236+
237+
return {
238+
...conversationHistory,
239+
recipientId: conversationHistory.conversation.userId,
240+
};
214241
},
215242
},
216243
Cycle: prisma.cycle,

apps/server/src/modules/sync/sync.gateway.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class SyncGateway implements OnGatewayInit, OnGatewayConnection {
3737
});
3838

3939
const { query, headers } = client.handshake;
40-
const isValid = isValidAuthentication(headers);
40+
const isValid = await isValidAuthentication(headers);
4141

4242
if (!isValid) {
4343
this.logger.info({

0 commit comments

Comments
 (0)