feat: widgets and ai chat
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
import { BaseApiWithErrors, classroomio, apiClient, getRequestBaseUrl } from '$lib/utils/services/api';
|
||||
import type {
|
||||
AgentConversation,
|
||||
AgentConversationCreateData,
|
||||
AgentConversationSummary,
|
||||
AgentStatusData,
|
||||
AiAssistantMessage
|
||||
} from '../utils/types';
|
||||
|
||||
class AiAssistantApi extends BaseApiWithErrors {
|
||||
status: AgentStatusData | null = $state(null);
|
||||
conversations: AgentConversationSummary[] = $state([]);
|
||||
currentConversation: AgentConversation | null = $state(null);
|
||||
|
||||
async fetchStatus(courseId: string) {
|
||||
await this.execute<typeof classroomio.agent.status.$get>({
|
||||
requestFn: () =>
|
||||
classroomio.agent.status.$get({
|
||||
query: { courseId }
|
||||
}),
|
||||
logContext: 'fetching agent status',
|
||||
onSuccess: (result) => {
|
||||
this.status = result.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async listConversations(courseId: string) {
|
||||
await this.execute<typeof classroomio.agent.history.$get>({
|
||||
requestFn: () =>
|
||||
classroomio.agent.history.$get({
|
||||
query: { courseId }
|
||||
}),
|
||||
logContext: 'listing conversations',
|
||||
onSuccess: (result) => {
|
||||
this.conversations = result.data as AgentConversationSummary[];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async loadConversation(conversationId: string) {
|
||||
await this.execute<(typeof classroomio.agent.history)[':conversationId']['$get']>({
|
||||
requestFn: () =>
|
||||
classroomio.agent.history[':conversationId'].$get({
|
||||
param: { conversationId }
|
||||
}),
|
||||
logContext: 'loading conversation',
|
||||
onSuccess: (result) => {
|
||||
this.currentConversation = {
|
||||
...(result.data as AgentConversation),
|
||||
messages: ((result.data as AgentConversation).messages ?? []) as AiAssistantMessage[]
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async createConversation(courseId: string, title?: string): Promise<{ id: string } | null> {
|
||||
let created: { id: string } | null = null;
|
||||
|
||||
await this.execute<typeof classroomio.agent.history.$post>({
|
||||
requestFn: () =>
|
||||
classroomio.agent.history.$post({
|
||||
json: { courseId, title }
|
||||
}),
|
||||
logContext: 'creating conversation',
|
||||
onSuccess: (result) => {
|
||||
const newConversation = result.data as AgentConversationCreateData;
|
||||
created = newConversation;
|
||||
|
||||
this.conversations = [
|
||||
{ ...newConversation, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() },
|
||||
...this.conversations
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
return created;
|
||||
}
|
||||
|
||||
async saveMessages(conversationId: string, messages: AiAssistantMessage[], title?: string) {
|
||||
await this.execute<(typeof classroomio.agent.history)[':conversationId']['$put']>({
|
||||
requestFn: () =>
|
||||
classroomio.agent.history[':conversationId'].$put({
|
||||
param: { conversationId },
|
||||
json: { messages, title }
|
||||
}),
|
||||
logContext: 'saving messages'
|
||||
});
|
||||
}
|
||||
|
||||
async deleteConversation(conversationId: string) {
|
||||
await this.execute<(typeof classroomio.agent.history)[':conversationId']['$delete']>({
|
||||
requestFn: () =>
|
||||
classroomio.agent.history[':conversationId'].$delete({
|
||||
param: { conversationId }
|
||||
}),
|
||||
logContext: 'deleting conversation',
|
||||
onSuccess: () => {
|
||||
this.conversations = this.conversations.filter((c) => c.id !== conversationId);
|
||||
|
||||
if (this.currentConversation?.id === conversationId) {
|
||||
this.currentConversation = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async uploadDocument(
|
||||
file: File,
|
||||
courseId: string,
|
||||
conversationId: string
|
||||
): Promise<{ documentId: string; fileName: string; wordCount: number; truncated: boolean } | null> {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
try {
|
||||
const url =
|
||||
`${getRequestBaseUrl()}/agent/upload` +
|
||||
`?courseId=${encodeURIComponent(courseId)}` +
|
||||
`&conversationId=${encodeURIComponent(conversationId)}`;
|
||||
|
||||
const response = await apiClient.request(url, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
credentials: 'include'
|
||||
});
|
||||
const result = (await response.json()) as {
|
||||
success: boolean;
|
||||
data?: { documentId: string; fileName: string; wordCount: number; truncated: boolean };
|
||||
};
|
||||
|
||||
if (result.success && result.data) {
|
||||
return result.data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error uploading document:', error);
|
||||
this.error = 'Failed to upload document';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async generateTitle(conversationId: string, firstMessageText: string): Promise<string | null> {
|
||||
let generatedTitle: string | null = null;
|
||||
|
||||
await this.execute<(typeof classroomio.agent.history)[':conversationId']['generate-title']['$post']>({
|
||||
requestFn: () =>
|
||||
classroomio.agent.history[':conversationId']['generate-title'].$post({
|
||||
param: { conversationId },
|
||||
json: { firstMessageText }
|
||||
}),
|
||||
logContext: 'generating title',
|
||||
onSuccess: (result) => {
|
||||
generatedTitle = (result.data as { title: string }).title;
|
||||
|
||||
// Update the title in the local conversations list
|
||||
this.conversations = this.conversations.map((c) =>
|
||||
c.id === conversationId ? { ...c, title: generatedTitle } : c
|
||||
);
|
||||
|
||||
if (this.currentConversation?.id === conversationId) {
|
||||
this.currentConversation = { ...this.currentConversation, title: generatedTitle };
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return generatedTitle;
|
||||
}
|
||||
}
|
||||
|
||||
export const aiAssistantApi = new AiAssistantApi();
|
||||
Reference in New Issue
Block a user