@studious-lms/server 1.1.12 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/routers/_app.d.ts +34 -2
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/conversation.d.ts +4 -0
- package/dist/routers/conversation.d.ts.map +1 -1
- package/dist/routers/conversation.js +7 -0
- package/dist/routers/folder.d.ts +13 -0
- package/dist/routers/folder.d.ts.map +1 -1
- package/dist/routers/folder.js +20 -1
- package/dist/routers/labChat.d.ts +0 -1
- package/dist/routers/labChat.d.ts.map +1 -1
- package/dist/routers/labChat.js +251 -10
- package/dist/utils/aiUser.d.ts +13 -0
- package/dist/utils/aiUser.d.ts.map +1 -0
- package/dist/utils/aiUser.js +57 -0
- package/dist/utils/inference.d.ts +56 -0
- package/dist/utils/inference.d.ts.map +1 -0
- package/dist/utils/inference.js +135 -0
- package/package.json +2 -1
- package/src/routers/conversation.ts +7 -0
- package/src/routers/folder.ts +23 -0
- package/src/routers/labChat.ts +293 -10
- package/src/utils/aiUser.ts +65 -0
- package/src/utils/inference.ts +193 -0
package/dist/routers/_app.d.ts
CHANGED
|
@@ -3272,6 +3272,19 @@ export declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
3272
3272
|
};
|
|
3273
3273
|
meta: object;
|
|
3274
3274
|
}>;
|
|
3275
|
+
getParents: import("@trpc/server").TRPCQueryProcedure<{
|
|
3276
|
+
input: {
|
|
3277
|
+
folderId: string;
|
|
3278
|
+
};
|
|
3279
|
+
output: {
|
|
3280
|
+
id: string;
|
|
3281
|
+
name: string;
|
|
3282
|
+
color: string | null;
|
|
3283
|
+
classId: string | null;
|
|
3284
|
+
parentFolderId: string | null;
|
|
3285
|
+
}[];
|
|
3286
|
+
meta: object;
|
|
3287
|
+
}>;
|
|
3275
3288
|
}>>;
|
|
3276
3289
|
notification: import("@trpc/server").TRPCBuiltRouter<{
|
|
3277
3290
|
ctx: import("../trpc.js").Context;
|
|
@@ -3399,6 +3412,10 @@ export declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
3399
3412
|
name: string | null;
|
|
3400
3413
|
createdAt: Date;
|
|
3401
3414
|
updatedAt: Date;
|
|
3415
|
+
labChat: {
|
|
3416
|
+
id: string;
|
|
3417
|
+
title: string;
|
|
3418
|
+
} | null;
|
|
3402
3419
|
members: ({
|
|
3403
3420
|
user: {
|
|
3404
3421
|
id: string;
|
|
@@ -3837,7 +3854,6 @@ export declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
3837
3854
|
} | null;
|
|
3838
3855
|
};
|
|
3839
3856
|
mentionedUserIds: string[];
|
|
3840
|
-
labChatId: string;
|
|
3841
3857
|
};
|
|
3842
3858
|
meta: object;
|
|
3843
3859
|
}>;
|
|
@@ -7128,6 +7144,19 @@ export declare const createCaller: import("@trpc/server").TRPCRouterCaller<{
|
|
|
7128
7144
|
};
|
|
7129
7145
|
meta: object;
|
|
7130
7146
|
}>;
|
|
7147
|
+
getParents: import("@trpc/server").TRPCQueryProcedure<{
|
|
7148
|
+
input: {
|
|
7149
|
+
folderId: string;
|
|
7150
|
+
};
|
|
7151
|
+
output: {
|
|
7152
|
+
id: string;
|
|
7153
|
+
name: string;
|
|
7154
|
+
color: string | null;
|
|
7155
|
+
classId: string | null;
|
|
7156
|
+
parentFolderId: string | null;
|
|
7157
|
+
}[];
|
|
7158
|
+
meta: object;
|
|
7159
|
+
}>;
|
|
7131
7160
|
}>>;
|
|
7132
7161
|
notification: import("@trpc/server").TRPCBuiltRouter<{
|
|
7133
7162
|
ctx: import("../trpc.js").Context;
|
|
@@ -7255,6 +7284,10 @@ export declare const createCaller: import("@trpc/server").TRPCRouterCaller<{
|
|
|
7255
7284
|
name: string | null;
|
|
7256
7285
|
createdAt: Date;
|
|
7257
7286
|
updatedAt: Date;
|
|
7287
|
+
labChat: {
|
|
7288
|
+
id: string;
|
|
7289
|
+
title: string;
|
|
7290
|
+
} | null;
|
|
7258
7291
|
members: ({
|
|
7259
7292
|
user: {
|
|
7260
7293
|
id: string;
|
|
@@ -7693,7 +7726,6 @@ export declare const createCaller: import("@trpc/server").TRPCRouterCaller<{
|
|
|
7693
7726
|
} | null;
|
|
7694
7727
|
};
|
|
7695
7728
|
mentionedUserIds: string[];
|
|
7696
|
-
labChatId: string;
|
|
7697
7729
|
};
|
|
7698
7730
|
meta: object;
|
|
7699
7731
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_app.d.ts","sourceRoot":"","sources":["../../src/routers/_app.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAa1E,eAAO,MAAM,SAAS
|
|
1
|
+
{"version":3,"file":"_app.d.ts","sourceRoot":"","sources":["../../src/routers/_app.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAa1E,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgBpB,CAAC;AAGH,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC;AACzC,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;AACxD,MAAM,MAAM,aAAa,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;AAG1D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAiC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/routers/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/routers/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqS7B,CAAC"}
|
|
@@ -14,6 +14,12 @@ export const conversationRouter = createTRPCRouter({
|
|
|
14
14
|
},
|
|
15
15
|
},
|
|
16
16
|
include: {
|
|
17
|
+
labChat: {
|
|
18
|
+
select: {
|
|
19
|
+
id: true,
|
|
20
|
+
title: true,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
17
23
|
members: {
|
|
18
24
|
include: {
|
|
19
25
|
user: {
|
|
@@ -93,6 +99,7 @@ export const conversationRouter = createTRPCRouter({
|
|
|
93
99
|
name: conversation.name,
|
|
94
100
|
createdAt: conversation.createdAt,
|
|
95
101
|
updatedAt: conversation.updatedAt,
|
|
102
|
+
labChat: conversation.labChat,
|
|
96
103
|
members: conversation.members,
|
|
97
104
|
lastMessage: conversation.messages[0] || null,
|
|
98
105
|
unreadCount,
|
package/dist/routers/folder.d.ts
CHANGED
|
@@ -304,5 +304,18 @@ export declare const folderRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
304
304
|
};
|
|
305
305
|
meta: object;
|
|
306
306
|
}>;
|
|
307
|
+
getParents: import("@trpc/server").TRPCQueryProcedure<{
|
|
308
|
+
input: {
|
|
309
|
+
folderId: string;
|
|
310
|
+
};
|
|
311
|
+
output: {
|
|
312
|
+
id: string;
|
|
313
|
+
name: string;
|
|
314
|
+
color: string | null;
|
|
315
|
+
classId: string | null;
|
|
316
|
+
parentFolderId: string | null;
|
|
317
|
+
}[];
|
|
318
|
+
meta: object;
|
|
319
|
+
}>;
|
|
307
320
|
}>>;
|
|
308
321
|
//# sourceMappingURL=folder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"folder.d.ts","sourceRoot":"","sources":["../../src/routers/folder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"folder.d.ts","sourceRoot":"","sources":["../../src/routers/folder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA6BxB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0vBvB,CAAC"}
|
package/dist/routers/folder.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { createTRPCRouter, protectedClassMemberProcedure, protectedTeacherProcedure } from "../trpc.js";
|
|
2
|
+
import { createTRPCRouter, protectedProcedure, protectedClassMemberProcedure, protectedTeacherProcedure } from "../trpc.js";
|
|
3
3
|
import { TRPCError } from "@trpc/server";
|
|
4
4
|
import { prisma } from "../lib/prisma.js";
|
|
5
5
|
import { uploadFiles } from "../lib/fileUpload.js";
|
|
@@ -704,4 +704,23 @@ export const folderRouter = createTRPCRouter({
|
|
|
704
704
|
});
|
|
705
705
|
return updatedFolder;
|
|
706
706
|
}),
|
|
707
|
+
getParents: protectedProcedure
|
|
708
|
+
.input(z.object({
|
|
709
|
+
folderId: z.string(),
|
|
710
|
+
}))
|
|
711
|
+
.query(async ({ ctx, input }) => {
|
|
712
|
+
const { folderId } = input;
|
|
713
|
+
let currentParent = folderId;
|
|
714
|
+
const parents = [];
|
|
715
|
+
while (currentParent) {
|
|
716
|
+
const parent = await prisma.folder.findFirst({
|
|
717
|
+
where: {
|
|
718
|
+
id: currentParent,
|
|
719
|
+
},
|
|
720
|
+
});
|
|
721
|
+
currentParent = parent?.parentFolderId;
|
|
722
|
+
parents.push(parent);
|
|
723
|
+
}
|
|
724
|
+
return parents;
|
|
725
|
+
}),
|
|
707
726
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"labChat.d.ts","sourceRoot":"","sources":["../../src/routers/labChat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"labChat.d.ts","sourceRoot":"","sources":["../../src/routers/labChat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAcxB,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAonBxB,CAAC"}
|
package/dist/routers/labChat.js
CHANGED
|
@@ -3,6 +3,9 @@ import { createTRPCRouter, protectedProcedure } from '../trpc.js';
|
|
|
3
3
|
import { prisma } from '../lib/prisma.js';
|
|
4
4
|
import { pusher } from '../lib/pusher.js';
|
|
5
5
|
import { TRPCError } from '@trpc/server';
|
|
6
|
+
import { inferenceClient, sendAIMessage } from '../utils/inference.js';
|
|
7
|
+
import { logger } from '../utils/logger.js';
|
|
8
|
+
import { isAIUser } from '../utils/aiUser.js';
|
|
6
9
|
export const labChatRouter = createTRPCRouter({
|
|
7
10
|
create: protectedProcedure
|
|
8
11
|
.input(z.object({
|
|
@@ -76,13 +79,13 @@ export const labChatRouter = createTRPCRouter({
|
|
|
76
79
|
displayInChat: false, // Lab chats don't show in regular chat list
|
|
77
80
|
},
|
|
78
81
|
});
|
|
79
|
-
// Add
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
// Add only teachers to the conversation (this is for course material creation)
|
|
83
|
+
const teacherMembers = classWithTeachers.teachers.map(t => ({
|
|
84
|
+
userId: t.id,
|
|
85
|
+
role: 'ADMIN'
|
|
86
|
+
}));
|
|
84
87
|
await tx.conversationMember.createMany({
|
|
85
|
-
data:
|
|
88
|
+
data: teacherMembers.map(member => ({
|
|
86
89
|
userId: member.userId,
|
|
87
90
|
conversationId: conversation.id,
|
|
88
91
|
role: member.role,
|
|
@@ -141,6 +144,10 @@ export const labChatRouter = createTRPCRouter({
|
|
|
141
144
|
});
|
|
142
145
|
return labChat;
|
|
143
146
|
});
|
|
147
|
+
// Generate AI introduction message in parallel (don't await - fire and forget)
|
|
148
|
+
generateAndSendLabIntroduction(result.id, result.conversationId, context, classWithTeachers.subject || 'Lab').catch(error => {
|
|
149
|
+
logger.error('Failed to generate AI introduction:', { error, labChatId: result.id });
|
|
150
|
+
});
|
|
144
151
|
// Broadcast lab chat creation to class members
|
|
145
152
|
try {
|
|
146
153
|
await pusher.trigger(`class-${classId}`, 'lab-chat-created', {
|
|
@@ -163,7 +170,8 @@ export const labChatRouter = createTRPCRouter({
|
|
|
163
170
|
.query(async ({ input, ctx }) => {
|
|
164
171
|
const userId = ctx.user.id;
|
|
165
172
|
const { labChatId } = input;
|
|
166
|
-
|
|
173
|
+
// First, try to find the lab chat if user is already a member
|
|
174
|
+
let labChat = await prisma.labChat.findFirst({
|
|
167
175
|
where: {
|
|
168
176
|
id: labChatId,
|
|
169
177
|
conversation: {
|
|
@@ -216,6 +224,85 @@ export const labChatRouter = createTRPCRouter({
|
|
|
216
224
|
},
|
|
217
225
|
},
|
|
218
226
|
});
|
|
227
|
+
// If not found, check if user is a teacher in the class
|
|
228
|
+
if (!labChat) {
|
|
229
|
+
const labChatForTeacher = await prisma.labChat.findFirst({
|
|
230
|
+
where: {
|
|
231
|
+
id: labChatId,
|
|
232
|
+
class: {
|
|
233
|
+
teachers: {
|
|
234
|
+
some: {
|
|
235
|
+
id: userId,
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
include: {
|
|
241
|
+
conversation: {
|
|
242
|
+
select: {
|
|
243
|
+
id: true,
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
if (labChatForTeacher) {
|
|
249
|
+
// Add teacher to conversation
|
|
250
|
+
await prisma.conversationMember.create({
|
|
251
|
+
data: {
|
|
252
|
+
userId,
|
|
253
|
+
conversationId: labChatForTeacher.conversation.id,
|
|
254
|
+
role: 'ADMIN',
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
// Now fetch the full lab chat with the user as a member
|
|
258
|
+
labChat = await prisma.labChat.findFirst({
|
|
259
|
+
where: {
|
|
260
|
+
id: labChatId,
|
|
261
|
+
},
|
|
262
|
+
include: {
|
|
263
|
+
conversation: {
|
|
264
|
+
include: {
|
|
265
|
+
members: {
|
|
266
|
+
include: {
|
|
267
|
+
user: {
|
|
268
|
+
select: {
|
|
269
|
+
id: true,
|
|
270
|
+
username: true,
|
|
271
|
+
profile: {
|
|
272
|
+
select: {
|
|
273
|
+
displayName: true,
|
|
274
|
+
profilePicture: true,
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
createdBy: {
|
|
284
|
+
select: {
|
|
285
|
+
id: true,
|
|
286
|
+
username: true,
|
|
287
|
+
profile: {
|
|
288
|
+
select: {
|
|
289
|
+
displayName: true,
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
class: {
|
|
295
|
+
select: {
|
|
296
|
+
id: true,
|
|
297
|
+
name: true,
|
|
298
|
+
subject: true,
|
|
299
|
+
section: true,
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
219
306
|
if (!labChat) {
|
|
220
307
|
throw new TRPCError({
|
|
221
308
|
code: 'NOT_FOUND',
|
|
@@ -407,7 +494,7 @@ export const labChatRouter = createTRPCRouter({
|
|
|
407
494
|
});
|
|
408
495
|
return message;
|
|
409
496
|
});
|
|
410
|
-
// Broadcast to Pusher channel (
|
|
497
|
+
// Broadcast to Pusher channel (same format as regular chat)
|
|
411
498
|
try {
|
|
412
499
|
await pusher.trigger(`conversation-${labChat.conversationId}`, 'new-message', {
|
|
413
500
|
id: result.id,
|
|
@@ -417,13 +504,19 @@ export const labChatRouter = createTRPCRouter({
|
|
|
417
504
|
createdAt: result.createdAt,
|
|
418
505
|
sender: result.sender,
|
|
419
506
|
mentionedUserIds,
|
|
420
|
-
labChatId, // Include lab chat ID for frontend context
|
|
421
507
|
});
|
|
422
508
|
}
|
|
423
509
|
catch (error) {
|
|
424
510
|
console.error('Failed to broadcast lab chat message:', error);
|
|
425
511
|
// Don't fail the request if Pusher fails
|
|
426
512
|
}
|
|
513
|
+
// Generate AI response in parallel (don't await - fire and forget)
|
|
514
|
+
if (!isAIUser(userId)) {
|
|
515
|
+
// Run AI response generation in background
|
|
516
|
+
generateAndSendLabResponse(labChatId, content, labChat.conversationId).catch(error => {
|
|
517
|
+
logger.error('Failed to generate AI response:', { error });
|
|
518
|
+
});
|
|
519
|
+
}
|
|
427
520
|
return {
|
|
428
521
|
id: result.id,
|
|
429
522
|
content: result.content,
|
|
@@ -432,7 +525,6 @@ export const labChatRouter = createTRPCRouter({
|
|
|
432
525
|
createdAt: result.createdAt,
|
|
433
526
|
sender: result.sender,
|
|
434
527
|
mentionedUserIds,
|
|
435
|
-
labChatId,
|
|
436
528
|
};
|
|
437
529
|
}),
|
|
438
530
|
delete: protectedProcedure
|
|
@@ -498,3 +590,152 @@ export const labChatRouter = createTRPCRouter({
|
|
|
498
590
|
return { success: true };
|
|
499
591
|
}),
|
|
500
592
|
});
|
|
593
|
+
/**
|
|
594
|
+
* Generate and send AI introduction for lab chat
|
|
595
|
+
* Uses the stored context directly from database
|
|
596
|
+
*/
|
|
597
|
+
async function generateAndSendLabIntroduction(labChatId, conversationId, contextString, subject) {
|
|
598
|
+
try {
|
|
599
|
+
// Enhance the stored context with clarifying question instructions
|
|
600
|
+
const enhancedSystemPrompt = `${contextString}
|
|
601
|
+
|
|
602
|
+
IMPORTANT INSTRUCTIONS:
|
|
603
|
+
- You are helping teachers create course materials
|
|
604
|
+
- Use the context information provided above (subject, topic, difficulty, objectives, etc.) as your foundation
|
|
605
|
+
- Only ask clarifying questions about details NOT already specified in the context
|
|
606
|
+
- Focus your questions on format preferences, specific requirements, or missing details needed to create the content
|
|
607
|
+
- Only output final course materials when you have sufficient details beyond what's in the context
|
|
608
|
+
- Do not use markdown formatting in your responses - use plain text only
|
|
609
|
+
- When creating content, make it clear and well-structured without markdown`;
|
|
610
|
+
const completion = await inferenceClient.chat.completions.create({
|
|
611
|
+
model: 'command-a-03-2025',
|
|
612
|
+
messages: [
|
|
613
|
+
{ role: 'system', content: enhancedSystemPrompt },
|
|
614
|
+
{
|
|
615
|
+
role: 'user',
|
|
616
|
+
content: 'Please introduce yourself to the teaching team. Explain that you will help create course materials by first asking clarifying questions based on the context provided, and only output final content when you have enough information.'
|
|
617
|
+
},
|
|
618
|
+
],
|
|
619
|
+
max_tokens: 300,
|
|
620
|
+
temperature: 0.8,
|
|
621
|
+
});
|
|
622
|
+
const response = completion.choices[0]?.message?.content;
|
|
623
|
+
if (!response) {
|
|
624
|
+
throw new Error('No response generated from inference API');
|
|
625
|
+
}
|
|
626
|
+
// Send AI introduction using centralized sender
|
|
627
|
+
await sendAIMessage(response, conversationId, {
|
|
628
|
+
subject,
|
|
629
|
+
});
|
|
630
|
+
logger.info('AI Introduction sent', { labChatId, conversationId });
|
|
631
|
+
}
|
|
632
|
+
catch (error) {
|
|
633
|
+
logger.error('Failed to generate AI introduction:', { error, labChatId });
|
|
634
|
+
// Send fallback introduction
|
|
635
|
+
try {
|
|
636
|
+
const fallbackIntro = `Hello teaching team! I'm your AI assistant for course material development. I will help you create educational content by first asking clarifying questions based on the provided context, then outputting final materials when I have sufficient information. I won't use markdown formatting in my responses. What would you like to work on?`;
|
|
637
|
+
await sendAIMessage(fallbackIntro, conversationId, {
|
|
638
|
+
subject,
|
|
639
|
+
});
|
|
640
|
+
logger.info('Fallback AI introduction sent', { labChatId });
|
|
641
|
+
}
|
|
642
|
+
catch (fallbackError) {
|
|
643
|
+
logger.error('Failed to send fallback AI introduction:', { error: fallbackError, labChatId });
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Generate and send AI response to teacher message
|
|
649
|
+
* Uses the stored context directly from database
|
|
650
|
+
*/
|
|
651
|
+
async function generateAndSendLabResponse(labChatId, teacherMessage, conversationId) {
|
|
652
|
+
try {
|
|
653
|
+
// Get lab context from database
|
|
654
|
+
const fullLabChat = await prisma.labChat.findUnique({
|
|
655
|
+
where: { id: labChatId },
|
|
656
|
+
include: {
|
|
657
|
+
class: {
|
|
658
|
+
select: {
|
|
659
|
+
name: true,
|
|
660
|
+
subject: true,
|
|
661
|
+
},
|
|
662
|
+
},
|
|
663
|
+
},
|
|
664
|
+
});
|
|
665
|
+
if (!fullLabChat) {
|
|
666
|
+
throw new Error('Lab chat not found');
|
|
667
|
+
}
|
|
668
|
+
// Get recent conversation history
|
|
669
|
+
const recentMessages = await prisma.message.findMany({
|
|
670
|
+
where: {
|
|
671
|
+
conversationId,
|
|
672
|
+
},
|
|
673
|
+
include: {
|
|
674
|
+
sender: {
|
|
675
|
+
select: {
|
|
676
|
+
id: true,
|
|
677
|
+
username: true,
|
|
678
|
+
profile: {
|
|
679
|
+
select: {
|
|
680
|
+
displayName: true,
|
|
681
|
+
},
|
|
682
|
+
},
|
|
683
|
+
},
|
|
684
|
+
},
|
|
685
|
+
},
|
|
686
|
+
orderBy: {
|
|
687
|
+
createdAt: 'desc',
|
|
688
|
+
},
|
|
689
|
+
take: 10, // Last 10 messages for context
|
|
690
|
+
});
|
|
691
|
+
// Build conversation history as proper message objects
|
|
692
|
+
// Enhance the stored context with clarifying question instructions
|
|
693
|
+
const enhancedSystemPrompt = `${fullLabChat.context}
|
|
694
|
+
|
|
695
|
+
IMPORTANT INSTRUCTIONS:
|
|
696
|
+
- Use the context information provided above (subject, topic, difficulty, objectives, etc.) as your foundation
|
|
697
|
+
- Based on the teacher's input and existing context, only ask clarifying questions about details NOT already specified
|
|
698
|
+
- Focus questions on format preferences, specific requirements, quantity, or missing implementation details
|
|
699
|
+
- Only output final course materials when you have sufficient details beyond what's in the context
|
|
700
|
+
- Do not use markdown formatting in your responses - use plain text only
|
|
701
|
+
- When you do create content, make it clear and well-structured without markdown
|
|
702
|
+
- If the request is vague, ask 1-2 specific clarifying questions about missing details only`;
|
|
703
|
+
const messages = [
|
|
704
|
+
{ role: 'system', content: enhancedSystemPrompt },
|
|
705
|
+
];
|
|
706
|
+
// Add recent conversation history
|
|
707
|
+
recentMessages.reverse().forEach(msg => {
|
|
708
|
+
const role = isAIUser(msg.senderId) ? 'assistant' : 'user';
|
|
709
|
+
const senderName = msg.sender?.profile?.displayName || msg.sender?.username || 'Teacher';
|
|
710
|
+
const content = isAIUser(msg.senderId) ? msg.content : `${senderName}: ${msg.content}`;
|
|
711
|
+
messages.push({
|
|
712
|
+
role: role,
|
|
713
|
+
content,
|
|
714
|
+
});
|
|
715
|
+
});
|
|
716
|
+
// Add the new teacher message
|
|
717
|
+
const senderName = 'Teacher'; // We could get this from the actual sender if needed
|
|
718
|
+
messages.push({
|
|
719
|
+
role: 'user',
|
|
720
|
+
content: `${senderName}: ${teacherMessage}`,
|
|
721
|
+
});
|
|
722
|
+
const completion = await inferenceClient.chat.completions.create({
|
|
723
|
+
model: 'command-a-03-2025',
|
|
724
|
+
messages,
|
|
725
|
+
max_tokens: 500,
|
|
726
|
+
temperature: 0.7,
|
|
727
|
+
});
|
|
728
|
+
const response = completion.choices[0]?.message?.content;
|
|
729
|
+
if (!response) {
|
|
730
|
+
throw new Error('No response generated from inference API');
|
|
731
|
+
}
|
|
732
|
+
// Send AI response
|
|
733
|
+
await sendAIMessage(response, conversationId, {
|
|
734
|
+
subject: fullLabChat.class?.subject || 'Lab',
|
|
735
|
+
});
|
|
736
|
+
logger.info('AI response sent', { labChatId, conversationId });
|
|
737
|
+
}
|
|
738
|
+
catch (error) {
|
|
739
|
+
logger.error('Failed to generate AI response:', { error, labChatId });
|
|
740
|
+
}
|
|
741
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensure AI assistant user exists in the database
|
|
3
|
+
*/
|
|
4
|
+
export declare function ensureAIUserExists(): Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* Get the AI user ID
|
|
7
|
+
*/
|
|
8
|
+
export declare function getAIUserId(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Check if a user ID belongs to the AI assistant
|
|
11
|
+
*/
|
|
12
|
+
export declare function isAIUser(userId: string): boolean;
|
|
13
|
+
//# sourceMappingURL=aiUser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aiUser.d.ts","sourceRoot":"","sources":["../../src/utils/aiUser.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0CxD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhD"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { prisma } from '../lib/prisma.js';
|
|
2
|
+
import { logger } from './logger.js';
|
|
3
|
+
const AI_USER_ID = 'AI_ASSISTANT';
|
|
4
|
+
/**
|
|
5
|
+
* Ensure AI assistant user exists in the database
|
|
6
|
+
*/
|
|
7
|
+
export async function ensureAIUserExists() {
|
|
8
|
+
try {
|
|
9
|
+
// Check if AI user already exists
|
|
10
|
+
const existingAIUser = await prisma.user.findUnique({
|
|
11
|
+
where: { id: AI_USER_ID },
|
|
12
|
+
});
|
|
13
|
+
if (existingAIUser) {
|
|
14
|
+
return; // AI user already exists
|
|
15
|
+
}
|
|
16
|
+
// Create AI user
|
|
17
|
+
await prisma.user.create({
|
|
18
|
+
data: {
|
|
19
|
+
id: AI_USER_ID,
|
|
20
|
+
username: 'ai-assistant',
|
|
21
|
+
email: 'ai@studious-lms.com',
|
|
22
|
+
password: 'ai-system-user', // Not used for login
|
|
23
|
+
verified: true,
|
|
24
|
+
role: 'NONE', // Special role for AI
|
|
25
|
+
profile: {
|
|
26
|
+
create: {
|
|
27
|
+
displayName: 'AI Assistant',
|
|
28
|
+
bio: 'Intelligent assistant for lab chats and educational support',
|
|
29
|
+
profilePicture: null,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
logger.info('AI user created successfully', { userId: AI_USER_ID });
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
// If user already exists (race condition), that's okay
|
|
38
|
+
if (error instanceof Error && error.message.includes('unique constraint')) {
|
|
39
|
+
logger.info('AI user already exists (race condition handled)');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
logger.error('Failed to create AI user', { error });
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get the AI user ID
|
|
48
|
+
*/
|
|
49
|
+
export function getAIUserId() {
|
|
50
|
+
return AI_USER_ID;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Check if a user ID belongs to the AI assistant
|
|
54
|
+
*/
|
|
55
|
+
export function isAIUser(userId) {
|
|
56
|
+
return userId === AI_USER_ID;
|
|
57
|
+
}
|