63 lines
2.6 KiB
TypeScript
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);
|
|
}
|
|
}
|