@goscribe/server 1.0.8 → 1.0.9

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.
Files changed (57) hide show
  1. package/AUTH_FRONTEND_SPEC.md +21 -0
  2. package/CHAT_FRONTEND_SPEC.md +474 -0
  3. package/MEETINGSUMMARY_FRONTEND_SPEC.md +28 -0
  4. package/PODCAST_FRONTEND_SPEC.md +595 -0
  5. package/STUDYGUIDE_FRONTEND_SPEC.md +18 -0
  6. package/WORKSHEETS_FRONTEND_SPEC.md +26 -0
  7. package/WORKSPACE_FRONTEND_SPEC.md +47 -0
  8. package/dist/lib/ai-session.d.ts +26 -0
  9. package/dist/lib/ai-session.js +343 -0
  10. package/dist/lib/inference.d.ts +2 -0
  11. package/dist/lib/inference.js +21 -0
  12. package/dist/lib/pusher.d.ts +14 -0
  13. package/dist/lib/pusher.js +94 -0
  14. package/dist/lib/storage.d.ts +10 -2
  15. package/dist/lib/storage.js +63 -6
  16. package/dist/routers/_app.d.ts +840 -58
  17. package/dist/routers/_app.js +6 -0
  18. package/dist/routers/ai-session.d.ts +0 -0
  19. package/dist/routers/ai-session.js +1 -0
  20. package/dist/routers/auth.d.ts +1 -0
  21. package/dist/routers/auth.js +6 -4
  22. package/dist/routers/chat.d.ts +171 -0
  23. package/dist/routers/chat.js +270 -0
  24. package/dist/routers/flashcards.d.ts +37 -0
  25. package/dist/routers/flashcards.js +128 -0
  26. package/dist/routers/meetingsummary.d.ts +0 -0
  27. package/dist/routers/meetingsummary.js +377 -0
  28. package/dist/routers/podcast.d.ts +277 -0
  29. package/dist/routers/podcast.js +847 -0
  30. package/dist/routers/studyguide.d.ts +54 -0
  31. package/dist/routers/studyguide.js +125 -0
  32. package/dist/routers/worksheets.d.ts +138 -51
  33. package/dist/routers/worksheets.js +317 -7
  34. package/dist/routers/workspace.d.ts +162 -7
  35. package/dist/routers/workspace.js +440 -8
  36. package/dist/server.js +6 -2
  37. package/package.json +11 -4
  38. package/prisma/migrations/20250826124819_add_worksheet_difficulty_and_estimated_time/migration.sql +213 -0
  39. package/prisma/migrations/20250826133236_add_worksheet_question_progress/migration.sql +31 -0
  40. package/prisma/migrations/migration_lock.toml +3 -0
  41. package/prisma/schema.prisma +87 -6
  42. package/prisma/seed.mjs +135 -0
  43. package/src/lib/ai-session.ts +411 -0
  44. package/src/lib/inference.ts +21 -0
  45. package/src/lib/pusher.ts +104 -0
  46. package/src/lib/storage.ts +89 -6
  47. package/src/routers/_app.ts +6 -0
  48. package/src/routers/auth.ts +8 -4
  49. package/src/routers/chat.ts +275 -0
  50. package/src/routers/flashcards.ts +142 -0
  51. package/src/routers/meetingsummary.ts +416 -0
  52. package/src/routers/podcast.ts +934 -0
  53. package/src/routers/studyguide.ts +144 -0
  54. package/src/routers/worksheets.ts +336 -7
  55. package/src/routers/workspace.ts +487 -8
  56. package/src/server.ts +7 -2
  57. package/test-ai-integration.js +134 -0
@@ -0,0 +1,377 @@
1
+ "use strict";
2
+ // import { z } from 'zod';
3
+ // import { TRPCError } from '@trpc/server';
4
+ // import { router, authedProcedure } from '../trpc.js';
5
+ // import OpenAI from 'openai';
6
+ // import fs from 'fs';
7
+ // import path from 'path';
8
+ // import { v4 as uuidv4 } from 'uuid';
9
+ // // Prisma enum values mapped manually to avoid type import issues in ESM
10
+ // const ArtifactType = {
11
+ // STUDY_GUIDE: 'STUDY_GUIDE',
12
+ // FLASHCARD_SET: 'FLASHCARD_SET',
13
+ // WORKSHEET: 'WORKSHEET',
14
+ // MEETING_SUMMARY: 'MEETING_SUMMARY',
15
+ // PODCAST_EPISODE: 'PODCAST_EPISODE',
16
+ // } as const;
17
+ // // Initialize OpenAI client
18
+ // const openai = new OpenAI({
19
+ // apiKey: process.env.OPENAI_API_KEY,
20
+ // });
21
+ // // Meeting summary schema for structured data
22
+ // const meetingSchema = z.object({
23
+ // title: z.string(),
24
+ // participants: z.array(z.string()),
25
+ // date: z.string(),
26
+ // duration: z.string().optional(),
27
+ // agenda: z.array(z.string()).optional(),
28
+ // transcript: z.string().optional(),
29
+ // notes: z.string().optional(),
30
+ // });
31
+ // export const meetingSummarize = router({
32
+ // // List all meeting summaries for a workspace
33
+ // listSummaries: authedProcedure
34
+ // .input(z.object({ workspaceId: z.string() }))
35
+ // .query(async ({ ctx, input }) => {
36
+ // const workspace = await ctx.db.workspace.findFirst({
37
+ // where: { id: input.workspaceId, ownerId: ctx.session.user.id },
38
+ // });
39
+ // if (!workspace) throw new TRPCError({ code: 'NOT_FOUND' });
40
+ // return ctx.db.artifact.findMany({
41
+ // where: {
42
+ // workspaceId: input.workspaceId,
43
+ // type: ArtifactType.MEETING_SUMMARY
44
+ // },
45
+ // include: {
46
+ // versions: {
47
+ // orderBy: { version: 'desc' },
48
+ // take: 1, // Get only the latest version
49
+ // },
50
+ // },
51
+ // orderBy: { updatedAt: 'desc' },
52
+ // });
53
+ // }),
54
+ // // Get a specific meeting summary
55
+ // getSummary: authedProcedure
56
+ // .input(z.object({ summaryId: z.string() }))
57
+ // .query(async ({ ctx, input }) => {
58
+ // const summary = await ctx.db.artifact.findFirst({
59
+ // where: {
60
+ // id: input.summaryId,
61
+ // type: ArtifactType.MEETING_SUMMARY,
62
+ // workspace: { ownerId: ctx.session.user.id }
63
+ // },
64
+ // include: {
65
+ // versions: {
66
+ // orderBy: { version: 'desc' },
67
+ // take: 1,
68
+ // },
69
+ // },
70
+ // });
71
+ // if (!summary) throw new TRPCError({ code: 'NOT_FOUND' });
72
+ // return summary;
73
+ // }),
74
+ // // Upload and process audio/video file
75
+ // uploadFile: authedProcedure
76
+ // .input(z.object({
77
+ // workspaceId: z.string(),
78
+ // fileName: z.string(),
79
+ // fileBuffer: z.string(), // Base64 encoded file
80
+ // mimeType: z.string(),
81
+ // title: z.string().optional(),
82
+ // }))
83
+ // .mutation(async ({ ctx, input }) => {
84
+ // const workspace = await ctx.db.workspace.findFirst({
85
+ // where: { id: input.workspaceId, ownerId: ctx.session.user.id },
86
+ // });
87
+ // if (!workspace) throw new TRPCError({ code: 'NOT_FOUND' });
88
+ // // Validate file type
89
+ // const allowedTypes = ['audio/mpeg', 'audio/mp3', 'video/mp4', 'audio/wav', 'audio/m4a'];
90
+ // if (!allowedTypes.includes(input.mimeType)) {
91
+ // throw new TRPCError({
92
+ // code: 'BAD_REQUEST',
93
+ // message: 'Unsupported file type. Please upload MP3, MP4, WAV, or M4A files.'
94
+ // });
95
+ // }
96
+ // try {
97
+ // // Create temporary file
98
+ // const tempDir = path.join(process.cwd(), 'temp');
99
+ // if (!fs.existsSync(tempDir)) {
100
+ // fs.mkdirSync(tempDir, { recursive: true });
101
+ // }
102
+ // const fileId = uuidv4();
103
+ // const fileExtension = path.extname(input.fileName);
104
+ // const tempFilePath = path.join(tempDir, `${fileId}${fileExtension}`);
105
+ // // Write buffer to temporary file
106
+ // const fileBuffer = Buffer.from(input.fileBuffer, 'base64');
107
+ // fs.writeFileSync(tempFilePath, fileBuffer);
108
+ // // Transcribe audio using OpenAI Whisper
109
+ // const transcript = await openai.audio.transcriptions.create({
110
+ // file: fs.createReadStream(tempFilePath),
111
+ // model: 'whisper-1',
112
+ // response_format: 'text',
113
+ // });
114
+ // // Generate meeting summary using GPT
115
+ // const summaryResponse = await openai.chat.completions.create({
116
+ // model: 'gpt-4-turbo-preview',
117
+ // messages: [
118
+ // {
119
+ // role: 'system',
120
+ // content: `You are a meeting summarizer. Given a meeting transcript, create a comprehensive summary that includes:
121
+ // 1. Meeting title/topic
122
+ // 2. Key participants mentioned
123
+ // 3. Main discussion points
124
+ // 4. Action items
125
+ // 5. Decisions made
126
+ // 6. Next steps
127
+ // Format the response as JSON with the following structure:
128
+ // {
129
+ // "title": "Meeting title",
130
+ // "participants": ["participant1", "participant2"],
131
+ // "keyPoints": ["point1", "point2"],
132
+ // "actionItems": ["action1", "action2"],
133
+ // "decisions": ["decision1", "decision2"],
134
+ // "nextSteps": ["step1", "step2"],
135
+ // "summary": "Overall meeting summary"
136
+ // }`
137
+ // },
138
+ // {
139
+ // role: 'user',
140
+ // content: `Please summarize this meeting transcript: ${transcript}`
141
+ // }
142
+ // ],
143
+ // });
144
+ // let summaryData;
145
+ // try {
146
+ // summaryData = JSON.parse(summaryResponse.choices[0]?.message?.content || '{}');
147
+ // } catch (parseError) {
148
+ // // Fallback if JSON parsing fails
149
+ // summaryData = {
150
+ // title: input.title || 'Meeting Summary',
151
+ // participants: [],
152
+ // keyPoints: [],
153
+ // actionItems: [],
154
+ // decisions: [],
155
+ // nextSteps: [],
156
+ // summary: summaryResponse.choices[0]?.message?.content || 'Unable to generate summary'
157
+ // };
158
+ // }
159
+ // // Create artifact in database
160
+ // const artifact = await ctx.db.artifact.create({
161
+ // data: {
162
+ // workspaceId: input.workspaceId,
163
+ // type: ArtifactType.MEETING_SUMMARY,
164
+ // title: summaryData.title || input.title || 'Meeting Summary',
165
+ // content: JSON.stringify({
166
+ // originalFileName: input.fileName,
167
+ // transcript: transcript,
168
+ // ...summaryData
169
+ // }),
170
+ // },
171
+ // });
172
+ // // Create initial version
173
+ // await ctx.db.artifactVersion.create({
174
+ // data: {
175
+ // artifactId: artifact.id,
176
+ // version: 1,
177
+ // content: artifact.content,
178
+ // },
179
+ // });
180
+ // // Clean up temporary file
181
+ // fs.unlinkSync(tempFilePath);
182
+ // return {
183
+ // id: artifact.id,
184
+ // title: artifact.title,
185
+ // summary: summaryData,
186
+ // transcript: transcript,
187
+ // };
188
+ // } catch (error) {
189
+ // console.error('Error processing meeting file:', error);
190
+ // throw new TRPCError({
191
+ // code: 'INTERNAL_SERVER_ERROR',
192
+ // message: 'Failed to process meeting file'
193
+ // });
194
+ // }
195
+ // }),
196
+ // // Process meeting data from schema
197
+ // processSchema: authedProcedure
198
+ // .input(z.object({
199
+ // workspaceId: z.string(),
200
+ // meetingData: meetingSchema,
201
+ // }))
202
+ // .mutation(async ({ ctx, input }) => {
203
+ // const workspace = await ctx.db.workspace.findFirst({
204
+ // where: { id: input.workspaceId, ownerId: ctx.session.user.id },
205
+ // });
206
+ // if (!workspace) throw new TRPCError({ code: 'NOT_FOUND' });
207
+ // try {
208
+ // // Create content for AI processing
209
+ // const meetingContent = `
210
+ // Meeting Title: ${input.meetingData.title}
211
+ // Participants: ${input.meetingData.participants.join(', ')}
212
+ // Date: ${input.meetingData.date}
213
+ // Duration: ${input.meetingData.duration || 'Not specified'}
214
+ // Agenda: ${input.meetingData.agenda?.join(', ') || 'Not provided'}
215
+ // Notes: ${input.meetingData.notes || 'Not provided'}
216
+ // Transcript: ${input.meetingData.transcript || 'Not provided'}
217
+ // `;
218
+ // // Generate enhanced summary using GPT
219
+ // const summaryResponse = await openai.chat.completions.create({
220
+ // model: 'gpt-4-turbo-preview',
221
+ // messages: [
222
+ // {
223
+ // role: 'system',
224
+ // content: `You are a meeting summarizer. Given meeting information, create a comprehensive summary that includes:
225
+ // 1. Key discussion points
226
+ // 2. Action items
227
+ // 3. Decisions made
228
+ // 4. Next steps
229
+ // 5. Important insights
230
+ // Format the response as JSON with the following structure:
231
+ // {
232
+ // "keyPoints": ["point1", "point2"],
233
+ // "actionItems": ["action1", "action2"],
234
+ // "decisions": ["decision1", "decision2"],
235
+ // "nextSteps": ["step1", "step2"],
236
+ // "insights": ["insight1", "insight2"],
237
+ // "summary": "Overall meeting summary"
238
+ // }`
239
+ // },
240
+ // {
241
+ // role: 'user',
242
+ // content: `Please analyze and summarize this meeting information: ${meetingContent}`
243
+ // }
244
+ // ],
245
+ // });
246
+ // let summaryData;
247
+ // try {
248
+ // summaryData = JSON.parse(summaryResponse.choices[0]?.message?.content || '{}');
249
+ // } catch (parseError) {
250
+ // // Fallback if JSON parsing fails
251
+ // summaryData = {
252
+ // keyPoints: [],
253
+ // actionItems: [],
254
+ // decisions: [],
255
+ // nextSteps: [],
256
+ // insights: [],
257
+ // summary: summaryResponse.choices[0]?.message?.content || 'Unable to generate summary'
258
+ // };
259
+ // }
260
+ // // Create artifact in database
261
+ // const artifact = await ctx.db.artifact.create({
262
+ // data: {
263
+ // workspaceId: input.workspaceId,
264
+ // type: ArtifactType.MEETING_SUMMARY,
265
+ // title: input.meetingData.title,
266
+ // content: JSON.stringify({
267
+ // originalData: input.meetingData,
268
+ // ...summaryData
269
+ // }),
270
+ // },
271
+ // });
272
+ // // Create initial version
273
+ // await ctx.db.artifactVersion.create({
274
+ // data: {
275
+ // artifactId: artifact.id,
276
+ // version: 1,
277
+ // content: artifact.content,
278
+ // },
279
+ // });
280
+ // return {
281
+ // id: artifact.id,
282
+ // title: artifact.title,
283
+ // summary: summaryData,
284
+ // originalData: input.meetingData,
285
+ // };
286
+ // } catch (error) {
287
+ // console.error('Error processing meeting schema:', error);
288
+ // throw new TRPCError({
289
+ // code: 'INTERNAL_SERVER_ERROR',
290
+ // message: 'Failed to process meeting data'
291
+ // });
292
+ // }
293
+ // }),
294
+ // // Update an existing meeting summary
295
+ // updateSummary: authedProcedure
296
+ // .input(z.object({
297
+ // summaryId: z.string(),
298
+ // title: z.string().optional(),
299
+ // content: z.string().optional(),
300
+ // }))
301
+ // .mutation(async ({ ctx, input }) => {
302
+ // const summary = await ctx.db.artifact.findFirst({
303
+ // where: {
304
+ // id: input.summaryId,
305
+ // type: ArtifactType.MEETING_SUMMARY,
306
+ // workspace: { ownerId: ctx.session.user.id }
307
+ // },
308
+ // include: {
309
+ // versions: {
310
+ // orderBy: { version: 'desc' },
311
+ // take: 1,
312
+ // },
313
+ // },
314
+ // });
315
+ // if (!summary) throw new TRPCError({ code: 'NOT_FOUND' });
316
+ // // Update artifact
317
+ // const updatedArtifact = await ctx.db.artifact.update({
318
+ // where: { id: input.summaryId },
319
+ // data: {
320
+ // title: input.title ?? summary.title,
321
+ // content: input.content ?? summary.content,
322
+ // updatedAt: new Date(),
323
+ // },
324
+ // });
325
+ // // Create new version if content changed
326
+ // if (input.content && input.content !== summary.content) {
327
+ // const latestVersion = summary.versions[0]?.version || 0;
328
+ // await ctx.db.artifactVersion.create({
329
+ // data: {
330
+ // artifactId: input.summaryId,
331
+ // version: latestVersion + 1,
332
+ // content: input.content,
333
+ // },
334
+ // });
335
+ // }
336
+ // return updatedArtifact;
337
+ // }),
338
+ // // Delete a meeting summary
339
+ // deleteSummary: authedProcedure
340
+ // .input(z.object({ summaryId: z.string() }))
341
+ // .mutation(async ({ ctx, input }) => {
342
+ // const summary = await ctx.db.artifact.findFirst({
343
+ // where: {
344
+ // id: input.summaryId,
345
+ // type: ArtifactType.MEETING_SUMMARY,
346
+ // workspace: { ownerId: ctx.session.user.id }
347
+ // },
348
+ // });
349
+ // if (!summary) throw new TRPCError({ code: 'NOT_FOUND' });
350
+ // // Delete associated versions first
351
+ // await ctx.db.artifactVersion.deleteMany({
352
+ // where: { artifactId: input.summaryId },
353
+ // });
354
+ // // Delete the artifact
355
+ // await ctx.db.artifact.delete({
356
+ // where: { id: input.summaryId },
357
+ // });
358
+ // return true;
359
+ // }),
360
+ // // Get meeting versions/history
361
+ // getVersions: authedProcedure
362
+ // .input(z.object({ summaryId: z.string() }))
363
+ // .query(async ({ ctx, input }) => {
364
+ // const summary = await ctx.db.artifact.findFirst({
365
+ // where: {
366
+ // id: input.summaryId,
367
+ // type: ArtifactType.MEETING_SUMMARY,
368
+ // workspace: { ownerId: ctx.session.user.id }
369
+ // },
370
+ // });
371
+ // if (!summary) throw new TRPCError({ code: 'NOT_FOUND' });
372
+ // return ctx.db.artifactVersion.findMany({
373
+ // where: { artifactId: input.summaryId },
374
+ // orderBy: { version: 'desc' },
375
+ // });
376
+ // }),
377
+ // });
@@ -0,0 +1,277 @@
1
+ export declare const podcast: import("@trpc/server").TRPCBuiltRouter<{
2
+ ctx: {
3
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
4
+ session: any;
5
+ req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
6
+ res: import("express").Response<any, Record<string, any>>;
7
+ cookies: Record<string, string | undefined>;
8
+ };
9
+ meta: object;
10
+ errorShape: import("@trpc/server").TRPCDefaultErrorShape;
11
+ transformer: true;
12
+ }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
13
+ listEpisodes: import("@trpc/server").TRPCQueryProcedure<{
14
+ input: {
15
+ workspaceId: string;
16
+ };
17
+ output: ({
18
+ id: string;
19
+ title: string;
20
+ description: string | null;
21
+ metadata: null;
22
+ segments: never[];
23
+ createdAt: Date;
24
+ updatedAt: Date;
25
+ workspaceId: string;
26
+ type: import("@prisma/client").$Enums.ArtifactType;
27
+ createdById: string | null;
28
+ isArchived: boolean;
29
+ } | {
30
+ id: string;
31
+ title: string;
32
+ description: string | undefined;
33
+ metadata: {
34
+ title: string;
35
+ totalDuration: number;
36
+ voice: string;
37
+ speed: number;
38
+ segments: {
39
+ id: string;
40
+ title: string;
41
+ content: string;
42
+ startTime: number;
43
+ duration: number;
44
+ keyPoints: string[];
45
+ order: number;
46
+ audioUrl?: string | undefined;
47
+ objectKey?: string | undefined;
48
+ }[];
49
+ summary: {
50
+ executiveSummary: string;
51
+ learningObjectives: string[];
52
+ keyConcepts: string[];
53
+ followUpActions: string[];
54
+ targetAudience: string;
55
+ prerequisites: string[];
56
+ tags: string[];
57
+ };
58
+ generatedAt: string;
59
+ description?: string | undefined;
60
+ };
61
+ segments: ({
62
+ id: string;
63
+ title: string;
64
+ audioUrl: string;
65
+ objectKey: string;
66
+ startTime: number;
67
+ duration: number;
68
+ order: number;
69
+ } | {
70
+ id: string;
71
+ title: string;
72
+ audioUrl: null;
73
+ objectKey: string | undefined;
74
+ startTime: number;
75
+ duration: number;
76
+ order: number;
77
+ })[];
78
+ createdAt: Date;
79
+ updatedAt: Date;
80
+ workspaceId: string;
81
+ type: import("@prisma/client").$Enums.ArtifactType;
82
+ createdById: string | null;
83
+ isArchived: boolean;
84
+ })[];
85
+ meta: object;
86
+ }>;
87
+ getEpisode: import("@trpc/server").TRPCQueryProcedure<{
88
+ input: {
89
+ episodeId: string;
90
+ };
91
+ output: {
92
+ id: string;
93
+ title: string;
94
+ description: string | undefined;
95
+ metadata: {
96
+ title: string;
97
+ totalDuration: number;
98
+ voice: string;
99
+ speed: number;
100
+ segments: {
101
+ id: string;
102
+ title: string;
103
+ content: string;
104
+ startTime: number;
105
+ duration: number;
106
+ keyPoints: string[];
107
+ order: number;
108
+ audioUrl?: string | undefined;
109
+ objectKey?: string | undefined;
110
+ }[];
111
+ summary: {
112
+ executiveSummary: string;
113
+ learningObjectives: string[];
114
+ keyConcepts: string[];
115
+ followUpActions: string[];
116
+ targetAudience: string;
117
+ prerequisites: string[];
118
+ tags: string[];
119
+ };
120
+ generatedAt: string;
121
+ description?: string | undefined;
122
+ };
123
+ segments: ({
124
+ id: string;
125
+ title: string;
126
+ content: string;
127
+ audioUrl: string;
128
+ objectKey: string;
129
+ startTime: number;
130
+ duration: number;
131
+ keyPoints: string[];
132
+ order: number;
133
+ } | {
134
+ id: string;
135
+ title: string;
136
+ content: string;
137
+ audioUrl: null;
138
+ objectKey: string | undefined;
139
+ startTime: number;
140
+ duration: number;
141
+ keyPoints: string[];
142
+ order: number;
143
+ })[];
144
+ content: string;
145
+ createdAt: Date;
146
+ updatedAt: Date;
147
+ };
148
+ meta: object;
149
+ }>;
150
+ generateEpisode: import("@trpc/server").TRPCMutationProcedure<{
151
+ input: {
152
+ workspaceId: string;
153
+ podcastData: {
154
+ title: string;
155
+ userPrompt: string;
156
+ description?: string | undefined;
157
+ voice?: "alloy" | "echo" | "fable" | "onyx" | "nova" | "shimmer" | undefined;
158
+ speed?: number | undefined;
159
+ generateIntro?: boolean | undefined;
160
+ generateOutro?: boolean | undefined;
161
+ segmentByTopics?: boolean | undefined;
162
+ };
163
+ };
164
+ output: {
165
+ id: string;
166
+ title: any;
167
+ description: string | undefined;
168
+ metadata: {
169
+ title: any;
170
+ description: string | undefined;
171
+ totalDuration: number;
172
+ voice: "alloy" | "echo" | "fable" | "onyx" | "nova" | "shimmer";
173
+ speed: number;
174
+ segments: {
175
+ id: string;
176
+ title: any;
177
+ content: any;
178
+ objectKey: string;
179
+ startTime: number;
180
+ duration: number;
181
+ keyPoints: any;
182
+ order: any;
183
+ }[];
184
+ summary: any;
185
+ generatedAt: string;
186
+ };
187
+ content: string;
188
+ };
189
+ meta: object;
190
+ }>;
191
+ regenerateSegment: import("@trpc/server").TRPCMutationProcedure<{
192
+ input: {
193
+ episodeId: string;
194
+ segmentId: string;
195
+ newContent?: string | undefined;
196
+ voice?: "alloy" | "echo" | "fable" | "onyx" | "nova" | "shimmer" | undefined;
197
+ speed?: number | undefined;
198
+ };
199
+ output: {
200
+ segmentId: string;
201
+ audioUrl: string | undefined;
202
+ duration: number;
203
+ content: string;
204
+ totalDuration: number;
205
+ };
206
+ meta: object;
207
+ }>;
208
+ getEpisodeSchema: import("@trpc/server").TRPCQueryProcedure<{
209
+ input: {
210
+ episodeId: string;
211
+ };
212
+ output: {
213
+ segments: {
214
+ id: string;
215
+ title: string;
216
+ startTime: number;
217
+ duration: number;
218
+ keyPoints: string[];
219
+ order: number;
220
+ }[];
221
+ summary: {
222
+ executiveSummary: string;
223
+ learningObjectives: string[];
224
+ keyConcepts: string[];
225
+ followUpActions: string[];
226
+ targetAudience: string;
227
+ prerequisites: string[];
228
+ tags: string[];
229
+ };
230
+ metadata: {
231
+ title: string;
232
+ description: string | undefined;
233
+ totalDuration: number;
234
+ voice: string;
235
+ speed: number;
236
+ };
237
+ };
238
+ meta: object;
239
+ }>;
240
+ updateEpisode: import("@trpc/server").TRPCMutationProcedure<{
241
+ input: {
242
+ episodeId: string;
243
+ title?: string | undefined;
244
+ description?: string | undefined;
245
+ };
246
+ output: {
247
+ id: string;
248
+ createdAt: Date;
249
+ updatedAt: Date;
250
+ title: string;
251
+ description: string | null;
252
+ workspaceId: string;
253
+ type: import("@prisma/client").$Enums.ArtifactType;
254
+ isArchived: boolean;
255
+ difficulty: import("@prisma/client").$Enums.Difficulty | null;
256
+ estimatedTime: string | null;
257
+ createdById: string | null;
258
+ };
259
+ meta: object;
260
+ }>;
261
+ deleteEpisode: import("@trpc/server").TRPCMutationProcedure<{
262
+ input: {
263
+ episodeId: string;
264
+ };
265
+ output: boolean;
266
+ meta: object;
267
+ }>;
268
+ getAvailableVoices: import("@trpc/server").TRPCQueryProcedure<{
269
+ input: void;
270
+ output: {
271
+ id: string;
272
+ name: string;
273
+ description: string;
274
+ }[];
275
+ meta: object;
276
+ }>;
277
+ }>>;