Files
gongxue-base/apps/server/src/agent-tools/tools/search-classroom-rentals.tool.ts

63 lines
2.6 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { ClassroomRentalsService } from '../../classroom-rentals/classroom-rentals.service';
import type { AgentToolContext, ToolDef, ToolInputResult } from '../agent-tool.types';
import { optionalPositiveInt, rejectUnknownKeys } from './tool-input';
interface Input { classroomId?: number; month?: string; includeEnded?: boolean; limit?: number }
function optionalMonth(value: unknown): ToolInputResult<string | undefined> {
if (value === undefined) return { ok: true, value: undefined };
if (typeof value !== 'string' || !/^\d{4}-\d{2}$/.test(value)) {
return { ok: false, error: 'month 必须是 YYYY-MM 格式' };
}
const [year, month] = value.split('-').map(Number);
if (month < 1 || month > 12 || year < 2000 || year > 2100) {
return { ok: false, error: 'month 不是有效月份' };
}
return { ok: true, value };
}
@Injectable()
export class SearchClassroomRentalsTool implements ToolDef<Input> {
readonly name = 'search_classroom_rentals';
readonly skillKey = 'classroom';
readonly description = '查询教室租赁订单(教室、承租方机构、起止日期、租金、状态)。';
readonly requiredPermission = 'rental:view';
readonly inputSchema = {
type: 'object',
properties: {
classroomId: { type: 'integer', minimum: 1 },
month: { type: 'string', description: 'YYYY-MM' },
includeEnded: { type: 'boolean', description: '是否包含已结束订单' },
limit: { type: 'integer', minimum: 1, maximum: 50 },
},
additionalProperties: false,
};
constructor(private readonly service: ClassroomRentalsService) {}
validate(raw: Record<string, unknown>): ToolInputResult<Input> {
const invalid = rejectUnknownKeys(raw, ['classroomId', 'month', 'includeEnded', 'limit']);
if (invalid) return invalid;
const classroomId = optionalPositiveInt(raw.classroomId, 'classroomId');
if (!classroomId.ok) return classroomId;
const month = optionalMonth(raw.month); if (!month.ok) return month;
if (raw.includeEnded !== undefined && typeof raw.includeEnded !== 'boolean') {
return { ok: false, error: 'includeEnded 必须是布尔值' };
}
const limit = optionalPositiveInt(raw.limit, 'limit', 50); if (!limit.ok) return limit;
return {
ok: true,
value: {
classroomId: classroomId.value,
month: month.value,
includeEnded: raw.includeEnded === undefined ? undefined : Boolean(raw.includeEnded),
limit: limit.value,
},
};
}
execute(input: Input, _context: AgentToolContext) {
return this.service.agentSearchRentals(input);
}
}