feat: 提交校园智能助手后端工程源码(Spring Boot 2.7.18 + 平台 starter + JPA + Nacos)
build / build-push (push) Successful in 40s
build / build-push (push) Successful in 40s
- com.yunhai.agent,端口 8093,context-path /agent,制品 target/agent.jar;与 NoticeService 同构 - CAS 单点登录 + 三层角色权限(学生/教师/管理员/访客)+ 会话与工具调用审计落库 - DeepSeek 大模型编排 + 7 个业务模块工具(请假/公告/宿舍/活动/作业/资源库/教师发展) - 浏览器代执行协议(服务端挂起 → 前端用登录态代调 → toolResult 续跑)+ 调用失败深链兜底 - 登出修复:服务端真正 session.invalidate() + 前端两步登出 + logout-guard - 保留 projman 注入的 .gitea/workflows/build.yml 与 docker/Dockerfile;docker/application-prod.yml、run-app.sh 随工程入库
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package com.yunhai.agent.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 「浏览器代执行」挂起载荷(方案 A)。
|
||||
*
|
||||
* <p>业务模块的用户态接口只认浏览器 CAS 会话,服务端代调必然 302。开启代执行后,
|
||||
* 模型决定调用模块工具时,服务端<b>不执行</b>,而是把接口描述放进本载荷下发前端;
|
||||
* 前端用用户自己的登录态调用模块接口,再把结果通过
|
||||
* {@link ChatRequest.ToolResultItem} 回传,服务端续跑模型生成最终回答。
|
||||
*
|
||||
* <p>★ 安全边界:本载荷里的 {@code pathAndQuery} 只供前端调用使用;
|
||||
* 回传续跑时服务端<b>只信任工具名</b>(重新查注册表拿方法/路径并做角色校验),
|
||||
* 前端回传的任何路径信息都不会被采信,防止被改写成任意地址。
|
||||
*/
|
||||
@Data
|
||||
public class BrowserToolRequest {
|
||||
|
||||
/** 本批代执行的工具调用(同一轮模型可能连调多个,如先查列表再查详情) */
|
||||
private List<BrowserCall> calls = new ArrayList<>();
|
||||
|
||||
/** 给用户看的一句话说明(前端在等待期展示) */
|
||||
private String notice;
|
||||
|
||||
/**
|
||||
* 一次代执行调用的完整描述。
|
||||
* <p>{@code pathAndQuery} 以 {@code /} 开头({@code /<模块ctx>/api/...?query}),
|
||||
* 前端拼上当前页面的 {@code location.origin} 即为最终地址 ——
|
||||
* 同站部署时天然同源;本地 dev 则会打到 vite 代理(404)→ 自动落回深链兜底。
|
||||
*/
|
||||
@Data
|
||||
public static class BrowserCall {
|
||||
/** 工具内部名(点分),回传结果时原样带回 */
|
||||
private String name;
|
||||
/** 中文简称(进度展示) */
|
||||
private String title;
|
||||
/** 模型给的参数(回显给用户看「在查什么」;回传时原样带回) */
|
||||
private Map<String, Object> arguments;
|
||||
/** 是否写操作 */
|
||||
private boolean write;
|
||||
|
||||
/** GET / POST_JSON / POST_FORM */
|
||||
private String method;
|
||||
/** 相对当前站点根的路径与查询串,如 /home-leave/api/activity/List?keyword=运动会 */
|
||||
private String pathAndQuery;
|
||||
/** POST 时的请求体(GET 为 null) */
|
||||
private String body;
|
||||
/** POST 时的 Content-Type */
|
||||
private String contentType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.yunhai.agent.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 前端发起的一次对话请求。
|
||||
*/
|
||||
@Data
|
||||
public class ChatRequest {
|
||||
|
||||
/** 会话 id;首次为空,服务端生成并在响应里带回,前端后续复用 */
|
||||
private String sessionId;
|
||||
|
||||
/** 用户输入的自然语言 */
|
||||
private String message;
|
||||
|
||||
/** 是否允许调用工具(默认允许);调试/纯问答可置 false */
|
||||
private Boolean enableTools = true;
|
||||
|
||||
/** 用户对上一次写操作的确认结果(预留:二次确认场景) */
|
||||
private Boolean confirmed;
|
||||
|
||||
/**
|
||||
* 表单提交:用户在补全表单里填完直接提交。
|
||||
* <p>非空时服务端<b>直接执行</b>指定工具(不再让模型猜该不该调、参数是什么),
|
||||
* 保证「填了就一定按填的提交」。
|
||||
*/
|
||||
private FormSubmit formSubmit;
|
||||
|
||||
/**
|
||||
* 浏览器代执行的结果回传(方案 A):与 {@link #formSubmit} 同级的「续跑」入口。
|
||||
* <p>前端用用户登录态调用模块接口后,把每个调用的原始响应带回;
|
||||
* 服务端重新查注册表解析结果、喂回模型生成最终回答。
|
||||
*/
|
||||
private java.util.List<ToolResultItem> toolResult;
|
||||
|
||||
/** 一次代执行调用的回传项(与挂起载荷里的 BrowserCall 按 name 对应) */
|
||||
@Data
|
||||
public static class ToolResultItem {
|
||||
/** 工具内部名(点分),与挂起时一致 */
|
||||
private String name;
|
||||
/** 模型参数原样带回(审计与轨迹展示用) */
|
||||
private Map<String, Object> arguments;
|
||||
/** HTTP 状态码;网络层失败时为 null */
|
||||
private Integer status;
|
||||
/** 响应体原文 */
|
||||
private String body;
|
||||
/** 网络层错误(fetch 失败/超时/跨域),有值时 status 无意义 */
|
||||
private String error;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class FormSubmit {
|
||||
/** 目标工具名,如 leave.submit */
|
||||
private String tool;
|
||||
/** 用户填写的参数(键与业务接口参数名一致) */
|
||||
private Map<String, Object> args;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.yunhai.agent.model;
|
||||
|
||||
import com.yunhai.agent.tool.FormRequest;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 一次对话的完整结果。
|
||||
*/
|
||||
@Data
|
||||
public class ChatResponse {
|
||||
|
||||
private String sessionId;
|
||||
|
||||
/** 智能体最终回复(自然语言) */
|
||||
private String reply;
|
||||
|
||||
/** 本轮执行过的工具调用(按顺序) */
|
||||
private List<ToolCallTrace> toolCalls = new ArrayList<>();
|
||||
|
||||
/** 是否发生了写操作(前端据此提示「已为你提交」) */
|
||||
private boolean wroteSomething;
|
||||
|
||||
/** 建议跳转的路由(写操作后给「去查看」按钮用) */
|
||||
private String landingPath;
|
||||
|
||||
/** 循环轮数 / token 用量,便于观测 */
|
||||
private int rounds;
|
||||
private Integer promptTokens;
|
||||
private Integer completionTokens;
|
||||
|
||||
/** 会话被重置或异常时的提示 */
|
||||
private String warning;
|
||||
|
||||
/**
|
||||
* 信息不全时下发的「补全表单」:前端渲染成可填卡片,用户填完直接提交。
|
||||
* <p>本轮正常执行完毕(或纯问答)时为 null。
|
||||
*/
|
||||
private FormRequest form;
|
||||
|
||||
/**
|
||||
* 「浏览器代执行」挂起载荷(方案 A):非空表示本轮工具调用需要
|
||||
* 前端用用户登录态调用模块接口并回传结果({@code toolResult})续跑。
|
||||
*/
|
||||
private BrowserToolRequest browserTool;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.yunhai.agent.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 一次工具调用的执行轨迹(回传前端渲染「智能体做了什么」)。
|
||||
*/
|
||||
@Data
|
||||
public class ToolCallTrace {
|
||||
|
||||
private String name;
|
||||
private String title;
|
||||
|
||||
/** 业务模块标识(前端据此拼出该模块页面地址做「去处理」跳转) */
|
||||
private String module;
|
||||
|
||||
/** 模型给出的参数(已脱敏:不含身份信息) */
|
||||
private Map<String, Object> arguments;
|
||||
|
||||
private boolean success = true;
|
||||
private String error;
|
||||
|
||||
/** 是否产生副作用的写操作 */
|
||||
private boolean write;
|
||||
|
||||
/** 执行后建议跳转的前端路由 */
|
||||
private String landingPath;
|
||||
|
||||
private long costMs;
|
||||
}
|
||||
Reference in New Issue
Block a user