Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | 7x 7x 7x 7x 7x 11x 11x 11x 11x 11x 23x 23x 16x 7x 2x 2x 5x 6x 5x 5x 5x 5x 5x | import { Inject, Injectable, Logger, forwardRef } from '@nestjs/common';
import { PostExecutionHook } from './post-execution-hook.interface';
import { SessionInput } from '../../core-entities';
import { PlanExecutionContext } from '../llm-orchestration.interfaces';
import { ChatService } from '../../interactive-chat/chat.service';
import { ApplicationStateService } from '../../application-state/application-state.service';
import { SessionInputsService } from '../../session-inputs/session-inputs.service';
import { CreateSessionInputDto } from '../../session-inputs/dto/session-input.dto';
@Injectable()
export class InvalidToolFeedbackHook implements PostExecutionHook {
private readonly logger = new Logger(InvalidToolFeedbackHook.name);
constructor(
@Inject(forwardRef(() => ChatService))
private readonly chatService: ChatService,
private readonly applicationStateService: ApplicationStateService,
private readonly sessionInputsService: SessionInputsService,
) {}
async run(
sessionInput: SessionInput,
executionContext: PlanExecutionContext,
): Promise<void> {
const invalidTools = executionContext.feedback.invalidToolErrors;
if (!invalidTools || invalidTools.length === 0) {
return; // No invalid tools, do nothing.
}
// Native tool calling: if toolResults exist, errors flow through role: 'tool' messages
// The FollowUpPostExecutionHook will handle the follow-up turn with toolResults
if (
executionContext.toolResults &&
executionContext.toolResults.length > 0
) {
this.logger.log(
`Found ${invalidTools.length} invalid tool(s), but native tool calling is active. ` +
`Errors will flow through toolResults. FollowUpPostExecutionHook will handle the follow-up.`,
);
// Do NOT halt hooks - let FollowUpPostExecutionHook run to process toolResults
return;
}
this.logger.log(
`Found ${invalidTools.length} invalid tool(s). Sending feedback to AI.`,
);
const toolNames = invalidTools.map((e) => `'${e.tool_name}'`).join(', ');
const feedbackMessage = `SYSTEM_FEEDBACK: The previous response included tools that are not valid. The following tool names could not be found: ${toolNames}. Please review the available tools and provide a corrected plan using only valid tool names. Do not apologize, just provide the corrected plan.`;
// FIX: Create SessionInput record for proper conversation tracking
const feedbackDto: CreateSessionInputDto = {
user_prompt: feedbackMessage,
execution_strategy: sessionInput.execution_strategy,
ad_hoc_context_definition: undefined,
context_template_id: undefined,
};
try {
await this.sessionInputsService.create(
sessionInput.session_id,
feedbackDto,
);
// Halt subsequent hooks to prevent them from running, as we've already initiated a new turn.
executionContext.flags.should_halt_hooks = true;
} catch (error) {
this.logger.error(
`Failed to send invalid tool feedback to AI for session ${sessionInput.session_id}`,
error.stack,
);
}
}
}
|