Files
xiaoqu_mcp_service/xiaoqu-agent-service/AGENTS.md
T

34 lines
5.1 KiB
Markdown
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.
# xiaoqu-agent-service 项目指引
## ai-proj 关联信息
- **ai-proj 项目 ID:224**(项目名 xiaoqu_agent_service)。本仓所有需求/任务创建后应挂到该项目,关联任务前确保任务也在项目 224。
- 近期需求示例:REQ-20260924-0009(id 5806,人流量统计工具+统计类限一个月,implementation 完成)→ 任务 22405;REQ-20260924-0003(id 5800,设备生命周期查询工具,implementation 完成)→ 任务 22391;REQ-20260921-0007(id 5778,设备电量消息查询工具,released)→ 任务 22306;REQ-20260919-0003(id 5747,出入库工具复查修复,released)→ 任务 22123。
## ai-proj MCP 已知限制与真实契约
- MCP `update_requirement` 不支持改 project_id/owner;改归属必须走 REST 两步:
1. `POST /api/v1/requirements/{id}/reassignment/preflight`,body=`{operation_id:"<uuid>", expected_version:<当前sync_version>, target_project_id:224, target_owner_id?/clear_owner?}`
2. `POST /api/v1/requirements/{id}/reassignment/confirm`,body=`{operation_id, preflight_token}`(两个字段缺一不可;preflight_token 一次性,confirm 失败即作废,必须在同一条命令里 preflight+confirm 原子执行)
- REST base 推导:mcp.json 里 ai-proj 的 url 去掉尾部 `/mcp/sse`(即 `https://ai.pipexerp.com/api/v1`),认证头 `X-API-Key` 同 mcp.json。
- ⚠️ 本机 shell(Bash 工具)直读 `~/.kimi-code/mcp.json` 会被托管层拦截("local Shell bypass is disabled for a managed MCP route");用 Read 工具读取不受限。
- 任务跨项目用 `move_task`,再 `link_tasks_to_requirement`(role=implementation)。
- REST 建需求/任务实测(2026-09-24):`POST /requirements` 与 `POST /tasks` 的 body 带 `project_id:224` 会创建失败/被忽略,先裸建再走 reassignment;关联用 `POST /requirements/{id}/tasks` body=`{task_id, role:"implementation"}`;更新用 `PUT /requirements/{id}`(不支持 PATCH),`delivery_stage`/`reviewer_id` 为只读(PUT 静默忽略);`POST /requirements/{id}/submit` 可推进 draft→pending 并自动分配评审人,`POST /requirements/{id}/review` 仅评审人可调用;released 由 CLI sync 或评审/界面流转。
- 本机无 ai-proj CLI,远程同步需在有 CLI 的机器执行 `ai-proj sync requirement --id <id> --direction to_remote`。
## 生产 ES 集群关键坑
- 生产两个 ES 集群(cloud/local,app.es.cloud/local.*)均为 **ES 7.7.1**:elasticsearch-java 7.17 高阶客户端(ElasticsearchClient)的 vendor Content-Type(`application/vnd.elasticsearch+json; compatible-with=7`)被 406 拒绝,且其 X-Elastic-Product 响应头校验(7.14 才引入)过不了——**业务 ES 查询一律注入低阶 `esCloudRestClient`/`esLocalRestClient`(RestClient)bean**,不要注入 esCloudClient/esLocalClient(EsClientConfig 里仅为兼容保留)。
- 低阶 `org.elasticsearch.client.Response` 构造器包私有且参数是 HttpResponse,测试里用 `mock(Response.class)` + stub `getEntity()` 构造;注意 `thenReturn(esResponse(...))` 里嵌套 when() 会触发 UnfinishedStubbingException,必须先创建好 Response 再 stub。
- electricitymessage 索引(电量消息类):`createTime` 是 date 类型(format strict_date_optional_time||epoch_millis),range 必须发 **epoch 毫秒**(`yyyy-MM-dd HH:mm:ss` 字符串 400);`_source` 里 `value` 是**文本**("28"/"100")、`createTime` 是 ISO 文本(`2026-09-21T10:00:00.000+08:00`),读取时都要归一。老系统能跑是因为 transport 客户端把 Date 序列化成 epoch 毫秒、Jackson 把字符串 value 反序列化进 Integer 字段。
- paperuselog 索引(换纸日志):`rfid` 是 **text** 类型(mapping 有 `ignore_above=256` 的 keyword 子字段),terms 聚合必须用 `rfid.keyword`,直接聚合 text 字段被 7.7.1 以 400 "Text fields are not optimised for aggregations" 拒绝(2026-09-22 生产实测修复);老系统不做 ES 聚合,而是翻页拉全量文档后在 Java 侧按 `P_{positionsId}_{snCode}_{rfid}`/`T_{toiletId}_{snCode}_{rfid}` 复合 key 去重,MCP 用 terms 聚合近似(语义差异见设计文档)。
- curl 直连 MCP 冒烟:JSON body 务必 `-d @file`(行内 `-d` 长 JSON 经网关会被截断报 "Invalid message format");响应是 SSE,`sed -n 's/^data://p'` 取 JSON。
- 托管 MCP 工具(mcp__xiaoqu__*)在服务重启后 session 失效会报 AI_PROJ_MCP_SEND_OUTCOME_UNKNOWN,改走上面 curl 直连即可。
## 生产部署要点
- `./deploy/deploy.sh remote-deploy`(SSH 别名 xiaoqu-prd,目录 /data/xiaoqu-agent-service)。
- **部署前必须先把 main 推 origin**:出现过本地 main 领先 origin 1 个修复提交、他人从 origin 构建部署导致生产跑到旧代码的情况(2026-09-22 paperuselog terms 结构 400)。
- 新工具上线后必须幂等绑 prod scope(svc 库 MySQL,tool 表唯一标识列是 `name`;scope 表是 `agent_scope`):hardware/district 系列惯例绑 scope 1(test)/2(operation)/3(xiaoqu-ai)/5(ops-query),工单/仓库系列只绑 scope 1。
- prod AK 的 Authorization 头值本身已含 "Bearer " 前缀,不要再拼。