@bpinhosilva/agent-orchestrator 1.0.0-alpha.12 → 1.0.0-alpha.13
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.
- package/CHANGELOG.md +7 -0
- package/dist/agents/agents.module.js +5 -2
- package/dist/agents/agents.service.js +52 -26
- package/dist/agents/dto/create-agent.dto.js +3 -3
- package/dist/agents/entities/agent.entity.js +8 -2
- package/dist/agents/implementations/claude.agent.js +136 -0
- package/dist/agents/implementations/gemini.agent.js +2 -2
- package/dist/common/storage.service.js +26 -2
- package/dist/providers/entities/provider.entity.js +1 -1
- package/dist/providers/providers.service.js +44 -0
- package/dist/src/agents/agents.module.d.ts +2 -0
- package/dist/src/agents/agents.module.js +3 -2
- package/dist/src/agents/agents.module.js.map +1 -1
- package/dist/src/agents/agents.service.js +49 -25
- package/dist/src/agents/agents.service.js.map +1 -1
- package/dist/src/agents/dto/create-agent.dto.d.ts +1 -1
- package/dist/src/agents/dto/create-agent.dto.js +5 -5
- package/dist/src/agents/dto/create-agent.dto.js.map +1 -1
- package/dist/src/agents/entities/agent.entity.d.ts +2 -1
- package/dist/src/agents/entities/agent.entity.js +8 -2
- package/dist/src/agents/entities/agent.entity.js.map +1 -1
- package/dist/src/agents/enums/provider.enum.d.ts +1 -3
- package/dist/src/agents/enums/provider.enum.js +1 -3
- package/dist/src/agents/enums/provider.enum.js.map +1 -1
- package/dist/src/agents/implementations/claude.agent.d.ts +24 -0
- package/dist/src/agents/implementations/claude.agent.js +141 -0
- package/dist/src/agents/implementations/claude.agent.js.map +1 -0
- package/dist/src/agents/implementations/gemini.agent.js +2 -2
- package/dist/src/common/storage.service.d.ts +13 -0
- package/dist/src/common/storage.service.js +26 -0
- package/dist/src/common/storage.service.js.map +1 -1
- package/dist/src/providers/entities/provider.entity.js +1 -1
- package/dist/src/providers/entities/provider.entity.js.map +1 -1
- package/dist/src/providers/providers.service.d.ts +4 -1
- package/dist/src/providers/providers.service.js +43 -0
- package/dist/src/providers/providers.service.js.map +1 -1
- package/dist/src/tasks/comments.service.d.ts +3 -1
- package/dist/src/tasks/comments.service.js +17 -3
- package/dist/src/tasks/comments.service.js.map +1 -1
- package/dist/src/tasks/dto/create-task.dto.d.ts +0 -1
- package/dist/src/tasks/dto/create-task.dto.js +2 -8
- package/dist/src/tasks/dto/create-task.dto.js.map +1 -1
- package/dist/src/tasks/entities/task.entity.d.ts +0 -1
- package/dist/src/tasks/entities/task.entity.js +1 -6
- package/dist/src/tasks/entities/task.entity.js.map +1 -1
- package/dist/src/tasks/task-scheduler.service.d.ts +3 -1
- package/dist/src/tasks/task-scheduler.service.js +49 -13
- package/dist/src/tasks/task-scheduler.service.js.map +1 -1
- package/dist/src/uploads/uploads.controller.d.ts +2 -1
- package/dist/src/uploads/uploads.controller.js +17 -3
- package/dist/src/uploads/uploads.controller.js.map +1 -1
- package/dist/tasks/comments.service.js +17 -3
- package/dist/tasks/dto/create-task.dto.js +1 -6
- package/dist/tasks/entities/task.entity.js +0 -4
- package/dist/tasks/task-scheduler.service.js +54 -13
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/uploads/uploads.controller.js +18 -3
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [1.0.0-alpha.13](https://github.com/bpinhosilva/agent-orchestrator/compare/v1.0.0-alpha.12...v1.0.0-alpha.13) (2026-03-26)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add Claude agent implementation with Anthropic SDK and refactor agent-provider ([1400a0d](https://github.com/bpinhosilva/agent-orchestrator/commit/1400a0dec6beb8393ddc4c5a23b9b860532079e8))
|
|
7
|
+
|
|
1
8
|
# [1.0.0-alpha.12](https://github.com/bpinhosilva/agent-orchestrator/compare/v1.0.0-alpha.11...v1.0.0-alpha.12) (2026-03-24)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -12,7 +12,10 @@ const typeorm_1 = require("@nestjs/typeorm");
|
|
|
12
12
|
const agents_controller_1 = require("./agents.controller");
|
|
13
13
|
const agents_service_1 = require("./agents.service");
|
|
14
14
|
const agent_entity_1 = require("./entities/agent.entity");
|
|
15
|
-
|
|
15
|
+
// Side-effect imports: @RegisterAgent decorators fire at class-definition time
|
|
16
|
+
// and self-register each implementation in AGENT_REGISTRY. No DI instantiation needed.
|
|
17
|
+
require("./implementations/gemini.agent");
|
|
18
|
+
require("./implementations/claude.agent");
|
|
16
19
|
let AgentsModule = class AgentsModule {
|
|
17
20
|
};
|
|
18
21
|
exports.AgentsModule = AgentsModule;
|
|
@@ -20,7 +23,7 @@ exports.AgentsModule = AgentsModule = __decorate([
|
|
|
20
23
|
(0, common_1.Module)({
|
|
21
24
|
imports: [typeorm_1.TypeOrmModule.forFeature([agent_entity_1.AgentEntity])],
|
|
22
25
|
controllers: [agents_controller_1.AgentsController],
|
|
23
|
-
providers: [agents_service_1.AgentsService
|
|
26
|
+
providers: [agents_service_1.AgentsService],
|
|
24
27
|
exports: [agents_service_1.AgentsService],
|
|
25
28
|
})
|
|
26
29
|
], AgentsModule);
|
|
@@ -19,6 +19,7 @@ const typeorm_1 = require("@nestjs/typeorm");
|
|
|
19
19
|
const typeorm_2 = require("typeorm");
|
|
20
20
|
const agent_entity_1 = require("./entities/agent.entity");
|
|
21
21
|
const agent_registry_1 = require("./registry/agent.registry");
|
|
22
|
+
const AGENT_RELATIONS = ['model', 'provider'];
|
|
22
23
|
let AgentsService = AgentsService_1 = class AgentsService {
|
|
23
24
|
constructor(agentRepository) {
|
|
24
25
|
this.agentRepository = agentRepository;
|
|
@@ -27,7 +28,9 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
27
28
|
}
|
|
28
29
|
async onModuleInit() {
|
|
29
30
|
this.logger.log('Initializing Agent instances from database...');
|
|
30
|
-
const agents = await this.agentRepository.find({
|
|
31
|
+
const agents = await this.agentRepository.find({
|
|
32
|
+
relations: AGENT_RELATIONS,
|
|
33
|
+
});
|
|
31
34
|
for (const agentEntity of agents) {
|
|
32
35
|
if (agentEntity.status !== 'inactive') {
|
|
33
36
|
try {
|
|
@@ -46,14 +49,14 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
46
49
|
this.agentInstances.delete(agentEntity.id);
|
|
47
50
|
return;
|
|
48
51
|
}
|
|
49
|
-
const
|
|
50
|
-
if (!
|
|
52
|
+
const providerName = agentEntity.provider?.name?.toLowerCase();
|
|
53
|
+
if (!providerName) {
|
|
51
54
|
this.logger.warn(`No provider found for agent #${agentEntity.id}. Skipping instance creation.`);
|
|
52
55
|
return;
|
|
53
56
|
}
|
|
54
|
-
const AgentClass = (0, agent_registry_1.getAgentImplementation)(
|
|
57
|
+
const AgentClass = (0, agent_registry_1.getAgentImplementation)(providerName);
|
|
55
58
|
if (!AgentClass) {
|
|
56
|
-
this.logger.warn(`No implementation found for provider: ${
|
|
59
|
+
this.logger.warn(`No implementation found for provider: ${providerName}. Skipping instance creation.`);
|
|
57
60
|
return;
|
|
58
61
|
}
|
|
59
62
|
try {
|
|
@@ -63,7 +66,7 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
63
66
|
description: agentEntity.description,
|
|
64
67
|
systemInstructions: agentEntity.systemInstructions,
|
|
65
68
|
role: agentEntity.role,
|
|
66
|
-
provider:
|
|
69
|
+
provider: providerName,
|
|
67
70
|
});
|
|
68
71
|
this.agentInstances.set(agentEntity.id, instance);
|
|
69
72
|
this.logger.debug(`Synchronized agent instance #${agentEntity.id}`);
|
|
@@ -71,24 +74,41 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
71
74
|
catch (error) {
|
|
72
75
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
73
76
|
this.logger.error(`Error synchronizing agent #${agentEntity.id}: ${errorMessage}`);
|
|
74
|
-
throw
|
|
77
|
+
throw new common_1.BadRequestException(`Failed to initialize agent instance: ${errorMessage}`);
|
|
75
78
|
}
|
|
76
79
|
}
|
|
77
80
|
async create(createAgentDto) {
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
const { modelId, providerId, ...rest } = createAgentDto;
|
|
82
|
+
const agentData = { ...rest };
|
|
83
|
+
if (modelId) {
|
|
84
|
+
agentData.model = { id: modelId };
|
|
85
|
+
}
|
|
86
|
+
if (providerId) {
|
|
87
|
+
agentData.provider = { id: providerId };
|
|
88
|
+
}
|
|
89
|
+
return await this.agentRepository.manager.transaction(async (manager) => {
|
|
90
|
+
const agent = manager.create(agent_entity_1.AgentEntity, agentData);
|
|
91
|
+
const savedAgent = await manager.save(agent);
|
|
92
|
+
// Reload with full relations for proper synchronization
|
|
93
|
+
const fullyLoadedAgent = await manager.findOne(agent_entity_1.AgentEntity, {
|
|
94
|
+
where: { id: savedAgent.id },
|
|
95
|
+
relations: AGENT_RELATIONS,
|
|
96
|
+
});
|
|
97
|
+
if (!fullyLoadedAgent) {
|
|
98
|
+
throw new Error(`Agent #${savedAgent.id} not found immediately after save`);
|
|
99
|
+
}
|
|
100
|
+
// This will throw BadRequestException if instantiation fails, rolling back the transaction
|
|
101
|
+
this.syncAgentInstance(fullyLoadedAgent);
|
|
102
|
+
return fullyLoadedAgent;
|
|
103
|
+
});
|
|
84
104
|
}
|
|
85
105
|
async findAll() {
|
|
86
|
-
return this.agentRepository.find({ relations:
|
|
106
|
+
return this.agentRepository.find({ relations: AGENT_RELATIONS });
|
|
87
107
|
}
|
|
88
108
|
async findOne(id) {
|
|
89
109
|
const agent = await this.agentRepository.findOne({
|
|
90
110
|
where: { id },
|
|
91
|
-
relations:
|
|
111
|
+
relations: AGENT_RELATIONS,
|
|
92
112
|
});
|
|
93
113
|
if (!agent) {
|
|
94
114
|
throw new common_1.NotFoundException(`Agent #${id} not found`);
|
|
@@ -96,21 +116,27 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
96
116
|
return agent;
|
|
97
117
|
}
|
|
98
118
|
async update(id, updateAgentDto) {
|
|
99
|
-
const { modelId, ...rest } = updateAgentDto;
|
|
119
|
+
const { modelId, providerId, ...rest } = updateAgentDto;
|
|
100
120
|
const updateData = { ...rest };
|
|
101
121
|
if (modelId) {
|
|
102
122
|
updateData.model = { id: modelId };
|
|
103
123
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
where: { id },
|
|
107
|
-
relations: ['model'],
|
|
108
|
-
});
|
|
109
|
-
if (!updatedAgent) {
|
|
110
|
-
throw new common_1.NotFoundException(`Agent #${id} not found`);
|
|
124
|
+
if (providerId) {
|
|
125
|
+
updateData.provider = { id: providerId };
|
|
111
126
|
}
|
|
112
|
-
this.
|
|
113
|
-
|
|
127
|
+
return await this.agentRepository.manager.transaction(async (manager) => {
|
|
128
|
+
await manager.update(agent_entity_1.AgentEntity, id, updateData);
|
|
129
|
+
const updatedAgent = await manager.findOne(agent_entity_1.AgentEntity, {
|
|
130
|
+
where: { id },
|
|
131
|
+
relations: AGENT_RELATIONS,
|
|
132
|
+
});
|
|
133
|
+
if (!updatedAgent) {
|
|
134
|
+
throw new common_1.NotFoundException(`Agent #${id} not found`);
|
|
135
|
+
}
|
|
136
|
+
// This will throw BadRequestException if instantiation fails, rolling back the transaction
|
|
137
|
+
this.syncAgentInstance(updatedAgent);
|
|
138
|
+
return updatedAgent;
|
|
139
|
+
});
|
|
114
140
|
}
|
|
115
141
|
async remove(id) {
|
|
116
142
|
const agent = await this.findOne(id);
|
|
@@ -138,7 +164,7 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
138
164
|
this.logger.debug(`Agent instance #${agentId} not found in memory. Checking database...`);
|
|
139
165
|
const agentEntity = await this.agentRepository.findOne({
|
|
140
166
|
where: { id: agentId },
|
|
141
|
-
relations:
|
|
167
|
+
relations: AGENT_RELATIONS,
|
|
142
168
|
});
|
|
143
169
|
if (!agentEntity) {
|
|
144
170
|
throw new common_1.NotFoundException(`Agent #${agentId} not found`);
|
|
@@ -45,7 +45,7 @@ __decorate([
|
|
|
45
45
|
__metadata("design:type", String)
|
|
46
46
|
], CreateAgentDto.prototype, "status", void 0);
|
|
47
47
|
__decorate([
|
|
48
|
-
(0, class_validator_1.
|
|
49
|
-
(0, class_validator_1.
|
|
48
|
+
(0, class_validator_1.IsUUID)(),
|
|
49
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
50
50
|
__metadata("design:type", String)
|
|
51
|
-
], CreateAgentDto.prototype, "
|
|
51
|
+
], CreateAgentDto.prototype, "providerId", void 0);
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.AgentEntity = void 0;
|
|
13
13
|
const typeorm_1 = require("typeorm");
|
|
14
14
|
const model_entity_1 = require("../../models/entities/model.entity");
|
|
15
|
+
const provider_entity_1 = require("../../providers/entities/provider.entity");
|
|
15
16
|
let AgentEntity = class AgentEntity {
|
|
16
17
|
};
|
|
17
18
|
exports.AgentEntity = AgentEntity;
|
|
@@ -40,8 +41,13 @@ __decorate([
|
|
|
40
41
|
__metadata("design:type", String)
|
|
41
42
|
], AgentEntity.prototype, "status", void 0);
|
|
42
43
|
__decorate([
|
|
43
|
-
(0, typeorm_1.
|
|
44
|
-
|
|
44
|
+
(0, typeorm_1.ManyToOne)(() => provider_entity_1.Provider, {
|
|
45
|
+
nullable: true,
|
|
46
|
+
eager: true,
|
|
47
|
+
onDelete: 'SET NULL',
|
|
48
|
+
}),
|
|
49
|
+
(0, typeorm_1.JoinColumn)({ name: 'providerId' }),
|
|
50
|
+
__metadata("design:type", provider_entity_1.Provider)
|
|
45
51
|
], AgentEntity.prototype, "provider", void 0);
|
|
46
52
|
__decorate([
|
|
47
53
|
(0, typeorm_1.ManyToOne)(() => model_entity_1.Model, (model) => model.agents, {
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var ClaudeAgent_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.ClaudeAgent = void 0;
|
|
17
|
+
const claude_agent_sdk_1 = require("@anthropic-ai/claude-agent-sdk");
|
|
18
|
+
const common_1 = require("@nestjs/common");
|
|
19
|
+
const agent_registry_1 = require("../registry/agent.registry");
|
|
20
|
+
let ClaudeAgent = ClaudeAgent_1 = class ClaudeAgent {
|
|
21
|
+
constructor(model = 'claude-opus-4-6') {
|
|
22
|
+
this.logger = new common_1.Logger(ClaudeAgent_1.name);
|
|
23
|
+
this.name = 'ClaudeAgent';
|
|
24
|
+
this.provider = 'anthropic';
|
|
25
|
+
this.model = model;
|
|
26
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
27
|
+
if (!apiKey) {
|
|
28
|
+
this.logger.error('ANTHROPIC_API_KEY environment variable is not set');
|
|
29
|
+
throw new Error('ANTHROPIC_API_KEY is required to initialize ClaudeAgent');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
getName() {
|
|
33
|
+
return this.name;
|
|
34
|
+
}
|
|
35
|
+
getDescription() {
|
|
36
|
+
return this.description || '';
|
|
37
|
+
}
|
|
38
|
+
getSystemInstructions() {
|
|
39
|
+
return this.systemInstructions || '';
|
|
40
|
+
}
|
|
41
|
+
getRole() {
|
|
42
|
+
return this.role || '';
|
|
43
|
+
}
|
|
44
|
+
getProvider() {
|
|
45
|
+
return this.provider;
|
|
46
|
+
}
|
|
47
|
+
getModel() {
|
|
48
|
+
return this.model;
|
|
49
|
+
}
|
|
50
|
+
updateConfig(config) {
|
|
51
|
+
if (config['name'])
|
|
52
|
+
this.name = config['name'];
|
|
53
|
+
if (config['description'])
|
|
54
|
+
this.description = config['description'];
|
|
55
|
+
if (config['systemInstructions'])
|
|
56
|
+
this.systemInstructions = config['systemInstructions'];
|
|
57
|
+
if (config['role'])
|
|
58
|
+
this.role = config['role'];
|
|
59
|
+
if (config['provider'])
|
|
60
|
+
this.provider = config['provider'];
|
|
61
|
+
if (config['model'])
|
|
62
|
+
this.model = config['model'];
|
|
63
|
+
}
|
|
64
|
+
buildSystemPrompt() {
|
|
65
|
+
return [
|
|
66
|
+
`Your name is ${this.name}.`,
|
|
67
|
+
this.role ? `Your role is: ${this.role}.` : '',
|
|
68
|
+
this.description ? `Description of yourself: ${this.description}.` : '',
|
|
69
|
+
this.systemInstructions
|
|
70
|
+
? `Instructions:\n${this.systemInstructions}`
|
|
71
|
+
: '',
|
|
72
|
+
]
|
|
73
|
+
.filter(Boolean)
|
|
74
|
+
.join('\n');
|
|
75
|
+
}
|
|
76
|
+
async processText(input) {
|
|
77
|
+
this.logger.debug(`Processing input with ClaudeAgent. Model: ${this.model}`);
|
|
78
|
+
try {
|
|
79
|
+
const systemPrompt = this.buildSystemPrompt();
|
|
80
|
+
let resultContent = '';
|
|
81
|
+
let resultMetadata = {};
|
|
82
|
+
const q = (0, claude_agent_sdk_1.query)({
|
|
83
|
+
prompt: input,
|
|
84
|
+
options: {
|
|
85
|
+
model: this.model,
|
|
86
|
+
systemPrompt,
|
|
87
|
+
permissionMode: 'bypassPermissions',
|
|
88
|
+
persistSession: false,
|
|
89
|
+
tools: [],
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
for await (const message of q) {
|
|
93
|
+
if (message.type === 'result' && message.subtype === 'success') {
|
|
94
|
+
resultContent = message.result;
|
|
95
|
+
resultMetadata = {
|
|
96
|
+
model: this.model,
|
|
97
|
+
usage: message.usage,
|
|
98
|
+
totalCostUsd: message.total_cost_usd,
|
|
99
|
+
numTurns: message.num_turns,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
content: resultContent,
|
|
105
|
+
metadata: resultMetadata,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
this.logger.error(`Claude Error: ${error}`);
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
isFeatureSupported(feature) {
|
|
114
|
+
void feature;
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
async performTask(task, project) {
|
|
118
|
+
this.logger.debug(`Performing task: ${task.title} for project: ${project.title}`);
|
|
119
|
+
const prompt = `
|
|
120
|
+
Task: ${task.title}
|
|
121
|
+
Description: ${task.description}
|
|
122
|
+
Project: ${project.title}
|
|
123
|
+
Project Description: ${project.description}
|
|
124
|
+
|
|
125
|
+
Please perform the task and provide the output.
|
|
126
|
+
`;
|
|
127
|
+
return this.processText(prompt);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
exports.ClaudeAgent = ClaudeAgent;
|
|
131
|
+
exports.ClaudeAgent = ClaudeAgent = ClaudeAgent_1 = __decorate([
|
|
132
|
+
(0, common_1.Injectable)(),
|
|
133
|
+
(0, agent_registry_1.RegisterAgent)('anthropic'),
|
|
134
|
+
__param(0, (0, common_1.Optional)()),
|
|
135
|
+
__metadata("design:paramtypes", [String])
|
|
136
|
+
], ClaudeAgent);
|
|
@@ -21,7 +21,7 @@ let GeminiAgent = GeminiAgent_1 = class GeminiAgent {
|
|
|
21
21
|
constructor(model = 'gemini-2.5-flash-lite') {
|
|
22
22
|
this.logger = new common_1.Logger(GeminiAgent_1.name);
|
|
23
23
|
this.name = 'GeminiAgent';
|
|
24
|
-
this.provider = '
|
|
24
|
+
this.provider = 'google';
|
|
25
25
|
this.enableGrounding = true;
|
|
26
26
|
this.model = model;
|
|
27
27
|
const apiKey = process.env.GEMINI_API_KEY;
|
|
@@ -173,7 +173,7 @@ Please perform the task and provide the output.
|
|
|
173
173
|
exports.GeminiAgent = GeminiAgent;
|
|
174
174
|
exports.GeminiAgent = GeminiAgent = GeminiAgent_1 = __decorate([
|
|
175
175
|
(0, common_1.Injectable)(),
|
|
176
|
-
(0, agent_registry_1.RegisterAgent)('
|
|
176
|
+
(0, agent_registry_1.RegisterAgent)('google'),
|
|
177
177
|
__param(0, (0, common_1.Optional)()),
|
|
178
178
|
__metadata("design:paramtypes", [String])
|
|
179
179
|
], GeminiAgent);
|
|
@@ -48,6 +48,7 @@ const common_1 = require("@nestjs/common");
|
|
|
48
48
|
const os = __importStar(require("os"));
|
|
49
49
|
const path = __importStar(require("path"));
|
|
50
50
|
const fs = __importStar(require("fs"));
|
|
51
|
+
const crypto = __importStar(require("crypto"));
|
|
51
52
|
let StorageService = StorageService_1 = class StorageService {
|
|
52
53
|
constructor() {
|
|
53
54
|
this.logger = new common_1.Logger(StorageService_1.name);
|
|
@@ -65,11 +66,34 @@ let StorageService = StorageService_1 = class StorageService {
|
|
|
65
66
|
return path.join(this.baseDir, 'artifacts');
|
|
66
67
|
}
|
|
67
68
|
getFullPath(relativePath) {
|
|
68
|
-
// relativePath is like /uploads/artifacts/<uuid>.extension
|
|
69
|
-
// We only care about the filename part if the prefix is fixed
|
|
70
69
|
const filename = path.basename(relativePath);
|
|
71
70
|
return path.join(this.getArtifactsPath(), filename);
|
|
72
71
|
}
|
|
72
|
+
async saveBase64(base64, mimeType, originalName) {
|
|
73
|
+
const buffer = Buffer.from(base64, 'base64');
|
|
74
|
+
return this.saveBuffer(buffer, mimeType, originalName);
|
|
75
|
+
}
|
|
76
|
+
async saveBuffer(buffer, mimeType, originalName) {
|
|
77
|
+
const id = crypto.randomUUID();
|
|
78
|
+
const extension = mimeType.split('/')[1] || 'bin';
|
|
79
|
+
const filename = `${id}.${extension}`;
|
|
80
|
+
const filePath = path.join(this.getArtifactsPath(), filename);
|
|
81
|
+
await fs.promises.writeFile(filePath, buffer);
|
|
82
|
+
this.logger.debug(`Saved artifact to: ${filePath}`);
|
|
83
|
+
return {
|
|
84
|
+
id,
|
|
85
|
+
originalName,
|
|
86
|
+
mimeType,
|
|
87
|
+
filePath: `uploads/artifacts/${filename}`, // Publicly accessible path via UploadsController
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
async delete(relativePath) {
|
|
91
|
+
const fullPath = this.getFullPath(relativePath);
|
|
92
|
+
if (fs.existsSync(fullPath)) {
|
|
93
|
+
await fs.promises.unlink(fullPath);
|
|
94
|
+
this.logger.debug(`Deleted artifact file: ${fullPath}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
73
97
|
};
|
|
74
98
|
exports.StorageService = StorageService;
|
|
75
99
|
exports.StorageService = StorageService = StorageService_1 = __decorate([
|
|
@@ -28,7 +28,7 @@ __decorate([
|
|
|
28
28
|
__metadata("design:type", String)
|
|
29
29
|
], Provider.prototype, "description", void 0);
|
|
30
30
|
__decorate([
|
|
31
|
-
(0, typeorm_1.OneToMany)(() => model_entity_1.Model, (model) => model.provider),
|
|
31
|
+
(0, typeorm_1.OneToMany)(() => model_entity_1.Model, (model) => model.provider, { cascade: true }),
|
|
32
32
|
__metadata("design:type", Array)
|
|
33
33
|
], Provider.prototype, "models", void 0);
|
|
34
34
|
__decorate([
|
|
@@ -21,6 +21,50 @@ let ProvidersService = class ProvidersService {
|
|
|
21
21
|
constructor(providerRepository) {
|
|
22
22
|
this.providerRepository = providerRepository;
|
|
23
23
|
}
|
|
24
|
+
async onModuleInit() {
|
|
25
|
+
await this.seedProviders();
|
|
26
|
+
}
|
|
27
|
+
async seedProviders() {
|
|
28
|
+
const defaultProviders = [
|
|
29
|
+
{
|
|
30
|
+
name: 'google',
|
|
31
|
+
description: 'Google Generative AI (Gemini)',
|
|
32
|
+
models: [
|
|
33
|
+
{ name: 'gemini-2.5-flash-lite' },
|
|
34
|
+
{ name: 'gemini-2.5-flash-image' },
|
|
35
|
+
{ name: 'gemini-2.5-pro' },
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'anthropic',
|
|
40
|
+
description: 'Anthropic Claude AI',
|
|
41
|
+
models: [{ name: 'claude-opus-4-6' }, { name: 'claude-haiku-4-5' }],
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
for (const p of defaultProviders) {
|
|
45
|
+
let provider = await this.providerRepository.findOne({
|
|
46
|
+
where: { name: p.name },
|
|
47
|
+
relations: ['models'],
|
|
48
|
+
});
|
|
49
|
+
if (!provider) {
|
|
50
|
+
provider = this.providerRepository.create(p);
|
|
51
|
+
await this.providerRepository.save(provider);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// Check for missing models
|
|
55
|
+
let changed = false;
|
|
56
|
+
for (const m of p.models) {
|
|
57
|
+
if (!provider.models.some((existing) => existing.name === m.name)) {
|
|
58
|
+
provider.models.push(m);
|
|
59
|
+
changed = true;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (changed) {
|
|
63
|
+
await this.providerRepository.save(provider);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
24
68
|
async create(createProviderDto) {
|
|
25
69
|
const provider = this.providerRepository.create(createProviderDto);
|
|
26
70
|
return this.providerRepository.save(provider);
|
|
@@ -12,7 +12,8 @@ const typeorm_1 = require("@nestjs/typeorm");
|
|
|
12
12
|
const agents_controller_1 = require("./agents.controller");
|
|
13
13
|
const agents_service_1 = require("./agents.service");
|
|
14
14
|
const agent_entity_1 = require("./entities/agent.entity");
|
|
15
|
-
|
|
15
|
+
require("./implementations/gemini.agent");
|
|
16
|
+
require("./implementations/claude.agent");
|
|
16
17
|
let AgentsModule = class AgentsModule {
|
|
17
18
|
};
|
|
18
19
|
exports.AgentsModule = AgentsModule;
|
|
@@ -20,7 +21,7 @@ exports.AgentsModule = AgentsModule = __decorate([
|
|
|
20
21
|
(0, common_1.Module)({
|
|
21
22
|
imports: [typeorm_1.TypeOrmModule.forFeature([agent_entity_1.AgentEntity])],
|
|
22
23
|
controllers: [agents_controller_1.AgentsController],
|
|
23
|
-
providers: [agents_service_1.AgentsService
|
|
24
|
+
providers: [agents_service_1.AgentsService],
|
|
24
25
|
exports: [agents_service_1.AgentsService],
|
|
25
26
|
})
|
|
26
27
|
], AgentsModule);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.module.js","sourceRoot":"","sources":["../../../src/agents/agents.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,2DAAuD;AACvD,qDAAiD;AACjD,0DAAsD;
|
|
1
|
+
{"version":3,"file":"agents.module.js","sourceRoot":"","sources":["../../../src/agents/agents.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,2DAAuD;AACvD,qDAAiD;AACjD,0DAAsD;AAGtD,0CAAwC;AACxC,0CAAwC;AAQjC,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IANxB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,uBAAa,CAAC,UAAU,CAAC,CAAC,0BAAW,CAAC,CAAC,CAAC;QAClD,WAAW,EAAE,CAAC,oCAAgB,CAAC;QAC/B,SAAS,EAAE,CAAC,8BAAa,CAAC;QAC1B,OAAO,EAAE,CAAC,8BAAa,CAAC;KACzB,CAAC;GACW,YAAY,CAAG"}
|
|
@@ -19,6 +19,7 @@ const typeorm_1 = require("@nestjs/typeorm");
|
|
|
19
19
|
const typeorm_2 = require("typeorm");
|
|
20
20
|
const agent_entity_1 = require("./entities/agent.entity");
|
|
21
21
|
const agent_registry_1 = require("./registry/agent.registry");
|
|
22
|
+
const AGENT_RELATIONS = ['model', 'provider'];
|
|
22
23
|
let AgentsService = AgentsService_1 = class AgentsService {
|
|
23
24
|
agentRepository;
|
|
24
25
|
logger = new common_1.Logger(AgentsService_1.name);
|
|
@@ -28,7 +29,9 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
28
29
|
}
|
|
29
30
|
async onModuleInit() {
|
|
30
31
|
this.logger.log('Initializing Agent instances from database...');
|
|
31
|
-
const agents = await this.agentRepository.find({
|
|
32
|
+
const agents = await this.agentRepository.find({
|
|
33
|
+
relations: AGENT_RELATIONS,
|
|
34
|
+
});
|
|
32
35
|
for (const agentEntity of agents) {
|
|
33
36
|
if (agentEntity.status !== 'inactive') {
|
|
34
37
|
try {
|
|
@@ -47,14 +50,14 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
47
50
|
this.agentInstances.delete(agentEntity.id);
|
|
48
51
|
return;
|
|
49
52
|
}
|
|
50
|
-
const
|
|
51
|
-
if (!
|
|
53
|
+
const providerName = agentEntity.provider?.name?.toLowerCase();
|
|
54
|
+
if (!providerName) {
|
|
52
55
|
this.logger.warn(`No provider found for agent #${agentEntity.id}. Skipping instance creation.`);
|
|
53
56
|
return;
|
|
54
57
|
}
|
|
55
|
-
const AgentClass = (0, agent_registry_1.getAgentImplementation)(
|
|
58
|
+
const AgentClass = (0, agent_registry_1.getAgentImplementation)(providerName);
|
|
56
59
|
if (!AgentClass) {
|
|
57
|
-
this.logger.warn(`No implementation found for provider: ${
|
|
60
|
+
this.logger.warn(`No implementation found for provider: ${providerName}. Skipping instance creation.`);
|
|
58
61
|
return;
|
|
59
62
|
}
|
|
60
63
|
try {
|
|
@@ -64,7 +67,7 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
64
67
|
description: agentEntity.description,
|
|
65
68
|
systemInstructions: agentEntity.systemInstructions,
|
|
66
69
|
role: agentEntity.role,
|
|
67
|
-
provider:
|
|
70
|
+
provider: providerName,
|
|
68
71
|
});
|
|
69
72
|
this.agentInstances.set(agentEntity.id, instance);
|
|
70
73
|
this.logger.debug(`Synchronized agent instance #${agentEntity.id}`);
|
|
@@ -72,23 +75,39 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
72
75
|
catch (error) {
|
|
73
76
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
74
77
|
this.logger.error(`Error synchronizing agent #${agentEntity.id}: ${errorMessage}`);
|
|
75
|
-
throw
|
|
78
|
+
throw new common_1.BadRequestException(`Failed to initialize agent instance: ${errorMessage}`);
|
|
76
79
|
}
|
|
77
80
|
}
|
|
78
81
|
async create(createAgentDto) {
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
const { modelId, providerId, ...rest } = createAgentDto;
|
|
83
|
+
const agentData = { ...rest };
|
|
84
|
+
if (modelId) {
|
|
85
|
+
agentData.model = { id: modelId };
|
|
86
|
+
}
|
|
87
|
+
if (providerId) {
|
|
88
|
+
agentData.provider = { id: providerId };
|
|
89
|
+
}
|
|
90
|
+
return await this.agentRepository.manager.transaction(async (manager) => {
|
|
91
|
+
const agent = manager.create(agent_entity_1.AgentEntity, agentData);
|
|
92
|
+
const savedAgent = await manager.save(agent);
|
|
93
|
+
const fullyLoadedAgent = await manager.findOne(agent_entity_1.AgentEntity, {
|
|
94
|
+
where: { id: savedAgent.id },
|
|
95
|
+
relations: AGENT_RELATIONS,
|
|
96
|
+
});
|
|
97
|
+
if (!fullyLoadedAgent) {
|
|
98
|
+
throw new Error(`Agent #${savedAgent.id} not found immediately after save`);
|
|
99
|
+
}
|
|
100
|
+
this.syncAgentInstance(fullyLoadedAgent);
|
|
101
|
+
return fullyLoadedAgent;
|
|
102
|
+
});
|
|
84
103
|
}
|
|
85
104
|
async findAll() {
|
|
86
|
-
return this.agentRepository.find({ relations:
|
|
105
|
+
return this.agentRepository.find({ relations: AGENT_RELATIONS });
|
|
87
106
|
}
|
|
88
107
|
async findOne(id) {
|
|
89
108
|
const agent = await this.agentRepository.findOne({
|
|
90
109
|
where: { id },
|
|
91
|
-
relations:
|
|
110
|
+
relations: AGENT_RELATIONS,
|
|
92
111
|
});
|
|
93
112
|
if (!agent) {
|
|
94
113
|
throw new common_1.NotFoundException(`Agent #${id} not found`);
|
|
@@ -96,21 +115,26 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
96
115
|
return agent;
|
|
97
116
|
}
|
|
98
117
|
async update(id, updateAgentDto) {
|
|
99
|
-
const { modelId, ...rest } = updateAgentDto;
|
|
118
|
+
const { modelId, providerId, ...rest } = updateAgentDto;
|
|
100
119
|
const updateData = { ...rest };
|
|
101
120
|
if (modelId) {
|
|
102
121
|
updateData.model = { id: modelId };
|
|
103
122
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
where: { id },
|
|
107
|
-
relations: ['model'],
|
|
108
|
-
});
|
|
109
|
-
if (!updatedAgent) {
|
|
110
|
-
throw new common_1.NotFoundException(`Agent #${id} not found`);
|
|
123
|
+
if (providerId) {
|
|
124
|
+
updateData.provider = { id: providerId };
|
|
111
125
|
}
|
|
112
|
-
this.
|
|
113
|
-
|
|
126
|
+
return await this.agentRepository.manager.transaction(async (manager) => {
|
|
127
|
+
await manager.update(agent_entity_1.AgentEntity, id, updateData);
|
|
128
|
+
const updatedAgent = await manager.findOne(agent_entity_1.AgentEntity, {
|
|
129
|
+
where: { id },
|
|
130
|
+
relations: AGENT_RELATIONS,
|
|
131
|
+
});
|
|
132
|
+
if (!updatedAgent) {
|
|
133
|
+
throw new common_1.NotFoundException(`Agent #${id} not found`);
|
|
134
|
+
}
|
|
135
|
+
this.syncAgentInstance(updatedAgent);
|
|
136
|
+
return updatedAgent;
|
|
137
|
+
});
|
|
114
138
|
}
|
|
115
139
|
async remove(id) {
|
|
116
140
|
const agent = await this.findOne(id);
|
|
@@ -138,7 +162,7 @@ let AgentsService = AgentsService_1 = class AgentsService {
|
|
|
138
162
|
this.logger.debug(`Agent instance #${agentId} not found in memory. Checking database...`);
|
|
139
163
|
const agentEntity = await this.agentRepository.findOne({
|
|
140
164
|
where: { id: agentId },
|
|
141
|
-
relations:
|
|
165
|
+
relations: AGENT_RELATIONS,
|
|
142
166
|
});
|
|
143
167
|
if (!agentEntity) {
|
|
144
168
|
throw new common_1.NotFoundException(`Agent #${agentId} not found`);
|