repoburg 1.3.155 → 1.3.156
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/backend/dist/src/app.module.js +0 -2
- package/backend/dist/src/app.module.js.map +1 -1
- package/backend/dist/src/common/cache/cache-invalidation.service.d.ts +1 -4
- package/backend/dist/src/common/cache/cache-invalidation.service.js +0 -12
- package/backend/dist/src/common/cache/cache-invalidation.service.js.map +1 -1
- package/backend/dist/src/common/cache/cache-invalidation.subscriber.js +0 -6
- package/backend/dist/src/common/cache/cache-invalidation.subscriber.js.map +1 -1
- package/backend/dist/src/core-entities/enums.d.ts +0 -7
- package/backend/dist/src/core-entities/enums.js +1 -9
- package/backend/dist/src/core-entities/enums.js.map +1 -1
- package/backend/dist/src/interactive-chat/chat.service.d.ts +20 -1
- package/backend/dist/src/interactive-chat/chat.service.js +187 -6
- package/backend/dist/src/interactive-chat/chat.service.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/invoke-subagent.handler.d.ts +3 -3
- package/backend/dist/src/llm-orchestration/action-handlers/invoke-subagent.handler.js +6 -6
- package/backend/dist/src/llm-orchestration/action-handlers/invoke-subagent.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/hooks/follow-up-post-execution.hook.d.ts +3 -1
- package/backend/dist/src/llm-orchestration/hooks/follow-up-post-execution.hook.js +13 -3
- package/backend/dist/src/llm-orchestration/hooks/follow-up-post-execution.hook.js.map +1 -1
- package/backend/dist/src/llm-orchestration/hooks/frontend-notification.hook.d.ts +3 -1
- package/backend/dist/src/llm-orchestration/hooks/frontend-notification.hook.js +29 -2
- package/backend/dist/src/llm-orchestration/hooks/frontend-notification.hook.js.map +1 -1
- package/backend/dist/src/sub-agents/sub-agent.entity.js.map +1 -1
- package/backend/dist/src/sub-agents/sub-agents.module.js +5 -17
- package/backend/dist/src/sub-agents/sub-agents.module.js.map +1 -1
- package/backend/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/backend/dist/src/sub-agents/sub-agent-run.entity.d.ts +0 -21
- package/backend/dist/src/sub-agents/sub-agent-run.entity.js +0 -147
- package/backend/dist/src/sub-agents/sub-agent-run.entity.js.map +0 -1
- package/backend/dist/src/sub-agents/sub-agent-runner.service.d.ts +0 -49
- package/backend/dist/src/sub-agents/sub-agent-runner.service.js +0 -690
- package/backend/dist/src/sub-agents/sub-agent-runner.service.js.map +0 -1
- package/backend/dist/src/sub-agents/sub-agent-runs.controller.d.ts +0 -19
- package/backend/dist/src/sub-agents/sub-agent-runs.controller.js +0 -153
- package/backend/dist/src/sub-agents/sub-agent-runs.controller.js.map +0 -1
- package/backend/dist/src/sub-agents/sub-agent-runs.service.d.ts +0 -23
- package/backend/dist/src/sub-agents/sub-agent-runs.service.js +0 -132
- package/backend/dist/src/sub-agents/sub-agent-runs.service.js.map +0 -1
|
@@ -1,690 +0,0 @@
|
|
|
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 SubAgentRunner_1;
|
|
15
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.SubAgentRunner = void 0;
|
|
17
|
-
const common_1 = require("@nestjs/common");
|
|
18
|
-
const core_1 = require("@nestjs/core");
|
|
19
|
-
const llm_provider_interface_1 = require("../llm-provider/llm-provider.interface");
|
|
20
|
-
const sub_agents_service_1 = require("./sub-agents.service");
|
|
21
|
-
const sub_agent_runs_service_1 = require("./sub-agent-runs.service");
|
|
22
|
-
const sessions_service_1 = require("../sessions/sessions.service");
|
|
23
|
-
const system_prompts_service_1 = require("../system-prompts/system-prompts.service");
|
|
24
|
-
const tool_schema_service_1 = require("../llm-orchestration/tool-schema.service");
|
|
25
|
-
const history_compression_service_1 = require("../llm-orchestration/history-compression.service");
|
|
26
|
-
const application_state_service_1 = require("../application-state/application-state.service");
|
|
27
|
-
const mcp_tool_action_handler_1 = require("../llm-orchestration/action-handlers/mcp-tool-action.handler");
|
|
28
|
-
const mcp_service_1 = require("../mcp/mcp.service");
|
|
29
|
-
const llm_orchestration_interfaces_1 = require("../llm-orchestration/llm-orchestration.interfaces");
|
|
30
|
-
const typeorm_1 = require("@nestjs/typeorm");
|
|
31
|
-
const typeorm_2 = require("typeorm");
|
|
32
|
-
const session_input_entity_1 = require("../core-entities/session-input.entity");
|
|
33
|
-
const ai_action_entity_1 = require("../core-entities/ai-action.entity");
|
|
34
|
-
const ai_actions_service_1 = require("../ai-actions/ai-actions.service");
|
|
35
|
-
const execution_logs_service_1 = require("../execution-logs/execution-logs.service");
|
|
36
|
-
const events_gateway_1 = require("../events/events.gateway");
|
|
37
|
-
const session_input_context_service_1 = require("../session-inputs/session-input-context.service");
|
|
38
|
-
const MAX_ITERATIONS = 1000;
|
|
39
|
-
let SubAgentRunner = SubAgentRunner_1 = class SubAgentRunner {
|
|
40
|
-
constructor(subAgentsService, subAgentRunsService, sessionsService, applicationStateService, executionLogsService, eventsGateway, llmProvider, moduleRef, sessionInputsRepository, aiActionsRepository) {
|
|
41
|
-
this.subAgentsService = subAgentsService;
|
|
42
|
-
this.subAgentRunsService = subAgentRunsService;
|
|
43
|
-
this.sessionsService = sessionsService;
|
|
44
|
-
this.applicationStateService = applicationStateService;
|
|
45
|
-
this.executionLogsService = executionLogsService;
|
|
46
|
-
this.eventsGateway = eventsGateway;
|
|
47
|
-
this.llmProvider = llmProvider;
|
|
48
|
-
this.moduleRef = moduleRef;
|
|
49
|
-
this.sessionInputsRepository = sessionInputsRepository;
|
|
50
|
-
this.aiActionsRepository = aiActionsRepository;
|
|
51
|
-
this.logger = new common_1.Logger(SubAgentRunner_1.name);
|
|
52
|
-
}
|
|
53
|
-
getHandlerRegistry() {
|
|
54
|
-
return this.moduleRef.get('ACTION_HANDLER_REGISTRY', { strict: false });
|
|
55
|
-
}
|
|
56
|
-
getToolSchemaService() {
|
|
57
|
-
return this.moduleRef.get(tool_schema_service_1.ToolSchemaService, { strict: false });
|
|
58
|
-
}
|
|
59
|
-
getHistoryCompressionService() {
|
|
60
|
-
return this.moduleRef.get(history_compression_service_1.HistoryCompressionService, { strict: false });
|
|
61
|
-
}
|
|
62
|
-
getSystemPromptsService() {
|
|
63
|
-
return this.moduleRef.get(system_prompts_service_1.SystemPromptsService, { strict: false });
|
|
64
|
-
}
|
|
65
|
-
getMcpService() {
|
|
66
|
-
return this.moduleRef.get(mcp_service_1.McpService, { strict: false });
|
|
67
|
-
}
|
|
68
|
-
getSessionInputContextService() {
|
|
69
|
-
return this.moduleRef.get(session_input_context_service_1.SessionInputContextService, { strict: false });
|
|
70
|
-
}
|
|
71
|
-
async runAgent(agentName, prompt, parentSessionId, options) {
|
|
72
|
-
this.logger.log(`runAgent called for "${agentName}" from parent session ${parentSessionId}`);
|
|
73
|
-
const subAgent = await this.subAgentsService.getAgentByName(agentName);
|
|
74
|
-
if (!subAgent) {
|
|
75
|
-
const availableAgents = (await this.subAgentsService.findActive())
|
|
76
|
-
.map((a) => a.name)
|
|
77
|
-
.join(', ');
|
|
78
|
-
return {
|
|
79
|
-
content: `Sub-agent "${agentName}" not found or not active. Available: ${availableAgents}`,
|
|
80
|
-
success: false,
|
|
81
|
-
iterations: 0,
|
|
82
|
-
childSessionId: '',
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
const startTime = Date.now();
|
|
86
|
-
const handlerRegistry = this.getHandlerRegistry();
|
|
87
|
-
const toolSchemaService = this.getToolSchemaService();
|
|
88
|
-
const historyCompressionService = this.getHistoryCompressionService();
|
|
89
|
-
const systemPromptsService = this.getSystemPromptsService();
|
|
90
|
-
const sessionInputContextService = this.getSessionInputContextService();
|
|
91
|
-
let childSession;
|
|
92
|
-
let existingHistory = [];
|
|
93
|
-
if (options?.sessionId) {
|
|
94
|
-
childSession = await this.sessionsService.findOne(options.sessionId);
|
|
95
|
-
if (!childSession) {
|
|
96
|
-
return {
|
|
97
|
-
content: `Session "${options.sessionId}" not found. Cannot reuse a non-existent session.`,
|
|
98
|
-
success: false,
|
|
99
|
-
iterations: 0,
|
|
100
|
-
childSessionId: options.sessionId,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
this.logger.log(`Reusing existing session ${childSession.id} for sub-agent "${agentName}"`);
|
|
104
|
-
const existingInputs = await this.sessionInputsRepository.find({
|
|
105
|
-
where: { session: { id: childSession.id }, is_discarded: false },
|
|
106
|
-
order: { sequence_number: 'ASC' },
|
|
107
|
-
});
|
|
108
|
-
existingHistory = this.reconstructHistory(existingInputs);
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
childSession = await this.sessionsService.create({
|
|
112
|
-
session_title: `Sub-Agent: ${agentName}`,
|
|
113
|
-
system_prompt_id: subAgent.system_prompt_id || undefined,
|
|
114
|
-
default_initial_context_template_id: subAgent.context_template_id || undefined,
|
|
115
|
-
default_followup_context_template_id: subAgent.followup_context_template_id || undefined,
|
|
116
|
-
model_id: subAgent.model_id || undefined,
|
|
117
|
-
sub_agent_id: subAgent.id,
|
|
118
|
-
parent_session_id: parentSessionId,
|
|
119
|
-
});
|
|
120
|
-
this.logger.log(`Created child session ${childSession.id} for sub-agent "${agentName}"`);
|
|
121
|
-
}
|
|
122
|
-
await this.subAgentRunsService.create({
|
|
123
|
-
parent_session_id: parentSessionId,
|
|
124
|
-
child_session_id: childSession.id,
|
|
125
|
-
sub_agent_id: subAgent.id,
|
|
126
|
-
agent_name: agentName,
|
|
127
|
-
initial_prompt: prompt,
|
|
128
|
-
});
|
|
129
|
-
let systemInstruction = '';
|
|
130
|
-
if (subAgent.system_prompt_id) {
|
|
131
|
-
const rendered = await systemPromptsService.findOneWithSession(subAgent.system_prompt_id, childSession.id, childSession.session_title);
|
|
132
|
-
systemInstruction = rendered?.prompt_content || '';
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
const defaultPrompt = await systemPromptsService.findDefaultWithSession(childSession.id, childSession.session_title);
|
|
136
|
-
systemInstruction = defaultPrompt?.prompt_content || '';
|
|
137
|
-
}
|
|
138
|
-
const mcpService = this.getMcpService();
|
|
139
|
-
let tools;
|
|
140
|
-
this.logger.log(`Sub-agent "${agentName}" tool config: enabled_tools=${JSON.stringify(subAgent.enabled_tools)}, enabled_mcp_tools=${JSON.stringify(subAgent.enabled_mcp_tools)}`);
|
|
141
|
-
if (subAgent.enabled_tools === null) {
|
|
142
|
-
tools = toolSchemaService.generateToolDefinitions(handlerRegistry);
|
|
143
|
-
this.logger.log(`Sub-agent "${agentName}" using ALL built-in tools (${handlerRegistry.size} available).`);
|
|
144
|
-
}
|
|
145
|
-
else if (subAgent.enabled_tools.length > 0) {
|
|
146
|
-
const filteredHandlers = new Map();
|
|
147
|
-
for (const toolName of subAgent.enabled_tools) {
|
|
148
|
-
const handler = handlerRegistry.get(toolName);
|
|
149
|
-
if (handler) {
|
|
150
|
-
filteredHandlers.set(toolName, handler);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
tools = toolSchemaService.generateToolDefinitions(filteredHandlers);
|
|
154
|
-
this.logger.log(`Sub-agent "${agentName}" using ${filteredHandlers.size}/${subAgent.enabled_tools.length} filtered built-in tools.`);
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
this.logger.log(`Sub-agent "${agentName}" has NO built-in tools (enabled_tools is empty array).`);
|
|
158
|
-
}
|
|
159
|
-
if (subAgent.enabled_mcp_tools !== null &&
|
|
160
|
-
subAgent.enabled_mcp_tools !== undefined) {
|
|
161
|
-
this.logger.log(`Sub-agent "${agentName}" entering MCP tool block (enabled_mcp_tools="${subAgent.enabled_mcp_tools}").`);
|
|
162
|
-
try {
|
|
163
|
-
const allMcpTools = await mcpService.getActiveMcpToolDefinitions();
|
|
164
|
-
this.logger.log(`Sub-agent "${agentName}" found ${allMcpTools.length} active MCP tool definitions: [${allMcpTools.map((t) => t.function.name).join(', ')}]`);
|
|
165
|
-
if (allMcpTools.length > 0) {
|
|
166
|
-
let enabledMcpToolNames;
|
|
167
|
-
if (subAgent.enabled_mcp_tools === 'all') {
|
|
168
|
-
enabledMcpToolNames = allMcpTools.map((t) => t.function.name);
|
|
169
|
-
this.logger.log(`Sub-agent "${agentName}" MCP mode: ALL — enabling ${enabledMcpToolNames.length} MCP tools.`);
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
const parsedMcpTools = this.subAgentsService.parseEnabledMcpTools(subAgent.enabled_mcp_tools) || [];
|
|
173
|
-
const allToolNames = allMcpTools.map((t) => t.function.name);
|
|
174
|
-
this.logger.log(`Sub-agent "${agentName}" MCP mode: SPECIFIC — parsedEnabledMcpTools="${subAgent.enabled_mcp_tools}" → parsed=${JSON.stringify(parsedMcpTools)}, allToolNames=${JSON.stringify(allToolNames)}`);
|
|
175
|
-
enabledMcpToolNames = this.resolveMcpToolNames(parsedMcpTools, allToolNames);
|
|
176
|
-
this.logger.log(`Sub-agent "${agentName}" MCP mode: SPECIFIC — resolved to ${enabledMcpToolNames.length} MCP tools: [${enabledMcpToolNames.join(', ')}]`);
|
|
177
|
-
}
|
|
178
|
-
const filteredMcpTools = allMcpTools.filter((tool) => enabledMcpToolNames.includes(tool.function.name));
|
|
179
|
-
this.logger.log(`Sub-agent "${agentName}" filtered to ${filteredMcpTools.length} MCP tool definitions: [${filteredMcpTools.map((t) => t.function.name).join(', ')}]`);
|
|
180
|
-
if (filteredMcpTools.length > 0) {
|
|
181
|
-
tools = [...(tools || []), ...filteredMcpTools];
|
|
182
|
-
this.logger.log(`Added ${filteredMcpTools.length} MCP tool definitions for sub-agent "${agentName}".`);
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
this.logger.warn(`Sub-agent "${agentName}" has MCP tools enabled but 0 matched after filtering. enabled_mcp_tools="${subAgent.enabled_mcp_tools}"`);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
this.logger.log(`Sub-agent "${agentName}" has MCP tools enabled but 0 active MCP tool definitions found on server.`);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
catch (error) {
|
|
193
|
-
this.logger.warn(`Failed to load MCP tool definitions for sub-agent "${agentName}": ${error.message}. Continuing without MCP tools.`);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
this.logger.log(`Sub-agent "${agentName}" skipping MCP tools (enabled_mcp_tools is ${subAgent.enabled_mcp_tools === null ? 'null' : 'undefined'}).`);
|
|
198
|
-
}
|
|
199
|
-
const builtInToolCount = tools
|
|
200
|
-
? tools.filter((t) => !t.function.name.includes('__')).length
|
|
201
|
-
: 0;
|
|
202
|
-
const mcpToolCount = tools
|
|
203
|
-
? tools.filter((t) => t.function.name.includes('__')).length
|
|
204
|
-
: 0;
|
|
205
|
-
this.logger.log(`Sub-agent "${agentName}" total tools for LLM: ${tools?.length ?? 0} (built-in: ${builtInToolCount}, MCP: ${mcpToolCount})`);
|
|
206
|
-
let initialUserMessage;
|
|
207
|
-
let generatedContextString = null;
|
|
208
|
-
let contextTemplate = null;
|
|
209
|
-
if (subAgent.context_template_id) {
|
|
210
|
-
try {
|
|
211
|
-
contextTemplate = subAgent.contextTemplate || null;
|
|
212
|
-
let adHocContextDefinition;
|
|
213
|
-
if (options?.masterContextDefinition) {
|
|
214
|
-
adHocContextDefinition = JSON.stringify(options.masterContextDefinition);
|
|
215
|
-
}
|
|
216
|
-
else if (options?.contextFiles && options.contextFiles.length > 0) {
|
|
217
|
-
adHocContextDefinition = JSON.stringify({
|
|
218
|
-
files: options.contextFiles,
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
const generatedContext = await sessionInputContextService.generateContext({
|
|
222
|
-
user_prompt: prompt,
|
|
223
|
-
context_template_id: subAgent.context_template_id,
|
|
224
|
-
ad_hoc_context_definition: adHocContextDefinition,
|
|
225
|
-
execution_strategy: 'auto_apply',
|
|
226
|
-
}, contextTemplate);
|
|
227
|
-
initialUserMessage = generatedContext;
|
|
228
|
-
generatedContextString = generatedContext;
|
|
229
|
-
this.logger.log(`Sub-agent "${agentName}" initial prompt rendered through context template "${contextTemplate?.template_name || subAgent.context_template_id}".`);
|
|
230
|
-
}
|
|
231
|
-
catch (error) {
|
|
232
|
-
this.logger.error(`Failed to render context template for sub-agent "${agentName}": ${error.message}. Falling back to raw prompt.`, error.stack);
|
|
233
|
-
initialUserMessage = prompt;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
else {
|
|
237
|
-
initialUserMessage = prompt;
|
|
238
|
-
}
|
|
239
|
-
const history = [
|
|
240
|
-
...existingHistory,
|
|
241
|
-
{ role: 'user', parts: [{ text: initialUserMessage }] },
|
|
242
|
-
];
|
|
243
|
-
await this.sessionInputsRepository.save(this.sessionInputsRepository.create({
|
|
244
|
-
session: { id: childSession.id },
|
|
245
|
-
role: 'user',
|
|
246
|
-
user_prompt: prompt,
|
|
247
|
-
generated_context_string: generatedContextString,
|
|
248
|
-
execution_strategy: 'auto_apply',
|
|
249
|
-
context_template_id: subAgent.context_template_id || undefined,
|
|
250
|
-
...(subAgent.context_template_id
|
|
251
|
-
? { contextTemplate: { id: subAgent.context_template_id } }
|
|
252
|
-
: {}),
|
|
253
|
-
}));
|
|
254
|
-
this.eventsGateway.sendToAll('refresh-ui', {
|
|
255
|
-
sessionId: childSession.id,
|
|
256
|
-
});
|
|
257
|
-
this.eventsGateway.sendToAll('refresh-ui', {
|
|
258
|
-
sessionId: parentSessionId,
|
|
259
|
-
});
|
|
260
|
-
let iterations = 0;
|
|
261
|
-
let finalContent = '';
|
|
262
|
-
let success = true;
|
|
263
|
-
await this.sessionsService.update(childSession.id, { is_running: true });
|
|
264
|
-
this.eventsGateway.sendToAll('llm-generation-started', {
|
|
265
|
-
sessionInputId: `subagent-${childSession.id}`,
|
|
266
|
-
sessionId: childSession.id,
|
|
267
|
-
isStreaming: false,
|
|
268
|
-
});
|
|
269
|
-
try {
|
|
270
|
-
const abortController = new AbortController();
|
|
271
|
-
const executionStrategy = await this.applicationStateService.getExecutionStrategy();
|
|
272
|
-
while (iterations < MAX_ITERATIONS) {
|
|
273
|
-
iterations++;
|
|
274
|
-
this.logger.log(`Sub-agent "${agentName}" iteration ${iterations}/${MAX_ITERATIONS}`);
|
|
275
|
-
const compressedHistory = await historyCompressionService.compress(history);
|
|
276
|
-
const llmResponse = await this.callWithRetry({
|
|
277
|
-
prompt: '',
|
|
278
|
-
systemInstruction,
|
|
279
|
-
history: compressedHistory,
|
|
280
|
-
modelId: childSession.model_id || undefined,
|
|
281
|
-
tools,
|
|
282
|
-
abortController,
|
|
283
|
-
}, childSession.id);
|
|
284
|
-
if (!llmResponse.text &&
|
|
285
|
-
(!llmResponse.tool_calls || llmResponse.tool_calls.length === 0)) {
|
|
286
|
-
this.logger.log(`Sub-agent "${agentName}" returned empty response with no tool calls. Ending loop.`);
|
|
287
|
-
finalContent = llmResponse.text || '(No response from sub-agent)';
|
|
288
|
-
break;
|
|
289
|
-
}
|
|
290
|
-
const modelMessage = {
|
|
291
|
-
role: 'model',
|
|
292
|
-
parts: [{ text: llmResponse.text || '' }],
|
|
293
|
-
};
|
|
294
|
-
if (llmResponse.tool_calls && llmResponse.tool_calls.length > 0) {
|
|
295
|
-
modelMessage.tool_calls = llmResponse.tool_calls;
|
|
296
|
-
}
|
|
297
|
-
if (llmResponse.thoughts) {
|
|
298
|
-
modelMessage.thoughts = llmResponse.thoughts;
|
|
299
|
-
}
|
|
300
|
-
history.push(modelMessage);
|
|
301
|
-
const modelInput = this.sessionInputsRepository.create({
|
|
302
|
-
session: { id: childSession.id },
|
|
303
|
-
role: 'model',
|
|
304
|
-
raw_llm_response: llmResponse.text || '',
|
|
305
|
-
tool_calls: llmResponse.tool_calls
|
|
306
|
-
? JSON.stringify(llmResponse.tool_calls)
|
|
307
|
-
: null,
|
|
308
|
-
thoughts: llmResponse.thoughts || null,
|
|
309
|
-
input_token_count: llmResponse.usage?.inputTokens || null,
|
|
310
|
-
output_token_count: llmResponse.usage?.outputTokens || null,
|
|
311
|
-
cached_token_count: llmResponse.usage?.cachedTokens || null,
|
|
312
|
-
execution_strategy: 'auto_apply',
|
|
313
|
-
});
|
|
314
|
-
await this.sessionInputsRepository.save(modelInput);
|
|
315
|
-
this.eventsGateway.sendToAll('refresh-ui', {
|
|
316
|
-
sessionId: childSession.id,
|
|
317
|
-
});
|
|
318
|
-
this.eventsGateway.sendToAll('refresh-ui', {
|
|
319
|
-
sessionId: parentSessionId,
|
|
320
|
-
});
|
|
321
|
-
if (!llmResponse.tool_calls || llmResponse.tool_calls.length === 0) {
|
|
322
|
-
this.logger.log(`Sub-agent "${agentName}" returned text with no tool calls. Ending loop.`);
|
|
323
|
-
finalContent = llmResponse.text || '';
|
|
324
|
-
break;
|
|
325
|
-
}
|
|
326
|
-
const executionContext = new llm_orchestration_interfaces_1.PlanExecutionContext();
|
|
327
|
-
executionContext.session_id = childSession.id;
|
|
328
|
-
executionContext.system_prompt_id = subAgent.system_prompt_id || null;
|
|
329
|
-
let shouldBreak = false;
|
|
330
|
-
const toolResults = [];
|
|
331
|
-
for (const toolCall of llmResponse.tool_calls) {
|
|
332
|
-
const toolName = toolCall.function.name;
|
|
333
|
-
const args = typeof toolCall.function.arguments === 'string'
|
|
334
|
-
? JSON.parse(toolCall.function.arguments)
|
|
335
|
-
: toolCall.function.arguments;
|
|
336
|
-
this.logger.log(`Sub-agent "${agentName}" calling tool: ${toolName}`);
|
|
337
|
-
if (toolName === 'final') {
|
|
338
|
-
const plainText = args.plain || args.content || '';
|
|
339
|
-
finalContent = plainText;
|
|
340
|
-
shouldBreak = true;
|
|
341
|
-
const actionEntity = this.aiActionsRepository.create({
|
|
342
|
-
input_id: modelInput.id,
|
|
343
|
-
sessionInput: { id: modelInput.id },
|
|
344
|
-
action_type: 'final',
|
|
345
|
-
status: ai_actions_service_1.AIActionStatus.CONFIRMED_KEPT,
|
|
346
|
-
order_of_execution: toolResults.length,
|
|
347
|
-
original_content_for_revert: null,
|
|
348
|
-
tool_call_id: toolCall.id || null,
|
|
349
|
-
plain: plainText,
|
|
350
|
-
selections: args.selections || null,
|
|
351
|
-
});
|
|
352
|
-
await this.aiActionsRepository.save(actionEntity);
|
|
353
|
-
toolResults.push({
|
|
354
|
-
toolCallId: toolCall.id || '',
|
|
355
|
-
toolName,
|
|
356
|
-
result: 'Task completed.',
|
|
357
|
-
});
|
|
358
|
-
continue;
|
|
359
|
-
}
|
|
360
|
-
let handler = handlerRegistry.get(toolName);
|
|
361
|
-
if (!handler) {
|
|
362
|
-
const mcpMatch = toolName.match(/^([^_]+)__(.+)$/);
|
|
363
|
-
if (mcpMatch) {
|
|
364
|
-
const [, serverName, toolNameRaw] = mcpMatch;
|
|
365
|
-
handler = new mcp_tool_action_handler_1.McpToolActionHandler(serverName, toolNameRaw, mcpService, '');
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
if (!handler) {
|
|
369
|
-
this.logger.warn(`No handler found for tool: ${toolName}. Skipping.`);
|
|
370
|
-
const errorMsg = `Tool '${toolName}' is not a valid tool. Please use a valid tool.`;
|
|
371
|
-
toolResults.push({
|
|
372
|
-
toolCallId: toolCall.id || '',
|
|
373
|
-
toolName,
|
|
374
|
-
result: errorMsg,
|
|
375
|
-
});
|
|
376
|
-
const actionEntity = this.aiActionsRepository.create({
|
|
377
|
-
input_id: modelInput.id,
|
|
378
|
-
sessionInput: { id: modelInput.id },
|
|
379
|
-
action_type: toolName,
|
|
380
|
-
status: ai_actions_service_1.AIActionStatus.EXECUTION_FAILED,
|
|
381
|
-
order_of_execution: toolResults.length,
|
|
382
|
-
original_content_for_revert: null,
|
|
383
|
-
tool_call_id: toolCall.id || null,
|
|
384
|
-
});
|
|
385
|
-
await this.aiActionsRepository.save(actionEntity);
|
|
386
|
-
continue;
|
|
387
|
-
}
|
|
388
|
-
let result;
|
|
389
|
-
try {
|
|
390
|
-
result = await handler.execute(args, executionContext);
|
|
391
|
-
}
|
|
392
|
-
catch (error) {
|
|
393
|
-
this.logger.error(`Handler for ${toolName} failed: ${error.message}`);
|
|
394
|
-
result = {
|
|
395
|
-
status: 'FAILURE',
|
|
396
|
-
summary: `An unexpected error occurred: ${error.message}`,
|
|
397
|
-
error_message: error.message,
|
|
398
|
-
persisted_args: args,
|
|
399
|
-
execution_log: { output: '', error_message: error.message },
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
const successStatus = this.getSuccessStatusForStrategy(executionStrategy);
|
|
403
|
-
const actionEntity = this.aiActionsRepository.create({
|
|
404
|
-
input_id: modelInput.id,
|
|
405
|
-
sessionInput: { id: modelInput.id },
|
|
406
|
-
action_type: toolName,
|
|
407
|
-
status: result.status === 'SUCCESS'
|
|
408
|
-
? successStatus
|
|
409
|
-
: ai_actions_service_1.AIActionStatus.EXECUTION_FAILED,
|
|
410
|
-
order_of_execution: toolResults.length,
|
|
411
|
-
original_content_for_revert: result.original_content_for_revert || null,
|
|
412
|
-
tool_call_id: toolCall.id || null,
|
|
413
|
-
...result.persisted_args,
|
|
414
|
-
});
|
|
415
|
-
const savedAction = await this.aiActionsRepository.save(actionEntity);
|
|
416
|
-
await this.executionLogsService.createLog({
|
|
417
|
-
action_id: savedAction.id,
|
|
418
|
-
output: result.execution_log.output,
|
|
419
|
-
error_message: result.execution_log.error_message,
|
|
420
|
-
});
|
|
421
|
-
const output = result.execution_log?.output || '';
|
|
422
|
-
const error = result.execution_log?.error_message || result.error_message || '';
|
|
423
|
-
const combinedResult = error
|
|
424
|
-
? `${output}\n\nError: ${error}`.trim()
|
|
425
|
-
: output;
|
|
426
|
-
toolResults.push({
|
|
427
|
-
toolCallId: toolCall.id || '',
|
|
428
|
-
toolName,
|
|
429
|
-
result: combinedResult,
|
|
430
|
-
});
|
|
431
|
-
if (executionContext.flags.should_halt) {
|
|
432
|
-
this.logger.log(`Execution context halted. Ending sub-agent loop.`);
|
|
433
|
-
shouldBreak = true;
|
|
434
|
-
break;
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
let followupUserMessage;
|
|
438
|
-
let followupGeneratedContext = null;
|
|
439
|
-
if (subAgent.followup_context_template_id && !shouldBreak) {
|
|
440
|
-
try {
|
|
441
|
-
const followupTemplate = subAgent.followupContextTemplate || null;
|
|
442
|
-
const commandOutputs = toolResults.map((tr) => `// Tool: ${tr.toolName}\n\`\`\`\n${tr.result}\n\`\`\``);
|
|
443
|
-
const adHocContextDefinition = JSON.stringify({
|
|
444
|
-
command_outputs: commandOutputs,
|
|
445
|
-
});
|
|
446
|
-
followupGeneratedContext =
|
|
447
|
-
await sessionInputContextService.generateContext({
|
|
448
|
-
user_prompt: '',
|
|
449
|
-
context_template_id: subAgent.followup_context_template_id,
|
|
450
|
-
ad_hoc_context_definition: adHocContextDefinition,
|
|
451
|
-
execution_strategy: 'auto_apply',
|
|
452
|
-
}, followupTemplate);
|
|
453
|
-
followupUserMessage = followupGeneratedContext;
|
|
454
|
-
this.logger.log(`Sub-agent "${agentName}" follow-up rendered through context template "${followupTemplate?.template_name || subAgent.followup_context_template_id}".`);
|
|
455
|
-
}
|
|
456
|
-
catch (error) {
|
|
457
|
-
this.logger.error(`Failed to render follow-up context template for sub-agent "${agentName}": ${error.message}. Using raw tool results.`, error.stack);
|
|
458
|
-
followupUserMessage = toolResults
|
|
459
|
-
.map((tr) => `Result from ${tr.toolName}:\n${tr.result}`)
|
|
460
|
-
.join('\n\n');
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
else {
|
|
464
|
-
followupUserMessage = toolResults
|
|
465
|
-
.map((tr) => `Result from ${tr.toolName}:\n${tr.result}`)
|
|
466
|
-
.join('\n\n');
|
|
467
|
-
}
|
|
468
|
-
for (const tr of toolResults) {
|
|
469
|
-
history.push({
|
|
470
|
-
role: 'tool',
|
|
471
|
-
tool_call_id: tr.toolCallId,
|
|
472
|
-
tool_name: tr.toolName,
|
|
473
|
-
parts: [{ text: tr.result }],
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
if (subAgent.followup_context_template_id && followupUserMessage) {
|
|
477
|
-
history.push({
|
|
478
|
-
role: 'user',
|
|
479
|
-
parts: [{ text: followupUserMessage }],
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
await this.sessionInputsRepository.save(this.sessionInputsRepository.create({
|
|
483
|
-
session: { id: childSession.id },
|
|
484
|
-
role: 'user',
|
|
485
|
-
user_prompt: '',
|
|
486
|
-
generated_context_string: followupGeneratedContext,
|
|
487
|
-
execution_strategy: 'auto_apply',
|
|
488
|
-
raw_llm_response: null,
|
|
489
|
-
tool_calls: JSON.stringify(toolResults.map((tr) => ({
|
|
490
|
-
id: tr.toolCallId,
|
|
491
|
-
type: 'function',
|
|
492
|
-
function: { name: tr.toolName, arguments: '{}' },
|
|
493
|
-
}))),
|
|
494
|
-
...(subAgent.followup_context_template_id
|
|
495
|
-
? { context_template_id: subAgent.followup_context_template_id }
|
|
496
|
-
: {}),
|
|
497
|
-
}));
|
|
498
|
-
this.eventsGateway.sendToAll('refresh-ui', {
|
|
499
|
-
sessionId: childSession.id,
|
|
500
|
-
});
|
|
501
|
-
this.eventsGateway.sendToAll('refresh-ui', {
|
|
502
|
-
sessionId: parentSessionId,
|
|
503
|
-
});
|
|
504
|
-
if (shouldBreak) {
|
|
505
|
-
break;
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
if (iterations >= MAX_ITERATIONS) {
|
|
509
|
-
this.logger.warn(`Sub-agent "${agentName}" reached max iterations (${MAX_ITERATIONS}).`);
|
|
510
|
-
if (!finalContent) {
|
|
511
|
-
finalContent =
|
|
512
|
-
'Sub-agent reached maximum iterations without completing.';
|
|
513
|
-
success = false;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
await this.subAgentRunsService.markCompleted(childSession.id, finalContent.substring(0, 5000));
|
|
517
|
-
await this.sessionsService.update(childSession.id, { is_running: false });
|
|
518
|
-
this.eventsGateway.sendToAll('llm-generation-ended', {
|
|
519
|
-
sessionInputId: `subagent-${childSession.id}`,
|
|
520
|
-
sessionId: childSession.id,
|
|
521
|
-
});
|
|
522
|
-
this.eventsGateway.sendToAll('refresh-ui', {
|
|
523
|
-
sessionId: childSession.id,
|
|
524
|
-
});
|
|
525
|
-
this.eventsGateway.sendToAll('refresh-ui', {
|
|
526
|
-
sessionId: parentSessionId,
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
catch (error) {
|
|
530
|
-
this.logger.error(`Sub-agent "${agentName}" failed: ${error.message}`, error.stack);
|
|
531
|
-
success = false;
|
|
532
|
-
finalContent = `Sub-agent "${agentName}" encountered an error: ${error.message}`;
|
|
533
|
-
await this.subAgentRunsService.markFailed(childSession.id, error.message);
|
|
534
|
-
await this.sessionsService.update(childSession.id, { is_running: false });
|
|
535
|
-
this.eventsGateway.sendToAll('llm-generation-ended', {
|
|
536
|
-
sessionInputId: `subagent-${childSession.id}`,
|
|
537
|
-
sessionId: childSession.id,
|
|
538
|
-
error: error.message,
|
|
539
|
-
});
|
|
540
|
-
this.eventsGateway.sendToAll('refresh-ui', {
|
|
541
|
-
sessionId: childSession.id,
|
|
542
|
-
});
|
|
543
|
-
this.eventsGateway.sendToAll('refresh-ui', {
|
|
544
|
-
sessionId: parentSessionId,
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
const durationMs = Date.now() - startTime;
|
|
548
|
-
this.logger.log(`Sub-agent "${agentName}" completed in ${durationMs}ms, ${iterations} iterations, success: ${success}`);
|
|
549
|
-
return {
|
|
550
|
-
content: finalContent,
|
|
551
|
-
success,
|
|
552
|
-
iterations,
|
|
553
|
-
childSessionId: childSession.id,
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
resolveMcpToolNames(entries, allActiveMcpToolNames) {
|
|
557
|
-
const result = [];
|
|
558
|
-
for (const entry of entries) {
|
|
559
|
-
for (const toolName of allActiveMcpToolNames) {
|
|
560
|
-
if (toolName === entry || toolName.startsWith(entry + '__')) {
|
|
561
|
-
if (!result.includes(toolName)) {
|
|
562
|
-
result.push(toolName);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
return result;
|
|
568
|
-
}
|
|
569
|
-
reconstructHistory(inputs) {
|
|
570
|
-
const history = [];
|
|
571
|
-
for (const input of inputs) {
|
|
572
|
-
if (input.role === 'user') {
|
|
573
|
-
const content = {
|
|
574
|
-
role: 'user',
|
|
575
|
-
parts: [
|
|
576
|
-
{
|
|
577
|
-
text: input.generated_context_string ||
|
|
578
|
-
input.user_prompt ||
|
|
579
|
-
input.raw_llm_response ||
|
|
580
|
-
'',
|
|
581
|
-
},
|
|
582
|
-
],
|
|
583
|
-
};
|
|
584
|
-
history.push(content);
|
|
585
|
-
}
|
|
586
|
-
else if (input.role === 'model') {
|
|
587
|
-
const content = {
|
|
588
|
-
role: 'model',
|
|
589
|
-
parts: [{ text: input.raw_llm_response || '' }],
|
|
590
|
-
};
|
|
591
|
-
if (input.tool_calls) {
|
|
592
|
-
try {
|
|
593
|
-
const parsed = JSON.parse(input.tool_calls);
|
|
594
|
-
if (Array.isArray(parsed)) {
|
|
595
|
-
content.tool_calls = parsed;
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
catch {
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
history.push(content);
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
return history;
|
|
605
|
-
}
|
|
606
|
-
async callWithRetry(request, sessionId) {
|
|
607
|
-
const retryEnabled = await this.applicationStateService.getLlmRetryEnabled();
|
|
608
|
-
const maxAttempts = await this.applicationStateService.getLlmRetryMaxAttempts();
|
|
609
|
-
let lastError;
|
|
610
|
-
let attempt = 1;
|
|
611
|
-
while (attempt <= maxAttempts) {
|
|
612
|
-
try {
|
|
613
|
-
if (attempt > 1) {
|
|
614
|
-
this.logger.log(`Retry attempt ${attempt}/${maxAttempts} for sub-agent session ${sessionId}`);
|
|
615
|
-
}
|
|
616
|
-
return await this.llmProvider.generateContent({
|
|
617
|
-
...request,
|
|
618
|
-
abortController: request.abortController,
|
|
619
|
-
});
|
|
620
|
-
}
|
|
621
|
-
catch (error) {
|
|
622
|
-
lastError = error;
|
|
623
|
-
if (error.name === 'AbortError' || error.code === 'ABORT_ERR') {
|
|
624
|
-
throw error;
|
|
625
|
-
}
|
|
626
|
-
const shouldRetry = retryEnabled && attempt < maxAttempts && this.isRetryableError(error);
|
|
627
|
-
if (!shouldRetry) {
|
|
628
|
-
throw error;
|
|
629
|
-
}
|
|
630
|
-
const backoffMs = Math.pow(2, attempt - 1) * 1000;
|
|
631
|
-
this.logger.log(`LLM call failed (attempt ${attempt}/${maxAttempts}): ${error.message}. Retrying in ${backoffMs}ms...`);
|
|
632
|
-
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
633
|
-
attempt++;
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
throw lastError;
|
|
637
|
-
}
|
|
638
|
-
isRetryableError(error) {
|
|
639
|
-
const errorMessage = error.message?.toLowerCase() || '';
|
|
640
|
-
const errorCode = error.code;
|
|
641
|
-
const status = error.status;
|
|
642
|
-
if (error.name === 'AbortError' || error.code === 'ABORT_ERR')
|
|
643
|
-
return false;
|
|
644
|
-
const networkErrors = [
|
|
645
|
-
'ECONNRESET',
|
|
646
|
-
'ETIMEDOUT',
|
|
647
|
-
'ENOTFOUND',
|
|
648
|
-
'ENETUNREACH',
|
|
649
|
-
'ECONNREFUSED',
|
|
650
|
-
];
|
|
651
|
-
if (errorCode && networkErrors.includes(errorCode))
|
|
652
|
-
return true;
|
|
653
|
-
if (status === 429 ||
|
|
654
|
-
errorMessage.includes('rate limit') ||
|
|
655
|
-
errorMessage.includes('too many requests'))
|
|
656
|
-
return true;
|
|
657
|
-
if (status >= 500 && status < 600)
|
|
658
|
-
return true;
|
|
659
|
-
if (errorMessage.includes('empty response') ||
|
|
660
|
-
errorMessage.includes('timeout'))
|
|
661
|
-
return true;
|
|
662
|
-
return false;
|
|
663
|
-
}
|
|
664
|
-
getSuccessStatusForStrategy(strategy) {
|
|
665
|
-
switch (strategy) {
|
|
666
|
-
case 'auto_apply':
|
|
667
|
-
return ai_actions_service_1.AIActionStatus.CONFIRMED_KEPT;
|
|
668
|
-
case 'review_first':
|
|
669
|
-
case 'apply_revert':
|
|
670
|
-
default:
|
|
671
|
-
return ai_actions_service_1.AIActionStatus.APPLIED_PENDING_REVIEW;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
};
|
|
675
|
-
exports.SubAgentRunner = SubAgentRunner;
|
|
676
|
-
exports.SubAgentRunner = SubAgentRunner = SubAgentRunner_1 = __decorate([
|
|
677
|
-
(0, common_1.Injectable)(),
|
|
678
|
-
__param(6, (0, common_1.Inject)(llm_provider_interface_1.LLM_PROVIDER)),
|
|
679
|
-
__param(8, (0, typeorm_1.InjectRepository)(session_input_entity_1.SessionInput)),
|
|
680
|
-
__param(9, (0, typeorm_1.InjectRepository)(ai_action_entity_1.AIAction)),
|
|
681
|
-
__metadata("design:paramtypes", [sub_agents_service_1.SubAgentsService,
|
|
682
|
-
sub_agent_runs_service_1.SubAgentRunsService,
|
|
683
|
-
sessions_service_1.SessionsService,
|
|
684
|
-
application_state_service_1.ApplicationStateService,
|
|
685
|
-
execution_logs_service_1.ExecutionLogsService,
|
|
686
|
-
events_gateway_1.EventsGateway, Object, core_1.ModuleRef,
|
|
687
|
-
typeorm_2.Repository,
|
|
688
|
-
typeorm_2.Repository])
|
|
689
|
-
], SubAgentRunner);
|
|
690
|
-
//# sourceMappingURL=sub-agent-runner.service.js.map
|