import { tool } from "@langchain/core/tools"; import z from "zod"; import mongoose from "mongoose"; import { DBModel } from "../../../../models/index.js"; const healthProfileQueryTool = tool( async ({ profileId, userId, name, mobile, page = 1, pageSize = 20 }) => { try { // 按档案 _id 精确查询单条 if (profileId) { if (!mongoose.Types.ObjectId.isValid(profileId)) { return { success: false, error: `Invalid profile ID: ${profileId}` }; } const doc = await DBModel.HealthProfile.findById(profileId).lean(); if (!doc) { return { success: false, error: `未找到 ID 为 ${profileId} 的健康档案` }; } return { success: true, data: [doc], total: 1 }; } const filter = {}; if (userId) { if (!mongoose.Types.ObjectId.isValid(userId)) { return { success: false, error: `Invalid user ID: ${userId}` }; } filter.userId = new mongoose.Types.ObjectId(userId); } if (name) { // 转义正则特殊字符,避免查询报错或 ReDoS;姓名支持中文、全拼、拼音首字母匹配 const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); const re = { $regex: escaped, $options: "i" }; filter.$or = [{ "profile.name": re }, { "profile.pinyin": re }, { "profile.pinyinFL": re }]; } if (mobile) { filter["profile.mobile"] = mobile; } const skip = (page - 1) * pageSize; const [list, total] = await Promise.all([ DBModel.HealthProfile.find(filter) .sort({ "meta.createtime": -1 }) .skip(skip) .limit(pageSize) .lean(), DBModel.HealthProfile.countDocuments(filter), ]); return { success: true, data: list, total, page, pageSize, }; } catch (error) { return { success: false, error: error.message }; } }, { name: "health_profile_query", description: "查询患者健康档案。支持按档案 ID 精确查询,或按用户 ID、患者姓名(模糊)、患者电话筛选,返回分页结果。", schema: z.object({ profileId: z .string() .optional() .describe("健康档案 ID(_id),提供时精确查询单条,忽略其他筛选条件"), userId: z.string().optional().describe("所属用户ID(精确匹配)"), name: z.string().optional().describe("患者姓名(支持中文模糊、全拼、拼音首字母匹配,如 张三/zhangsan/zs)"), mobile: z.string().optional().describe("患者电话(精确匹配)"), page: z.number().int().min(1).optional().describe("页码,从 1 开始"), pageSize: z .number() .int() .min(1) .max(50) .optional() .describe("每页数量(1-50),默认 20"), }), } ); export { healthProfileQueryTool };