All files / src/llm-orchestration/action-handlers generate-title.handler.ts

100% Statements 29/29
71.42% Branches 5/7
100% Functions 6/6
100% Lines 27/27

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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 1227x             7x 7x 7x 7x 7x     7x 15x 15x   15x     1x                                     4x           4x               4x                             4x             6x 6x 6x 3x 3x   3x                 3x 3x       2x       2x                   1x 1x                    
import { Injectable, Logger } from '@nestjs/common';
import { ActionHandler } from './action-handler.interface';
import {
  ActionExecutionResult,
  PlanExecutionContext,
  ToolMetadata,
} from '../llm-orchestration.interfaces';
import { GenerateTitleArgsDto } from './dto/generate-title.args.dto';
import { plainToClass } from 'class-transformer';
import { validate } from 'class-validator';
import { generateToolCall, generateToolCallJson } from '../../utils';
import { SessionsService } from '../../sessions/sessions.service';
 
@Injectable()
export class GenerateTitleHandler implements ActionHandler {
  readonly toolName = 'generate_title';
  private readonly logger = new Logger(GenerateTitleHandler.name);
 
  constructor(private readonly sessionsService: SessionsService) {}
 
  getMetadata(): ToolMetadata {
    return {
      name: this.toolName,
      description: this.getDefinition(true),
      arguments: [
        {
          name: 'title',
          type: 'string',
          description:
            'A concise session title (3-5 words) that summarizes the task.',
          required: true,
        },
      ],
    };
  }
 
  private generateExample(
    toolCall: Record<string, any>,
    useJson: boolean = false,
  ): string {
    return useJson
      ? generateToolCallJson(toolCall)
      : generateToolCall(toolCall);
  }
 
  getDefinition(useJsonFormat: boolean = false): string {
    const example = this.generateExample(
      {
        tool_name: this.toolName,
        title: 'Fix authentication bug',
      },
      useJsonFormat,
    );
 
    const definition = `
<${this.toolName}>
  Updates the session title to a concise, descriptive name.
  Use this tool when the current session needs a title or when the task scope has changed significantly.
  The title must be **3-5 words** - brief but informative.
 
  Parameters:
  - "title": (string) A concise title for the session (3-5 words).
 
  <example>
    Explanation: Set a descriptive title for a debugging session.
:${example}
  </example>
</${this.toolName}>
`;
    return definition.trim();
  }
 
  async execute(
    args: { [key: string]: any },
    context: PlanExecutionContext,
  ): Promise<ActionExecutionResult> {
    const validatedArgs = plainToClass(GenerateTitleArgsDto, args);
    const errors = await validate(validatedArgs);
    if (errors.length > 0) {
      const errorMessages = errors
        .map((err) => Object.values(err.constraints || {}).join(', '))
        .join('; ');
      return {
        status: 'FAILURE',
        summary: `Invalid arguments for ${this.toolName}.`,
        error_message: errorMessages,
        persisted_args: args,
        execution_log: { output: '', error_message: errorMessages },
      };
    }
 
    try {
      await this.sessionsService.update(context.session_id, {
        session_title: validatedArgs.title,
      });
 
      this.logger.log(
        `Session title updated to: "${validatedArgs.title}" for session ${context.session_id}`,
      );
 
      return {
        status: 'SUCCESS',
        summary: `Session title updated to: "${validatedArgs.title}"`,
        persisted_args: validatedArgs,
        execution_log: {
          output: `Session title set to: ${validatedArgs.title}`,
          error_message: '',
        },
      };
    } catch (error) {
      this.logger.error(`Failed to update session title: ${error.message}`);
      return {
        status: 'FAILURE',
        summary: 'Failed to update session title.',
        error_message: error.message,
        persisted_args: args,
        execution_log: { output: '', error_message: error.message },
      };
    }
  }
}