Skip to content

Commit f744954

Browse files
authored
Merge pull request #66 from codecbros/dev
2 parents 721b378 + d885946 commit f744954

12 files changed

Lines changed: 465 additions & 413 deletions

File tree

‎package.json‎

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,31 @@
2323
"build:swc": "nest build -b swc"
2424
},
2525
"dependencies": {
26-
"@ai-sdk/google": "^2.0.47",
27-
"@ai-sdk/openai": "^2.0.88",
28-
"@ai-sdk/openai-compatible": "^1.0.29",
26+
"@ai-sdk/google": "^3.0.1",
27+
"@ai-sdk/openai": "^3.0.1",
28+
"@ai-sdk/openai-compatible": "^2.0.1",
2929
"@fastify/helmet": "^13.0.2",
3030
"@fastify/multipart": "^9.3.0",
3131
"@fastify/static": "^8.3.0",
3232
"@keyv/redis": "^5.1.5",
3333
"@nestjs/bullmq": "^11.0.4",
34-
"@nestjs/cache-manager": "^3.0.1",
35-
"@nestjs/common": "^11.1.9",
34+
"@nestjs/cache-manager": "^3.1.0",
35+
"@nestjs/common": "^11.1.10",
3636
"@nestjs/config": "^4.0.2",
37-
"@nestjs/core": "^11.1.9",
37+
"@nestjs/core": "^11.1.10",
3838
"@nestjs/jwt": "^11.0.2",
3939
"@nestjs/passport": "^11.0.5",
40-
"@nestjs/platform-express": "^11.1.9",
41-
"@nestjs/platform-fastify": "^11.1.9",
40+
"@nestjs/platform-express": "^11.1.10",
41+
"@nestjs/platform-fastify": "^11.1.10",
4242
"@nestjs/swagger": "^11.2.3",
4343
"@nestjs/terminus": "^11.0.0",
4444
"@nestjs/throttler": "^6.5.0",
4545
"@prisma/client": "^6.19.1",
4646
"@toon-format/toon": "^2.1.0",
4747
"@types/passport-jwt": "^4.0.1",
48-
"ai": "^5.0.114",
48+
"ai": "^6.0.3",
4949
"bcrypt": "^6.0.0",
50-
"bullmq": "^5.66.0",
50+
"bullmq": "^5.66.4",
5151
"cache-manager": "^7.2.7",
5252
"cacheable": "^2.3.1",
5353
"class-transformer": "^0.5.1",
@@ -72,17 +72,17 @@
7272
"devDependencies": {
7373
"@nestjs/cli": "^11.0.14",
7474
"@nestjs/schematics": "^11.0.9",
75-
"@nestjs/testing": "^11.1.9",
75+
"@nestjs/testing": "^11.1.10",
7676
"@swc/cli": "^0.7.9",
77-
"@swc/core": "^1.15.5",
77+
"@swc/core": "^1.15.7",
7878
"@types/bcrypt": "^6.0.0",
7979
"@types/express": "^5.0.6",
8080
"@types/jest": "^30.0.0",
8181
"@types/multer": "^2.0.0",
8282
"@types/node": "^25.0.3",
8383
"@types/supertest": "^6.0.3",
84-
"@typescript-eslint/eslint-plugin": "^8.50.0",
85-
"@typescript-eslint/parser": "^8.50.0",
84+
"@typescript-eslint/eslint-plugin": "^8.50.1",
85+
"@typescript-eslint/parser": "^8.50.1",
8686
"eslint": "^9.39.2",
8787
"eslint-config-prettier": "^10.1.8",
8888
"eslint-plugin-prettier": "^5.5.4",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- AlterTable
2+
ALTER TABLE "combinations" ADD COLUMN "ai_description" TEXT;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Please do not edit this file manually
22
# It should be added in your version-control system (e.g., Git)
3-
provider = "postgresql"
3+
provider = "postgresql"

‎prisma/schema.prisma‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ model Combination {
205205
user User @relation(fields: [userId], references: [id])
206206
isAIGenerated Boolean @default(false) @map("is_ai_generated")
207207
occasions String[]
208+
aiDescription String? @map("ai_description") @db.Text
208209
209210
items CombinationItem[]
210211
savedCombinations SavedCombination[]

‎src/modules/ai/ai.service.ts‎

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import {
66
Logger,
77
OnModuleInit,
88
} from '@nestjs/common';
9-
import { generateObject, generateText, LanguageModel } from 'ai';
9+
import { generateObject, generateText, LanguageModel, Output, Tool, ToolLoopAgent, ToolSet } from 'ai';
1010
import { Schema } from 'zod';
1111
import aiConfig from './config/ai.config';
1212
import { ConfigType } from '@nestjs/config';
1313
import { AIProviderEnum } from './enums/provider.enum';
14-
import { createOllama } from 'ollama-ai-provider-v2';
14+
// import { createOllama } from 'ollama-ai-provider-v2';
1515
import { openai } from '@ai-sdk/openai';
1616
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
1717

@@ -30,12 +30,12 @@ export class AiService implements OnModuleInit {
3030
this.logger.log('Usando Google Gemini', AiService.name);
3131
this.textModelAI = google(this.envAI.textModel);
3232
break;
33-
case AIProviderEnum.OLLAMA:
34-
this.logger.log('Usando Ollama', AiService.name);
35-
this.textModelAI = createOllama({
36-
baseURL: this.envAI.url,
37-
}).languageModel(this.envAI.textModel);
38-
break;
33+
// case AIProviderEnum.OLLAMA:
34+
// this.logger.log('Usando Ollama', AiService.name);
35+
// this.textModelAI = createOllama({
36+
// baseURL: this.envAI.url,
37+
// }).languageModel(this.envAI.textModel);
38+
// break;
3939
case AIProviderEnum.OPENAI:
4040
this.logger.log('Usando OpenAI', AiService.name);
4141
this.textModelAI = openai(this.envAI.textModel);
@@ -82,4 +82,15 @@ export class AiService implements OnModuleInit {
8282

8383
return textGenerated;
8484
}
85+
86+
async agent(prompt: string, outputSchema: Schema, systemPrompt?: string, tools?: ToolSet) {
87+
const agent = new ToolLoopAgent({
88+
model: this.textModelAI,
89+
instructions: systemPrompt,
90+
tools,
91+
output: Output.object({schema: outputSchema}),
92+
})
93+
94+
return (await agent.generate({prompt})).output;
95+
}
8596
}

‎src/modules/wardrobe/controllers/combinations/combinations.controller.spec.ts‎

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ describe('CombinationsController', () => {
6666
page: 1,
6767
};
6868

69+
const mockUser = {
70+
id: 'user-123',
71+
role: RoleEnum.USER,
72+
};
73+
6974
it('should generate combinations successfully', async () => {
7075
const expectedResult = {
7176
message: 'Combinaciones generadas correctamente',
@@ -87,10 +92,10 @@ describe('CombinationsController', () => {
8792
expectedResult,
8893
);
8994

90-
const result = await controller.generateCombinations(createDto);
95+
const result = await controller.generateCombinations(createDto, mockUser);
9196

9297
expect(result).toEqual(expectedResult);
93-
expect(service.generateCombinations).toHaveBeenCalledWith(createDto);
98+
expect(service.generateCombinations).toHaveBeenCalledWith(createDto, 'user-123');
9499
expect(service.generateCombinations).toHaveBeenCalledTimes(1);
95100
});
96101

@@ -100,7 +105,7 @@ describe('CombinationsController', () => {
100105
data: {},
101106
});
102107

103-
await controller.generateCombinations(createDto);
108+
await controller.generateCombinations(createDto, mockUser);
104109

105110
expect(service.generateCombinations).toHaveBeenCalledWith(
106111
expect.objectContaining({
@@ -109,6 +114,7 @@ describe('CombinationsController', () => {
109114
occasions: createDto.occasions,
110115
description: createDto.description,
111116
}),
117+
mockUser.id,
112118
);
113119
});
114120
});
@@ -119,9 +125,10 @@ describe('CombinationsController', () => {
119125
description: 'A casual outfit',
120126
occasions: ['Casual'],
121127
isAIGenerated: true,
128+
explanation: 'This is a great combination',
122129
combinationItems: [
123-
{ wardrobeItemId: 'item-1', explanation: 'Perfect shirt' },
124-
{ wardrobeItemId: 'item-2', explanation: 'Nice pants' },
130+
{ wardrobeItemId: 'item-1' },
131+
{ wardrobeItemId: 'item-2' },
125132
],
126133
};
127134

@@ -325,8 +332,8 @@ describe('CombinationsController', () => {
325332
const addItemsDto: AddItemsToCombinationDto = {
326333
combinationId: 'comb-1',
327334
combinationItems: [
328-
{ wardrobeItemId: 'item-1', explanation: 'Nice shirt' },
329-
{ wardrobeItemId: 'item-2', explanation: 'Good pants' },
335+
{ wardrobeItemId: 'item-1' },
336+
{ wardrobeItemId: 'item-2' },
330337
],
331338
};
332339

@@ -367,7 +374,7 @@ describe('CombinationsController', () => {
367374
const singleItemDto = {
368375
combinationId: 'comb-1',
369376
combinationItems: [
370-
{ wardrobeItemId: 'item-1', explanation: 'Nice shirt' },
377+
{ wardrobeItemId: 'item-1' },
371378
],
372379
};
373380

‎src/modules/wardrobe/controllers/combinations/combinations.controller.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ export class CombinationsController {
4646
'Genera combinaciones de prendas a partir de una lista de prendas base y categorías seleccionadas. Estas combinaciones no se guardan automaticamente',
4747
operationId: 'generateCombinations',
4848
})
49-
async generateCombinations(@Body() payload: CreateCombinationDto) {
50-
return this.combinationsService.generateCombinations(payload);
49+
async generateCombinations(@Body() payload: CreateCombinationDto, @CurrentSession() user: InfoUserInterface) {
50+
return this.combinationsService.generateCombinations(payload, user.id);
5151
}
5252

5353
@Post('save')

‎src/modules/wardrobe/dtos/combinations.dto.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,6 @@ class CombinationItemDto {
5959
@ApiProperty()
6060
@IsString()
6161
wardrobeItemId: string;
62-
63-
@ApiProperty()
64-
@IsString()
65-
@IsOptional()
66-
explanation: string;
6762
}
6863

6964
export class SaveCombinationDto extends PickType(CreateCombinationDto, [
@@ -82,6 +77,11 @@ export class SaveCombinationDto extends PickType(CreateCombinationDto, [
8277
@IsArray()
8378
@Type(() => CombinationItemDto)
8479
combinationItems: CombinationItemDto[];
80+
81+
@ApiProperty()
82+
@IsString()
83+
@IsOptional()
84+
explanation: string;
8585
}
8686

8787
export class AddItemsToCombinationDto extends PickType(SaveCombinationDto, [

‎src/modules/wardrobe/prompts/combinations.prompts.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ ${encode(clothingItemsBase)}
7676
${encode(clothingItems)}
7777
7878
# Categories:
79-
${encode(categories)}$
79+
${encode(categories)}
8080
8181
# Occasions:
8282
${encode(occasions)}

0 commit comments

Comments
 (0)