list suggestions

This commit is contained in:
Bastian Wagner
2026-06-15 14:42:58 +02:00
parent b979a3b097
commit 3998923693
10 changed files with 204 additions and 100 deletions

View File

@@ -40,6 +40,17 @@ export class ListsController {
return this.listsService.createList(this.requireUserId(request), createDto);
}
@Post('with-item-suggestions')
createListWithItemSuggestions(
@Req() request: AuthenticatedRequest,
@Body() createDto: CreateListDto,
) {
return this.listsService.createListWithItemSuggestions(
this.requireUserId(request),
createDto,
);
}
@Get()
listLists(@Req() request: AuthenticatedRequest) {
return this.listsService.listLists(this.requireUserId(request));

View File

@@ -465,6 +465,55 @@ describe('ListsService', () => {
expect(requestPayload.tools).toBeUndefined();
});
it('creates a list and returns item suggestions for it', async () => {
process.env.MISTRAL_API_KEY = 'test-key';
process.env.MISTRAL_AGENT_ID = 'agent-listify';
mockMistralResponse({
choices: [
{
message: {
content: JSON.stringify({
suggestions: [
{
title: 'Location buchen',
notes: 'Mit Kapazitaet abgleichen',
required: true,
},
],
}),
},
},
],
});
const response = await service.createListWithItemSuggestions('user-1', {
name: 'Sommerfest',
description: 'Planung fuer Team-Event',
kind: 'todo',
});
expect(response.list.name).toBe('Sommerfest');
expect(response.list.items).toHaveLength(0);
expect(response.suggestions).toEqual([
{
title: 'Location buchen',
notes: 'Mit Kapazitaet abgleichen',
quantity: undefined,
required: true,
},
]);
await expect(service.listLists('user-1')).resolves.toHaveLength(1);
const requestPayload = getMistralRequestPayload();
expect(requestPayload.messages[1].content).toContain('Name: Sommerfest');
expect(requestPayload.messages[1].content).toContain(
'Beschreibung: Planung fuer Team-Event',
);
expect(requestPayload.messages[1].content).toContain(
'Vorhandene Items: keine',
);
});
it('returns an empty suggestion list for malformed provider content', async () => {
process.env.MISTRAL_API_KEY = 'test-key';
process.env.MISTRAL_AGENT_ID = 'agent-listify';

View File

@@ -41,6 +41,11 @@ export interface ListItemSuggestionsResponse {
suggestions: ListItemSuggestion[];
}
export interface CreateListWithItemSuggestionsResponse {
list: UserList;
suggestions: ListItemSuggestion[];
}
interface MistralAgentCompletionResponse {
choices?: Array<{
message?: {
@@ -109,6 +114,21 @@ export class ListsService {
return userList;
}
async createListWithItemSuggestions(
ownerId: string,
createDto: CreateListDto,
): Promise<CreateListWithItemSuggestionsResponse> {
const list = await this.createList(ownerId, createDto);
const listEntity = await this.findAccessibleList(ownerId, list.id);
const response = await this.callMistralForItemSuggestions(listEntity);
const suggestions = this.normalizeItemSuggestions(response, listEntity.items);
return {
list,
suggestions,
};
}
async createListFromTemplate(
ownerId: string,
template: ListTemplate,