Skip to content

Commit 65b2c6b

Browse files
author
LocalMind Dev
committed
fix(ai-config): complete AI Model Configuration implementation with all endpoints
Complete implementation of AI Model Configuration with fixes for integration errors: Service Layer Fixes: - Remove bad import from 'inspector' - Fix removeAgent to use $pull operator with _id matching - Use $addToSet instead of $push for agent deduplication - Add getConfig() method to retrieve without plaintext keys - Add updateConfig() method for PATCH/PUT operations - Add proper error handling and validation Utility Layer Fixes: - Fix findAiModelConfigByUserId to use userId filter instead of findById - Fix findAiModelConfigById_And_ModelName to search by userId - Select exclude agents.key to prevent plaintext API keys in responses Routes Layer Updates: - POST /v1/config/agents - Create/setup AI model config - GET /v1/get/ai-model-config - Retrieve config (encrypted keys excluded) - PUT /v1/update/ai-model-config - Update config (encrypted keys excluded) - DELETE /v1/config/agents/:agentId - Remove specific agent Controller Implementation: - Implement getAiModelConfig() with authentication - Implement updateAiModelConfig() with Zod validation - Implement removeAgent() with proper error handling - Fix setupAiModelConfig to avoid empty agent placeholders - Check for duplicate agents in-memory instead of DB queries Security: - No plaintext API keys returned in GET responses - Proper authentication middleware usage - Input validation with Zod schemas - Proper error responses with status codes Fixes #3
1 parent 005f325 commit 65b2c6b

4 files changed

Lines changed: 151 additions & 29 deletions

File tree

LocalMind-Backend/src/api/v1/AiModelConfig/AiModelConfig.controller.ts

Lines changed: 108 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ import UserUtils from '../user/user.utils'
44
import { SendResponse } from '../../../utils/SendResponse.utils'
55
import { aiModelConfig_Constant } from './AiModelConfig.constant'
66
import AiModelConfigService from './AiModelConfig.service'
7-
import { aiModelConfig_CreateSchema } from './AiModelConfig.validator'
7+
import { aiModelConfig_CreateSchema, aiModelConfig_UpdateSchema } from './AiModelConfig.validator'
88
import { IAgent } from './AiModelConfig.type'
99

1010
class AiModelConfig_Controller {
11-
public async createAiModelConfig(_data: unknown) {}
12-
1311
public async setupAiModelConfig(req: Request, res: Response): Promise<void> {
1412
try {
1513
const token = req.headers.authorization?.split(' ')[1] || req.cookies?.token
@@ -31,24 +29,26 @@ class AiModelConfig_Controller {
3129
if (!existingConfig) {
3230
CreateConfig = await AiModelConfigService.setupAiModelConfig({
3331
userId: String(FindUserByToken._id),
34-
agents: [{} as IAgent],
32+
agents: [],
3533
system_prompt,
3634
})
3735
}
3836

39-
await Promise.all(
40-
(agents as IAgent[]).map(async (agent) => {
41-
const isAlreadyAdded = await AiModelConfigUtility.findAiModelConfigById_And_ModelName(
42-
String(FindUserByToken._id),
43-
agent.model
44-
)
45-
if (!isAlreadyAdded) {
46-
await AiModelConfigService.addAgent(String(FindUserByToken._id), agent)
47-
}
48-
})
37+
// Add agents without duplicates (check in-memory)
38+
const existingModels = new Set(
39+
(existingConfig?.agents || CreateConfig?.agents || []).map((a: IAgent) => a.model)
4940
)
5041

51-
const configToReturn = CreateConfig || existingConfig
42+
for (const agent of agents as IAgent[]) {
43+
if (!existingModels.has(agent.model)) {
44+
await AiModelConfigService.addAgent(String(FindUserByToken._id), agent)
45+
existingModels.add(agent.model)
46+
}
47+
}
48+
49+
const configToReturn = await AiModelConfigUtility.findAiModelConfigByUserId(
50+
String(FindUserByToken._id)
51+
)
5252

5353
SendResponse.success(
5454
res,
@@ -57,8 +57,6 @@ class AiModelConfig_Controller {
5757
201
5858
)
5959
} catch (error) {
60-
console.error('Error in setupAiModelConfig:', error)
61-
6260
SendResponse.error(
6361
res,
6462
(error as Error).message || 'Failed to set up AI Model Config',
@@ -68,9 +66,100 @@ class AiModelConfig_Controller {
6866
}
6967
}
7068

71-
public async updateAiModelConfig(_data: unknown) {}
69+
public async getAiModelConfig(req: Request, res: Response): Promise<void> {
70+
try {
71+
const userId = (req as any).user?._id || (req as any).user?.id
72+
73+
if (!userId) {
74+
SendResponse.error(res, 'Authentication required', 401, null)
75+
return
76+
}
77+
78+
const config = await AiModelConfigService.getConfig(String(userId))
79+
80+
if (!config) {
81+
SendResponse.error(res, 'No AI Model Configuration found', 404, null)
82+
return
83+
}
84+
85+
SendResponse.success(res, 'AI Model Configuration retrieved successfully', {
86+
config,
87+
})
88+
} catch (error) {
89+
SendResponse.error(
90+
res,
91+
(error as Error).message || 'Failed to retrieve AI Model Config',
92+
500,
93+
error
94+
)
95+
}
96+
}
97+
98+
public async updateAiModelConfig(req: Request, res: Response): Promise<void> {
99+
try {
100+
const userId = (req as any).user?._id || (req as any).user?.id
101+
102+
if (!userId) {
103+
SendResponse.error(res, 'Authentication required', 401, null)
104+
return
105+
}
106+
107+
const ValidateData = await aiModelConfig_UpdateSchema.parseAsync(req.body)
108+
109+
const updatedConfig = await AiModelConfigService.updateConfig(String(userId), ValidateData)
110+
111+
if (!updatedConfig) {
112+
SendResponse.error(res, 'AI Model Configuration not found', 404, null)
113+
return
114+
}
115+
116+
SendResponse.success(res, 'AI Model Configuration updated successfully', {
117+
config: updatedConfig,
118+
})
119+
} catch (error) {
120+
if ((error as any).code === 'P2025') {
121+
SendResponse.error(res, 'AI Model Configuration not found', 404, null)
122+
return
123+
}
124+
125+
SendResponse.error(
126+
res,
127+
(error as Error).message || 'Failed to update AI Model Config',
128+
500,
129+
error
130+
)
131+
}
132+
}
133+
134+
public async removeAgent(req: Request, res: Response): Promise<void> {
135+
try {
136+
const userId = (req as any).user?._id || (req as any).user?.id
137+
const { agentId } = req.params
138+
139+
if (!userId) {
140+
SendResponse.error(res, 'Authentication required', 401, null)
141+
return
142+
}
72143

73-
public async deleteAiModelConfig(_data: unknown) {}
144+
if (!agentId) {
145+
SendResponse.error(res, 'Agent ID is required', 400, null)
146+
return
147+
}
148+
149+
const updatedConfig = await AiModelConfigService.removeAgent(String(userId), agentId)
150+
151+
SendResponse.success(res, 'Agent removed successfully', {
152+
config: updatedConfig,
153+
})
154+
} catch (error) {
155+
SendResponse.error(
156+
res,
157+
(error as Error).message || 'Failed to remove agent',
158+
500,
159+
error
160+
)
161+
}
162+
}
74163
}
75164

76165
export default new AiModelConfig_Controller()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
import { Router } from 'express'
22
import AiModelConfigController from './AiModelConfig.controller'
3+
import { userMiddleware } from '../user/user.middleware'
4+
35
const router: Router = Router()
46

7+
// POST: Create/setup AI model config
58
router.post('/v1/config/agents', AiModelConfigController.setupAiModelConfig)
69

10+
// GET: Retrieve AI model config (no plaintext API keys)
11+
router.get('/v1/get/ai-model-config', userMiddleware, AiModelConfigController.getAiModelConfig)
12+
13+
// PUT: Update AI model config
14+
router.put('/v1/update/ai-model-config', userMiddleware, AiModelConfigController.updateAiModelConfig)
15+
16+
// DELETE: Remove a specific agent from config
17+
router.delete('/v1/config/agents/:agentId', userMiddleware, AiModelConfigController.removeAgent)
18+
719
export { router as AiModelConfigRoutes }

LocalMind-Backend/src/api/v1/AiModelConfig/AiModelConfig.service.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { console } from 'inspector'
21
import AiModelConfig from './AiModelConfig.model'
32
import { IAiModelConfig, IAgent } from './AiModelConfig.type'
43

@@ -8,22 +7,44 @@ class AiModelConfig_Service {
87
}
98

109
async addAgent(userId: string, agent: IAgent): Promise<IAiModelConfig | null> {
11-
console.log('Adding agent for userId:', userId, 'with agent:', agent)
1210
return await AiModelConfig.findOneAndUpdate(
1311
{ userId },
14-
{ $push: { agents: agent } },
12+
{ $addToSet: { agents: agent } },
1513
{ new: true }
1614
)
1715
}
1816

19-
async removeAgent(userId: string, _agentId: string): Promise<IAiModelConfig | null> {
20-
const config = (await AiModelConfig.findOne({ userId }).exec()) as any
17+
async removeAgent(userId: string, agentId: string): Promise<IAiModelConfig | null> {
18+
if (!agentId) {
19+
throw new Error('Agent ID is required to remove an agent.')
20+
}
21+
22+
const config = await AiModelConfig.findOneAndUpdate(
23+
{ userId },
24+
{ $pull: { agents: { _id: agentId } } },
25+
{ new: true }
26+
).exec()
2127

2228
if (!config) {
2329
throw new Error('AI Model Config not found for the user.')
2430
}
2531

26-
return await config.save()
32+
return config
33+
}
34+
35+
async getConfig(userId: string): Promise<IAiModelConfig | null> {
36+
return await AiModelConfig.findOne({ userId }).select('-agents.key').exec()
37+
}
38+
39+
async updateConfig(
40+
userId: string,
41+
updates: Partial<IAiModelConfig>
42+
): Promise<IAiModelConfig | null> {
43+
return await AiModelConfig.findOneAndUpdate({ userId }, updates, {
44+
new: true,
45+
})
46+
.select('-agents.key')
47+
.exec()
2748
}
2849
}
2950

LocalMind-Backend/src/api/v1/AiModelConfig/AiModelConfig.utility.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ class AiModelConfigUtility {
77
}
88

99
public async findAiModelConfigById_And_ModelName(
10-
id: string,
10+
userId: string,
1111
modelName: string
1212
): Promise<IAiModelConfig | null> {
13-
return await AiModelConfig.findOne({ _id: id, 'agents.model': modelName }).exec()
13+
return await AiModelConfig.findOne({ userId, 'agents.model': modelName }).exec()
1414
}
1515

16-
public async findAiModelConfigByUserId(id: string): Promise<IAiModelConfig | null> {
17-
return await AiModelConfig.findById(id).exec()
16+
public async findAiModelConfigByUserId(userId: string): Promise<IAiModelConfig | null> {
17+
return await AiModelConfig.findOne({ userId }).select('-agents.key').exec()
1818
}
1919

2020
public async findAiModelConfigsByUserId(userId: string): Promise<IAiModelConfig[]> {

0 commit comments

Comments
 (0)