@bpinhosilva/agent-orchestrator 1.0.0-alpha.12 → 1.0.0-alpha.14

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.
Files changed (69) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/agents/agents.module.js +2 -1
  3. package/dist/agents/agents.service.js +64 -32
  4. package/dist/agents/dto/create-agent.dto.js +3 -3
  5. package/dist/agents/entities/agent.entity.js +8 -2
  6. package/dist/agents/implementations/claude.agent.js +142 -0
  7. package/dist/agents/implementations/gemini.agent.js +17 -8
  8. package/dist/app.module.js +21 -8
  9. package/dist/common/storage.service.js +26 -2
  10. package/dist/config/env.validation.js +46 -0
  11. package/dist/providers/entities/provider.entity.js +1 -1
  12. package/dist/providers/providers.service.js +44 -0
  13. package/dist/src/agents/agents.module.js +2 -1
  14. package/dist/src/agents/agents.module.js.map +1 -1
  15. package/dist/src/agents/agents.service.d.ts +3 -1
  16. package/dist/src/agents/agents.service.js +60 -31
  17. package/dist/src/agents/agents.service.js.map +1 -1
  18. package/dist/src/agents/dto/create-agent.dto.d.ts +1 -1
  19. package/dist/src/agents/dto/create-agent.dto.js +5 -5
  20. package/dist/src/agents/dto/create-agent.dto.js.map +1 -1
  21. package/dist/src/agents/entities/agent.entity.d.ts +2 -1
  22. package/dist/src/agents/entities/agent.entity.js +8 -2
  23. package/dist/src/agents/entities/agent.entity.js.map +1 -1
  24. package/dist/src/agents/enums/provider.enum.d.ts +1 -3
  25. package/dist/src/agents/enums/provider.enum.js +1 -3
  26. package/dist/src/agents/enums/provider.enum.js.map +1 -1
  27. package/dist/src/agents/implementations/claude.agent.d.ts +27 -0
  28. package/dist/src/agents/implementations/claude.agent.js +148 -0
  29. package/dist/src/agents/implementations/claude.agent.js.map +1 -0
  30. package/dist/src/agents/implementations/gemini.agent.d.ts +4 -1
  31. package/dist/src/agents/implementations/gemini.agent.js +18 -9
  32. package/dist/src/agents/implementations/gemini.agent.js.map +1 -1
  33. package/dist/src/app.module.js +21 -8
  34. package/dist/src/app.module.js.map +1 -1
  35. package/dist/src/common/storage.service.d.ts +13 -0
  36. package/dist/src/common/storage.service.js +26 -0
  37. package/dist/src/common/storage.service.js.map +1 -1
  38. package/dist/src/config/env.validation.d.ts +2 -0
  39. package/dist/src/config/env.validation.js +47 -0
  40. package/dist/src/config/env.validation.js.map +1 -0
  41. package/dist/src/main.js +5 -1
  42. package/dist/src/main.js.map +1 -1
  43. package/dist/src/providers/entities/provider.entity.js +1 -1
  44. package/dist/src/providers/entities/provider.entity.js.map +1 -1
  45. package/dist/src/providers/providers.service.d.ts +4 -1
  46. package/dist/src/providers/providers.service.js +43 -0
  47. package/dist/src/providers/providers.service.js.map +1 -1
  48. package/dist/src/tasks/comments.service.d.ts +3 -1
  49. package/dist/src/tasks/comments.service.js +17 -3
  50. package/dist/src/tasks/comments.service.js.map +1 -1
  51. package/dist/src/tasks/dto/create-task.dto.d.ts +0 -1
  52. package/dist/src/tasks/dto/create-task.dto.js +1 -8
  53. package/dist/src/tasks/dto/create-task.dto.js.map +1 -1
  54. package/dist/src/tasks/entities/task.entity.d.ts +0 -1
  55. package/dist/src/tasks/entities/task.entity.js +1 -6
  56. package/dist/src/tasks/entities/task.entity.js.map +1 -1
  57. package/dist/src/tasks/task-scheduler.service.d.ts +3 -1
  58. package/dist/src/tasks/task-scheduler.service.js +49 -13
  59. package/dist/src/tasks/task-scheduler.service.js.map +1 -1
  60. package/dist/src/uploads/uploads.controller.d.ts +2 -1
  61. package/dist/src/uploads/uploads.controller.js +17 -3
  62. package/dist/src/uploads/uploads.controller.js.map +1 -1
  63. package/dist/tasks/comments.service.js +17 -3
  64. package/dist/tasks/dto/create-task.dto.js +0 -6
  65. package/dist/tasks/entities/task.entity.js +0 -4
  66. package/dist/tasks/task-scheduler.service.js +54 -13
  67. package/dist/tsconfig.build.tsbuildinfo +1 -1
  68. package/dist/uploads/uploads.controller.js +18 -3
  69. package/package.json +5 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ # [1.0.0-alpha.14](https://github.com/bpinhosilva/agent-orchestrator/compare/v1.0.0-alpha.13...v1.0.0-alpha.14) (2026-03-27)
2
+
3
+
4
+ ### Features
5
+
6
+ * add CreateTaskDto ([1604945](https://github.com/bpinhosilva/agent-orchestrator/commit/1604945737b5df5480c6c0814c369902f7cc9142))
7
+ * implement transient agent instances with dynamic configurationn ([5d57b08](https://github.com/bpinhosilva/agent-orchestrator/commit/5d57b0886edf4b14d93ab76f245f4311b6657f7d))
8
+
9
+ # [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)
10
+
11
+
12
+ ### Features
13
+
14
+ * add Claude agent implementation with Anthropic SDK and refactor agent-provider ([1400a0d](https://github.com/bpinhosilva/agent-orchestrator/commit/1400a0dec6beb8393ddc4c5a23b9b860532079e8))
15
+
1
16
  # [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
17
 
3
18
 
@@ -13,6 +13,7 @@ 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
  const gemini_agent_1 = require("./implementations/gemini.agent");
16
+ const claude_agent_1 = 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, gemini_agent_1.GeminiAgent],
24
+ providers: [agents_service_1.AgentsService, gemini_agent_1.GeminiAgent, claude_agent_1.ClaudeAgent],
24
25
  exports: [agents_service_1.AgentsService],
25
26
  })
26
27
  ], AgentsModule);
@@ -19,19 +19,24 @@ 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 core_1 = require("@nestjs/core");
23
+ const AGENT_RELATIONS = ['model', 'provider'];
22
24
  let AgentsService = AgentsService_1 = class AgentsService {
23
- constructor(agentRepository) {
25
+ constructor(agentRepository, moduleRef) {
24
26
  this.agentRepository = agentRepository;
27
+ this.moduleRef = moduleRef;
25
28
  this.logger = new common_1.Logger(AgentsService_1.name);
26
29
  this.agentInstances = new Map();
27
30
  }
28
31
  async onModuleInit() {
29
32
  this.logger.log('Initializing Agent instances from database...');
30
- const agents = await this.agentRepository.find({ relations: ['model'] });
33
+ const agents = await this.agentRepository.find({
34
+ relations: AGENT_RELATIONS,
35
+ });
31
36
  for (const agentEntity of agents) {
32
37
  if (agentEntity.status !== 'inactive') {
33
38
  try {
34
- this.syncAgentInstance(agentEntity);
39
+ await this.syncAgentInstance(agentEntity);
35
40
  }
36
41
  catch (error) {
37
42
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -41,29 +46,32 @@ let AgentsService = AgentsService_1 = class AgentsService {
41
46
  }
42
47
  this.logger.log(`Initialized ${this.agentInstances.size} agent instances.`);
43
48
  }
44
- syncAgentInstance(agentEntity) {
49
+ async syncAgentInstance(agentEntity) {
45
50
  if (agentEntity.status === 'inactive') {
46
51
  this.agentInstances.delete(agentEntity.id);
47
52
  return;
48
53
  }
49
- const provider = agentEntity.provider;
50
- if (!provider) {
54
+ const providerName = agentEntity.provider?.name?.toLowerCase();
55
+ if (!providerName) {
51
56
  this.logger.warn(`No provider found for agent #${agentEntity.id}. Skipping instance creation.`);
52
57
  return;
53
58
  }
54
- const AgentClass = (0, agent_registry_1.getAgentImplementation)(provider);
59
+ const AgentClass = (0, agent_registry_1.getAgentImplementation)(providerName);
55
60
  if (!AgentClass) {
56
- this.logger.warn(`No implementation found for provider: ${provider}. Skipping instance creation.`);
61
+ this.logger.warn(`No implementation found for provider: ${providerName}. Skipping instance creation.`);
57
62
  return;
58
63
  }
59
64
  try {
60
- const instance = new AgentClass(agentEntity.model?.name);
65
+ // Use resolve for TRANSIENT scoped providers. This ensures we get a fresh instance
66
+ // which we then configure and store in our Map (making it a singleton for this ID).
67
+ const instance = await this.moduleRef.resolve(AgentClass);
61
68
  instance.updateConfig?.({
62
69
  name: agentEntity.name,
63
70
  description: agentEntity.description,
64
71
  systemInstructions: agentEntity.systemInstructions,
65
72
  role: agentEntity.role,
66
- provider: agentEntity.provider,
73
+ provider: providerName,
74
+ model: agentEntity.model?.name,
67
75
  });
68
76
  this.agentInstances.set(agentEntity.id, instance);
69
77
  this.logger.debug(`Synchronized agent instance #${agentEntity.id}`);
@@ -71,24 +79,41 @@ let AgentsService = AgentsService_1 = class AgentsService {
71
79
  catch (error) {
72
80
  const errorMessage = error instanceof Error ? error.message : String(error);
73
81
  this.logger.error(`Error synchronizing agent #${agentEntity.id}: ${errorMessage}`);
74
- throw error;
82
+ throw new common_1.BadRequestException(`Failed to initialize agent instance: ${errorMessage}`);
75
83
  }
76
84
  }
77
85
  async create(createAgentDto) {
78
- const agent = this.agentRepository.create(createAgentDto);
79
- const savedAgent = await this.agentRepository.save(agent);
80
- // Reload with relations for proper synchronization
81
- const fullyLoadedAgent = await this.findOne(savedAgent.id);
82
- this.syncAgentInstance(fullyLoadedAgent);
83
- return fullyLoadedAgent;
86
+ const { modelId, providerId, ...rest } = createAgentDto;
87
+ const agentData = { ...rest };
88
+ if (modelId) {
89
+ agentData.model = { id: modelId };
90
+ }
91
+ if (providerId) {
92
+ agentData.provider = { id: providerId };
93
+ }
94
+ return await this.agentRepository.manager.transaction(async (manager) => {
95
+ const agent = manager.create(agent_entity_1.AgentEntity, agentData);
96
+ const savedAgent = await manager.save(agent);
97
+ // Reload with full relations for proper synchronization
98
+ const fullyLoadedAgent = await manager.findOne(agent_entity_1.AgentEntity, {
99
+ where: { id: savedAgent.id },
100
+ relations: AGENT_RELATIONS,
101
+ });
102
+ if (!fullyLoadedAgent) {
103
+ throw new Error(`Agent #${savedAgent.id} not found immediately after save`);
104
+ }
105
+ // This will throw BadRequestException if instantiation fails, rolling back the transaction
106
+ await this.syncAgentInstance(fullyLoadedAgent);
107
+ return fullyLoadedAgent;
108
+ });
84
109
  }
85
110
  async findAll() {
86
- return this.agentRepository.find({ relations: ['model'] });
111
+ return this.agentRepository.find({ relations: AGENT_RELATIONS });
87
112
  }
88
113
  async findOne(id) {
89
114
  const agent = await this.agentRepository.findOne({
90
115
  where: { id },
91
- relations: ['model'],
116
+ relations: AGENT_RELATIONS,
92
117
  });
93
118
  if (!agent) {
94
119
  throw new common_1.NotFoundException(`Agent #${id} not found`);
@@ -96,21 +121,27 @@ let AgentsService = AgentsService_1 = class AgentsService {
96
121
  return agent;
97
122
  }
98
123
  async update(id, updateAgentDto) {
99
- const { modelId, ...rest } = updateAgentDto;
124
+ const { modelId, providerId, ...rest } = updateAgentDto;
100
125
  const updateData = { ...rest };
101
126
  if (modelId) {
102
127
  updateData.model = { id: modelId };
103
128
  }
104
- await this.agentRepository.update(id, updateData);
105
- const updatedAgent = await this.agentRepository.findOne({
106
- where: { id },
107
- relations: ['model'],
108
- });
109
- if (!updatedAgent) {
110
- throw new common_1.NotFoundException(`Agent #${id} not found`);
129
+ if (providerId) {
130
+ updateData.provider = { id: providerId };
111
131
  }
112
- this.syncAgentInstance(updatedAgent);
113
- return updatedAgent;
132
+ return await this.agentRepository.manager.transaction(async (manager) => {
133
+ await manager.update(agent_entity_1.AgentEntity, id, updateData);
134
+ const updatedAgent = await manager.findOne(agent_entity_1.AgentEntity, {
135
+ where: { id },
136
+ relations: AGENT_RELATIONS,
137
+ });
138
+ if (!updatedAgent) {
139
+ throw new common_1.NotFoundException(`Agent #${id} not found`);
140
+ }
141
+ // This will throw BadRequestException if instantiation fails, rolling back the transaction
142
+ await this.syncAgentInstance(updatedAgent);
143
+ return updatedAgent;
144
+ });
114
145
  }
115
146
  async remove(id) {
116
147
  const agent = await this.findOne(id);
@@ -138,7 +169,7 @@ let AgentsService = AgentsService_1 = class AgentsService {
138
169
  this.logger.debug(`Agent instance #${agentId} not found in memory. Checking database...`);
139
170
  const agentEntity = await this.agentRepository.findOne({
140
171
  where: { id: agentId },
141
- relations: ['model'],
172
+ relations: AGENT_RELATIONS,
142
173
  });
143
174
  if (!agentEntity) {
144
175
  throw new common_1.NotFoundException(`Agent #${agentId} not found`);
@@ -146,7 +177,7 @@ let AgentsService = AgentsService_1 = class AgentsService {
146
177
  if (agentEntity.status === 'inactive') {
147
178
  throw new common_1.NotFoundException(`Agent #${agentId} is currently inactive and cannot be probed.`);
148
179
  }
149
- this.syncAgentInstance(agentEntity);
180
+ await this.syncAgentInstance(agentEntity);
150
181
  agent = this.agentInstances.get(agentId);
151
182
  if (!agent) {
152
183
  throw new common_1.NotFoundException(`Failed to initialize agent #${agentId} after database fetch`);
@@ -159,5 +190,6 @@ exports.AgentsService = AgentsService;
159
190
  exports.AgentsService = AgentsService = AgentsService_1 = __decorate([
160
191
  (0, common_1.Injectable)(),
161
192
  __param(0, (0, typeorm_1.InjectRepository)(agent_entity_1.AgentEntity)),
162
- __metadata("design:paramtypes", [typeorm_2.Repository])
193
+ __metadata("design:paramtypes", [typeorm_2.Repository,
194
+ core_1.ModuleRef])
163
195
  ], AgentsService);
@@ -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.IsString)(),
49
- (0, class_validator_1.IsOptional)(),
48
+ (0, class_validator_1.IsUUID)(),
49
+ (0, class_validator_1.IsNotEmpty)(),
50
50
  __metadata("design:type", String)
51
- ], CreateAgentDto.prototype, "provider", void 0);
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.Column)({ type: 'text', nullable: true }),
44
- __metadata("design:type", String)
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,142 @@
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 config_1 = require("@nestjs/config");
20
+ const agent_registry_1 = require("../registry/agent.registry");
21
+ let ClaudeAgent = ClaudeAgent_1 = class ClaudeAgent {
22
+ constructor(configService, model = 'claude-opus-4-6') {
23
+ this.configService = configService;
24
+ this.logger = new common_1.Logger(ClaudeAgent_1.name);
25
+ this.name = 'ClaudeAgent';
26
+ this.provider = 'anthropic';
27
+ this.model = model;
28
+ }
29
+ validateApiKey() {
30
+ const apiKey = this.configService.get('ANTHROPIC_API_KEY');
31
+ if (!apiKey) {
32
+ this.logger.error('ANTHROPIC_API_KEY environment variable is not set');
33
+ throw new Error('ANTHROPIC_API_KEY is required to initialize ClaudeAgent');
34
+ }
35
+ return apiKey;
36
+ }
37
+ getName() {
38
+ return this.name;
39
+ }
40
+ getDescription() {
41
+ return this.description || '';
42
+ }
43
+ getSystemInstructions() {
44
+ return this.systemInstructions || '';
45
+ }
46
+ getRole() {
47
+ return this.role || '';
48
+ }
49
+ getProvider() {
50
+ return this.provider;
51
+ }
52
+ getModel() {
53
+ return this.model;
54
+ }
55
+ updateConfig(config) {
56
+ if (config['name'])
57
+ this.name = config['name'];
58
+ if (config['description'])
59
+ this.description = config['description'];
60
+ if (config['systemInstructions'])
61
+ this.systemInstructions = config['systemInstructions'];
62
+ if (config['role'])
63
+ this.role = config['role'];
64
+ if (config['provider'])
65
+ this.provider = config['provider'];
66
+ if (config['model'])
67
+ this.model = config['model'];
68
+ }
69
+ buildSystemPrompt() {
70
+ return [
71
+ `Your name is ${this.name}.`,
72
+ this.role ? `Your role is: ${this.role}.` : '',
73
+ this.description ? `Description of yourself: ${this.description}.` : '',
74
+ this.systemInstructions
75
+ ? `Instructions:\n${this.systemInstructions}`
76
+ : '',
77
+ ]
78
+ .filter(Boolean)
79
+ .join('\n');
80
+ }
81
+ async processText(input) {
82
+ this.validateApiKey();
83
+ this.logger.debug(`Processing input with ClaudeAgent. Model: ${this.model}`);
84
+ try {
85
+ const systemPrompt = this.buildSystemPrompt();
86
+ let resultContent = '';
87
+ let resultMetadata = {};
88
+ const q = (0, claude_agent_sdk_1.query)({
89
+ prompt: input,
90
+ options: {
91
+ model: this.model,
92
+ systemPrompt,
93
+ permissionMode: 'bypassPermissions',
94
+ persistSession: false,
95
+ tools: [],
96
+ },
97
+ });
98
+ for await (const message of q) {
99
+ if (message.type === 'result' && message.subtype === 'success') {
100
+ resultContent = message.result;
101
+ resultMetadata = {
102
+ model: this.model,
103
+ usage: message.usage,
104
+ totalCostUsd: message.total_cost_usd,
105
+ numTurns: message.num_turns,
106
+ };
107
+ }
108
+ }
109
+ return {
110
+ content: resultContent,
111
+ metadata: resultMetadata,
112
+ };
113
+ }
114
+ catch (error) {
115
+ this.logger.error(`Claude Error: ${error}`);
116
+ throw error;
117
+ }
118
+ }
119
+ isFeatureSupported(feature) {
120
+ void feature;
121
+ return false;
122
+ }
123
+ async performTask(task, project) {
124
+ this.logger.debug(`Performing task: ${task.title} for project: ${project.title}`);
125
+ const prompt = `
126
+ Task: ${task.title}
127
+ Description: ${task.description}
128
+ Project: ${project.title}
129
+ Project Description: ${project.description}
130
+
131
+ Please perform the task and provide the output.
132
+ `;
133
+ return this.processText(prompt);
134
+ }
135
+ };
136
+ exports.ClaudeAgent = ClaudeAgent;
137
+ exports.ClaudeAgent = ClaudeAgent = ClaudeAgent_1 = __decorate([
138
+ (0, common_1.Injectable)({ scope: common_1.Scope.TRANSIENT }),
139
+ (0, agent_registry_1.RegisterAgent)('anthropic'),
140
+ __param(1, (0, common_1.Optional)()),
141
+ __metadata("design:paramtypes", [config_1.ConfigService, String])
142
+ ], ClaudeAgent);
@@ -16,20 +16,28 @@ Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.GeminiAgent = void 0;
17
17
  const genai_1 = require("@google/genai");
18
18
  const common_1 = require("@nestjs/common");
19
+ const config_1 = require("@nestjs/config");
19
20
  const agent_registry_1 = require("../registry/agent.registry");
20
21
  let GeminiAgent = GeminiAgent_1 = class GeminiAgent {
21
- constructor(model = 'gemini-2.5-flash-lite') {
22
+ constructor(configService, model = 'gemini-2.5-flash-lite') {
23
+ this.configService = configService;
22
24
  this.logger = new common_1.Logger(GeminiAgent_1.name);
25
+ this.genAI = null;
23
26
  this.name = 'GeminiAgent';
24
- this.provider = 'Google';
27
+ this.provider = 'google';
25
28
  this.enableGrounding = true;
26
29
  this.model = model;
27
- const apiKey = process.env.GEMINI_API_KEY;
30
+ }
31
+ getGenAI() {
32
+ if (this.genAI)
33
+ return this.genAI;
34
+ const apiKey = this.configService.get('GEMINI_API_KEY');
28
35
  if (!apiKey) {
29
36
  this.logger.error('GEMINI_API_KEY environment variable is not set');
30
37
  throw new Error('GEMINI_API_KEY is required to initialize GeminiAgent');
31
38
  }
32
39
  this.genAI = new genai_1.GoogleGenAI({ apiKey });
40
+ return this.genAI;
33
41
  }
34
42
  getName() {
35
43
  return this.name;
@@ -74,7 +82,8 @@ let GeminiAgent = GeminiAgent_1 = class GeminiAgent {
74
82
  if (tools.length > 0) {
75
83
  this.logger.debug(`Adding tools to request: ${JSON.stringify(tools)}`);
76
84
  }
77
- const response = await this.genAI.models.generateContent({
85
+ const genAI = this.getGenAI();
86
+ const response = await genAI.models.generateContent({
78
87
  model: this.model,
79
88
  contents,
80
89
  config: {
@@ -172,8 +181,8 @@ Please perform the task and provide the output.
172
181
  };
173
182
  exports.GeminiAgent = GeminiAgent;
174
183
  exports.GeminiAgent = GeminiAgent = GeminiAgent_1 = __decorate([
175
- (0, common_1.Injectable)(),
176
- (0, agent_registry_1.RegisterAgent)('Google'),
177
- __param(0, (0, common_1.Optional)()),
178
- __metadata("design:paramtypes", [String])
184
+ (0, common_1.Injectable)({ scope: common_1.Scope.TRANSIENT }),
185
+ (0, agent_registry_1.RegisterAgent)('google'),
186
+ __param(1, (0, common_1.Optional)()),
187
+ __metadata("design:paramtypes", [config_1.ConfigService, String])
179
188
  ], GeminiAgent);
@@ -22,21 +22,34 @@ const users_module_1 = require("./users/users.module");
22
22
  const common_module_1 = require("./common/common.module");
23
23
  const uploads_module_1 = require("./uploads/uploads.module");
24
24
  const schedule_1 = require("@nestjs/schedule");
25
+ const config_1 = require("@nestjs/config");
26
+ const env_validation_1 = require("./config/env.validation");
25
27
  let AppModule = class AppModule {
26
28
  };
27
29
  exports.AppModule = AppModule;
28
30
  exports.AppModule = AppModule = __decorate([
29
31
  (0, common_1.Module)({
30
32
  imports: [
33
+ config_1.ConfigModule.forRoot({
34
+ isGlobal: true,
35
+ validationSchema: env_validation_1.envValidationSchema,
36
+ }),
31
37
  schedule_1.ScheduleModule.forRoot(),
32
- typeorm_1.TypeOrmModule.forRoot({
33
- type: process.env.DATABASE_URL ? 'postgres' : 'sqlite',
34
- database: process.env.DATABASE_URL
35
- ? undefined
36
- : (0, path_1.join)(process.cwd(), 'local.sqlite'),
37
- url: process.env.DATABASE_URL,
38
- autoLoadEntities: true,
39
- synchronize: true, // Use only in development
38
+ typeorm_1.TypeOrmModule.forRootAsync({
39
+ imports: [config_1.ConfigModule],
40
+ inject: [config_1.ConfigService],
41
+ useFactory: (configService) => {
42
+ const databaseUrl = configService.get('DATABASE_URL');
43
+ return {
44
+ type: databaseUrl ? 'postgres' : 'sqlite',
45
+ database: databaseUrl
46
+ ? undefined
47
+ : (0, path_1.join)(process.cwd(), 'local.sqlite'),
48
+ url: databaseUrl,
49
+ autoLoadEntities: true,
50
+ synchronize: configService.get('NODE_ENV') !== 'production',
51
+ };
52
+ },
40
53
  }),
41
54
  serve_static_1.ServeStaticModule.forRoot({
42
55
  rootPath: (0, path_1.join)(__dirname, '..', '..', 'ui', 'dist'),
@@ -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([
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.envValidationSchema = void 0;
37
+ const Joi = __importStar(require("joi"));
38
+ exports.envValidationSchema = Joi.object({
39
+ PORT: Joi.number().default(3000),
40
+ DATABASE_URL: Joi.string().optional(),
41
+ GEMINI_API_KEY: Joi.string().optional(),
42
+ ANTHROPIC_API_KEY: Joi.string().optional(),
43
+ NODE_ENV: Joi.string()
44
+ .valid('development', 'production', 'test', 'provision')
45
+ .default('development'),
46
+ });
@@ -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);