Files
contracts/base/res_api_param_test2.json
T
what 9446571363 重构: base 包资源核心类型迁移到 req/resx,新增 res_watcher/res_api_param
base/resource.go、resource_hooks.go、resource_test.go、query_field.go 删除,ResField 等具体实现搬到 req/resx(见 res_field.go 里的类型别名)。res_listener.go 替换成 res_watcher.go,对应资源变更监听概念改名。新增 res_api_param.go 及配套测试(ResApi 参数建模,给 MCP tool 的 JSON Schema 生成用)。
2026-07-22 09:13:05 +08:00

475 lines
25 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"tools": [
{
"name": "res-query",
"description": "Query records with filters, joins, aggregates, ordering, pagination, and recursive tree traversal.\rAll relations are SQL JOINs within a single query; the main resource is the primary table.\rPrefer JOIN over multiple queries: when the needed data spans several resources, combine same-connection resources into one query using relations, then make separate queries only for resources on different connections.\rWRONG: 3 queries — User → UserRole → Role, even though User and UserRole share the same connection.\rRIGHT: 1 query joining User + UserRole (same connection), then 1 separate query for Role (different connection).\rIMPORTANT:\r(1) Never guess field names — only use codes from res-schema results in this conversation.\r(2) Call res-schema first if the resource schema has not been fetched yet.\r(3) Use recursive to traverse all descendants of hierarchical data (e.g. categories, menus, org charts); returns a flat list, not a nested tree.",
"inputSchema": {
"type": "object",
"properties": {
"conditions": {
"type": "object",
"properties": {
"children": {
"type": "array",
"items": {
"$ref": "#/properties/conditions"
},
"title": "子条件",
"description": "子条件节点,递归结构"
},
"exprs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {
"type": "string",
"title": "字段编码",
"description": "必须来自 res-schema 返回的字段列表,禁止猜测字段名"
},
"fieldResource": {
"type": "string",
"title": "所属资源",
"description": "字段所属的表标识,取值为主资源编码或 relations[].code"
},
"fieldSqlFunc": {
"type": "string",
"title": "列SQL函数",
"description": "对列应用 SQL 函数后再参与比较,拼接为 {func}({fieldResource}.{field}) {operator} {token}。\r\n支持 SQL-92 / SQL:1999 / SQL:2003 标准函数及数据库方言函数,如 DATE、UPPER、ROUND。\r\n需要第二参数的函数(如 ROUND、CAST)配合 fieldSqlFuncParam 使用。"
},
"fieldSqlFuncParam": {
"type": "string",
"title": "列SQL函数参数",
"description": "fieldSqlFunc 的附加参数,按函数类型用途不同:\r\r通用函数(有 param 时):{func}({fieldResource}.{field}, {fieldSqlFuncParam}) {operator} {token}\r 示例:ROUND(col, 2) → fieldSqlFuncParam=\"2\"\r SUBSTRING(col, 1, 10) → fieldSqlFuncParam=\"1, 10\"\r\rJSON 函数(param 为 JSON 路径表达式):\r json_member_oftoken 是否是列 JSON 数组的成员):\r 无 paramJSON_CONTAINS({token}, JSON_ARRAY({field}))\r 有 paramJSON_CONTAINS({fieldSqlFuncParam}, JSON_ARRAY({field}))\r json_contains(列 JSON 是否包含 token):\r 无 paramJSON_CONTAINS({field}, JSON_ARRAY({token}))\r 有 paramJSON_CONTAINS({fieldSqlFuncParam}, JSON_ARRAY({token}))"
},
"ignoreEmptyParam": {
"type": "boolean",
"title": "忽略空参数",
"description": "当 tokenType=param 且请求参数值为空(空字符串或 null)时,跳过该条件不生成 SQL。用于实现可选过滤项",
"default": false
},
"operator": {
"type": "string",
"title": "运算符",
"description": "标准 SQL 比较运算符:\r\n= / != / > / >= / < / <=\r\nLIKE:模糊匹配(%keyword%\r\nIN:包含,token 逗号分隔多值\r\nIS NULL / IS NOT NULL:空值判断,无需 token\r\nREGEXP:正则匹配",
"default": "="
},
"token": {
"type": "string",
"title": "比较值",
"description": "比较目标,内容由 tokenType 决定。operator 为 IS NULL/IS NOT NULL 时可省略"
},
"tokenType": {
"type": "string",
"title": "比较值类型",
"description": "先选类型再填 token\r\nstringtoken 填字面量如 '2024-01-01'\r\nfunctoken 填内置函数名 UserID|UserUuid|UserRolesUuid|UserPlatform|UserSaaS\r\nparamtoken 填请求参数路径如 body.status\r\nsqltoken 填原始SQL如 CURRENT_DATE",
"default": "string",
"enum": [
"string",
"func"
]
}
},
"title": "条件项",
"description": "单条比较表达式,生成 [{fieldSqlFunc}(]{fieldResource}.{field}[)] {operator} {token} 片段",
"required": [
"field",
"operator"
]
},
"title": "条件表达式列表",
"description": "当前层的叶子比较列表,每项生成一个 {fieldResource}.{field} {operator} {token} 片段,同层多项以 type 连接"
},
"type": {
"type": "string",
"title": "逻辑连接符",
"description": "当前节点的逻辑运算符,将 exprs 各项与 children 各组以 AND 或 OR 连接",
"default": "and",
"enum": [
"and",
"or"
]
}
},
"title": "树形查询条件",
"description": "WHERE 条件树。\rexprs 每项生成一段比较:[{fieldSqlFunc}(]{fieldResource}.{field}[)] {operator} {token},同层多项以 type(and/or) 连接;\rchildren 为同结构子节点,递归嵌套实现复杂过滤。",
"required": [
"exprs",
"type"
]
},
"fields": {
"type": "array",
"items": {
"type": "object",
"properties": {
"alias": {
"type": "string",
"title": "别名",
"description": "输出字段别名,对应 SQL AS。isExpr=true 时必填;普通字段在多表 JOIN 存在同名冲突时填写,其余情况默认使用 code 值"
},
"code": {
"type": "string",
"title": "字段编码",
"description": "两种互斥用法,每个对象只能选其一:\r1. 普通字段编码,只填字段名本身如 amount,不含资源前缀,所属表由 codeResource 单独指定,isExpr 保持默认 false\r2. 原始 SQL 表达式(如 COUNT(*) / SUM(User.amount)),可含 {Resource}.{field} 引用,必须同时设置 isExpr = true 且 alias 必填\r注意:SELECT 中混入聚合表达式与非聚合字段时,需配合 groupBy 使用,否则结果不符合预期\r重要:字段编码必须来自 res-schema 返回的字段列表,禁止猜测或推断字段名"
},
"codeResource": {
"type": "string",
"title": "所属资源",
"description": "字段所属的表标识,取值为主资源编码或 relations[].code"
},
"dataType": {
"type": "string",
"title": "数据类型",
"description": "指定字段的返回数据类型,影响序列化方式;不填则由资源字段定义决定",
"default": "string",
"enum": [
"string",
"bool",
"number",
"array",
"json",
"integer",
"float"
]
},
"isExpr": {
"type": "boolean",
"title": "是否表达式",
"description": "设为 true 时,code 内容作为原始 SQL 表达式拼入 SELECT(如聚合函数 COUNT(*) / SUM(amount)),而非普通字段编码。isExpr=true 时 alias 为必填项",
"default": false
}
},
"title": "资源字段",
"description": "结构化字段,支持指定所属表、输出别名、聚合表达式及数据类型",
"required": [
"code"
]
},
"title": "查询字段",
"description": "SELECT 字段列表,不传则返回所有字段(仅主资源字段,不含 JOIN 表)。\r使用 relations 时,JOIN 表的字段不会自动出现在结果中,必须在 fields 里显式列出需要的 JOIN 表字段,否则 JOIN 无意义。\r普通字段:code 填字段名,codeResource 指定所属表;聚合/表达式:isExpr=truecode 填 SQL 表达式,alias 必填。\r仅查询聚合结果时,fields 只传聚合字段,不要混入普通字段,除非同时提供 groupBy。\r重要:所有字段编码必须先通过 res-schema 确认,禁止凭名称语义猜测"
},
"groupBy": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string",
"title": "字段编码",
"description": "格式必须为 {Resource}.{field},如 User.status。\r{Resource} 取值为主资源编码或 relations[].code"
},
{
"type": "object",
"properties": {
"expr": {
"type": "string",
"title": "表达式",
"description": "type=field 时填 {Resource}.{field}(如 User.status\rtype=sql 时填原始 SQL 表达式(如 DATE(created_at)"
},
"type": {
"type": "string",
"title": "表达式类型",
"description": "field:按资源字段分组,expr 填 {Resource}.{field},如 User.status\rsql:按原始 SQL 表达式分组,expr 填任意合法 SQL,如 DATE(created_at)",
"default": "field",
"enum": [
"field",
"sql"
]
}
},
"title": "分组表达式",
"description": "结构化分组项,type=field 用于资源字段,type=sql 用于原始 SQL 表达式",
"required": [
"type",
"expr"
]
}
]
},
"title": "分组规则",
"description": "GROUP BY 列表,配合 fields 中的聚合表达式使用。\r字段必须带资源前缀({Resource}.{field});聚合函数(COUNT / SUM 等)放在 fields 中,不属于此处"
},
"limit": {
"type": "integer",
"title": "每页条数",
"description": "返回的最大记录数",
"default": 30
},
"offset": {
"type": "integer",
"title": "偏移量",
"description": "跳过的记录数",
"default": 0
},
"orderBy": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string",
"title": "字段编码",
"description": "格式必须为 {Resource}.{field},如 User.created_at,默认升序(ASC)。\r需要降序或使用 SQL 表达式时使用对象形式"
},
{
"type": "object",
"properties": {
"direction": {
"type": "string",
"title": "排序方向",
"default": "asc",
"enum": [
"asc",
"desc"
]
},
"expr": {
"type": "string",
"title": "表达式",
"description": "type=field 时填 {Resource}.{field}(如 User.created_at);type=sql 时填原始 SQL 表达式(如 COUNT(*) / DATE(created_at)"
},
"type": {
"type": "string",
"title": "表达式类型",
"description": "field:按资源字段排序,expr 填 {Resource}.{field},如 User.created_at\rsql:按原始 SQL 表达式排序,expr 填任意合法 SQL,如 COUNT(*) / DATE(created_at)",
"default": "field",
"enum": [
"field",
"sql"
]
}
},
"title": "排序表达式",
"description": "结构化排序项,type=field 用于资源字段,type=sql 用于原始 SQL 表达式",
"required": [
"type",
"expr"
]
}
]
},
"title": "排序规则",
"description": "ORDER BY 列表,多项按顺序依次应用。\r字段必须带资源前缀({Resource}.{field});需要降序或 SQL 表达式排序时使用对象形式"
},
"relations": {
"type": "array",
"items": {
"type": "object",
"properties": {
"actuallyField": {
"type": "string",
"title": "实际资源字段",
"description": "目标资源(code)参与 ON 条件的字段"
},
"actuallyResource": {
"type": "string",
"title": "实际资源",
"description": "被关联的目标资源编码(相当于 SQL 表名)。JOIN 拼接为:{type} JOIN {actuallyResource} AS {code} ON {code}.{actuallyField} = {relationResource}.{relationField}"
},
"code": {
"type": "string",
"title": "关联标识",
"description": "JOIN 表别名(AS code),同时作为 fields/conditions/groupBy/orderBy 中 {Resource} 的取值。\r通常与 actuallyResource 保持一致;仅当多个关联引用同一资源导致冲突时,才需要重命名"
},
"conditions": {
"$ref": "#/properties/conditions",
"description": "该 JOIN 的附加过滤条件,作用于 JOIN ON 或主查询 WHERE,结构与顶层 conditions 相同"
},
"name": {
"type": "string",
"title": "关联名称",
"description": "关联的显示名称"
},
"relationField": {
"type": "string",
"title": "被关联资源字段",
"description": "ON 条件对端资源的字段"
},
"relationResource": {
"type": "string",
"title": "被关联资源",
"description": "ON 条件对端的资源编码(通常为主资源或父关联资源)"
},
"type": {
"type": "string",
"title": "关联类型",
"description": "SQL JOIN 类型(仅支持同库连接,不可跨库):\rinner:内连接,只返回两表均匹配的行\rleft:左连接,保留主表所有行\rright:右连接,保留关联表所有行",
"enum": [
"inner",
"left",
"right"
]
}
},
"required": [
"actuallyField",
"actuallyResource",
"code",
"relationField",
"relationResource",
"type"
]
},
"title": "资源关联",
"description": "SQL JOIN 列表,所有关联在同一条 SQL 中执行。\r关联资源的字段通过 code(表别名)在 fields / conditions / groupBy / orderBy 中引用。\r重要:所有关联资源必须与主资源在同一数据库连接。res-schema 返回的资源名称后面标有连接标识(如 · default / · service-support),建立 JOIN 前必须确认主资源与所有关联资源的连接标识完全一致,不一致则不可使用 JOIN,需分次查询后在应用层合并。"
},
"resource": {
"type": "string",
"title": "主资源",
"description": "主资源编码(resource),作为本次查询的主表,relations 中的关联资源均以此为基础 JOIN"
},
"recursive": {
"type": "object",
"title": "递归查询",
"description": "树形/层级数据的递归查询配置。配置后会以 pField=root 的记录为根节点,向下递归遍历所有子孙节点,返回平铺的记录列表(非嵌套树)。",
"properties": {
"pField": {
"type": "string",
"title": "父节点字段",
"description": "存储父节点 ID 的字段编码,格式为 {Resource}.{field}。{Resource} 取值为主资源编码或 relations[].code,如 Category.pid"
},
"cField": {
"type": "string",
"title": "当前节点字段",
"description": "存储自身 ID 的字段编码,格式为 {Resource}.{field}。{Resource} 取值为主资源编码或 relations[].code,如 Category.id"
},
"root": {
"type": "string",
"title": "根节点值",
"description": "递归起点,pField 等于此值的记录作为根节点,通常为 0 或空字符串"
},
"depth": {
"type": "integer",
"title": "递归深度",
"description": "最大递归层数,防止循环引用导致无限递归,不传则不限制"
}
},
"required": ["pField", "cField", "root"]
}
},
"required": [
"fields",
"resource"
]
},
"annotations": {}
},
{
"name": "res-create",
"description": "Create one or multiple new records for the specified resource. Returns all fields of the created record(s).\rCall res-schema first to get the field list before building the data object.\rIMPORTANT: Never guess field names — only use codes from res-schema results.",
"inputSchema": {
"type": "object",
"properties": {
"resource": {
"type": "string",
"title": "主资源",
"description": "目标资源编码,数据将写入该资源对应的表"
},
"data": {
"title": "创建数据",
"description": "单条记录传对象,批量创建传对象数组。\rkey 为字段编码(必须来自 res-schema 返回的字段列表,禁止猜测),value 为写入值。\r有默认值的字段可以不传,系统会自动填充。\r批量创建(array)时,所有记录必须包含完全相同的字段集合,不可部分记录有某字段而其他记录没有。\r系统保留字段禁止传入,包括:id、created_at、updated_at、created_user、owned_user、enabled 及其他由系统自动维护的字段",
"oneOf": [
{
"type": "object",
"title": "单条记录",
"description": "创建单条记录,key 为字段编码,value 为字段值",
"additionalProperties": true
},
{
"type": "array",
"title": "批量记录",
"description": "批量创建,每个元素为一条记录对象",
"items": {
"type": "object",
"additionalProperties": true
}
}
]
}
},
"required": ["resource", "data"]
},
"annotations": {}
},
{
"name": "res-update",
"description": "Update records by their IDs. Returns only the updated fields of the modified records.\rBefore calling this tool, ALWAYS use res-query to retrieve and show the user the records that will be affected. Only call res-update after the user has reviewed and confirmed.\rPass __confirm__: true when the user has approved the update.\rIMPORTANT: Never guess field names — only use codes from res-schema results.",
"inputSchema": {
"type": "object",
"properties": {
"resource": {
"type": "string",
"title": "主资源",
"description": "目标资源编码"
},
"ids": {
"type": "array",
"title": "记录ID列表",
"description": "必填,指定要更新的记录 ID 列表。必须通过 res-query 预先查询获得,禁止手动构造。",
"items": {
"type": "integer"
}
},
"data": {
"type": "object",
"title": "更新数据",
"description": "只传需要修改的字段,未传字段保持不变。\rkey 为字段编码(必须来自 res-schema 返回的字段列表,禁止猜测),value 为新值。\r系统保留字段禁止传入,包括:id、created_at、updated_at、created_user、owned_user、enabled 及其他由系统自动维护的字段",
"additionalProperties": true
},
"__confirm__": {
"type": "boolean",
"title": "确认执行",
"description": "首次调用不传。仅当服务端返回需要确认的提示时,重新调用并传入 true 以执行更新。不可主动传入,否则将跳过安全确认步骤。",
"default": false
}
},
"required": ["resource", "ids", "data"]
},
"annotations": {}
},
{
"name": "res-delete",
"description": "Hard-delete records by ID (physical removal, unrecoverable).\rWARNING: Prefer soft delete — use res-update to set deleted_at=CURRENT_TIMESTAMP and enabled=0 instead.\rOnly call res-delete when the user explicitly requests permanent/physical deletion.\rBefore calling, ALWAYS use res-query to show the user the affected records and obtain confirmation.\rPass __confirm__: true after the user has confirmed.",
"inputSchema": {
"type": "object",
"properties": {
"resource": {
"type": "string",
"title": "主资源",
"description": "目标资源编码"
},
"ids": {
"type": "array",
"title": "记录ID列表",
"description": "必填,指定要删除的记录 ID 列表。必须通过 res-query 预先查询获得,禁止手动构造。",
"items": {
"type": "integer"
}
},
"__confirm__": {
"type": "boolean",
"title": "确认执行",
"description": "首次调用不传。仅当服务端返回需要确认的提示时,重新调用并传入 true 以执行删除。不可主动传入,否则将跳过安全确认步骤。",
"default": false
}
},
"required": ["resource", "ids"]
},
"annotations": {}
},
{
"name": "res-schema",
"description": "Look up available resources and their field definitions. Without keywords: lists all resources. With keywords: returns matched resources with their field list, types, and constraints. Keywords match against resource code, name, or table name; supports Chinese fuzzy matching; use | to separate multiple terms (e.g. \"用户|权限\"). Call this before using res-query / res-update / res-delete if the resource schema is not already in the current conversation.",
"inputSchema": {
"type": "object",
"properties": {
"keywords": {
"type": "string",
"title": "查找关键字",
"description": "搜索关键词,用于筛选资源列表。支持多个关键词,用 | 分隔。\r对每条资源的编码(code)、名称(name)、数据表名(table)进行匹配,\r支持中文分词模糊匹配,结果按匹配相关度从高到低排序。\r示例:\"用户\" 或 \"用户|权限\""
}
}
},
"annotations": {}
}
]
}