mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-06-10 11:17:00 +08:00
refactor(agent): rename WORKSPACE_FILE to LOCAL_FILE for memory storage mode
该模式的 .agent-session 目录实际位于 workspace.root 之下、与各 session 的 workspace 子目录平级而非嵌套,旧名 WORKSPACE_FILE 容易误导为"存储在 某个 workspace 内部"。LOCAL_FILE 与 REDIS、MYSQL 同层级地描述后端类型, 更准确地反映实际行为。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -467,7 +467,7 @@ Session ID 只允许直接使用 `[a-zA-Z0-9_-]+`。其他字符会被 URL 编
|
||||
| --- | --- | --- |
|
||||
| `JVM` | 默认值,使用 AgentScope 的 JVM 内 Session | 单进程内多轮对话,进程退出后可丢失 |
|
||||
| `NONE` | 不加载也不保存持久化 Session | 不需要持久化;如需严格无状态,配合唯一 `sessionId` 使用 |
|
||||
| `WORKSPACE_FILE` | 保存到 `workspace.root/.agent-session/<sessionId>/` | 本地文件持久化、开发测试、小规模部署 |
|
||||
| `LOCAL_FILE` | 保存到 `workspace.root/.agent-session/<sessionId>/` | 本地文件持久化、开发测试、小规模部署 |
|
||||
| `REDIS` | 使用用户提供的 Redis 客户端 Bean | 多实例共享短期会话 |
|
||||
| `MYSQL` | 使用用户提供的 `DataSource` Bean | 需要数据库持久化和运维治理 |
|
||||
|
||||
@@ -479,10 +479,10 @@ Session ID 只允许直接使用 `[a-zA-Z0-9_-]+`。其他字符会被 URL 编
|
||||
| `save-after-call` | `true` | 调用成功后保存记忆 |
|
||||
| `save-on-error` | `true` | 调用抛错时也尝试保存记忆 |
|
||||
|
||||
`WORKSPACE_FILE` 示例:
|
||||
`LOCAL_FILE` 示例:
|
||||
|
||||
```properties
|
||||
liteflow.agent.session.memory.mode=WORKSPACE_FILE
|
||||
liteflow.agent.session.memory.mode=LOCAL_FILE
|
||||
liteflow.agent.session.memory.load-on-first-use=true
|
||||
liteflow.agent.session.memory.save-after-call=true
|
||||
liteflow.agent.session.memory.save-on-error=true
|
||||
@@ -526,7 +526,7 @@ LiteFlow 不创建 JDBC 连接池,`DataSource` 也需要由业务应用提供
|
||||
└── .agent-session/
|
||||
```
|
||||
|
||||
`<sessionId>/` 是 Agent 工具读写文件的目录;`.agent-session/` 只在 `session.memory.mode=WORKSPACE_FILE` 时创建,用于保存 AgentScope 的记忆文件。
|
||||
`<sessionId>/` 是 Agent 工具读写文件的目录;`.agent-session/` 只在 `session.memory.mode=LOCAL_FILE` 时创建,用于保存 AgentScope 的记忆文件。
|
||||
|
||||
### 6.2 Workspace 配置
|
||||
|
||||
@@ -769,7 +769,7 @@ liteflow.agent.anthropic-compatible.gateway.base-url=https://anthropic-gateway.e
|
||||
| `workspace root does not exist` | `auto-create=false` 且目录不存在 | 提前创建目录,或开启 `auto-create` |
|
||||
| `Missing API key: please configure liteflow.agent.openai.api-key` | 对应平台凭据未配置 | 配置对应平台的 `api-key` |
|
||||
| 多轮对话没有记忆 | 默认 Session ID 由 `NanoIdSessionIdGenerator` 每次随机生成 | 覆写 `resolveSessionId`,返回稳定的业务会话 ID |
|
||||
| 重启后没有历史记忆 | `session.memory.mode=JVM` 或 `NONE` | 改为 `WORKSPACE_FILE`、`REDIS` 或 `MYSQL` |
|
||||
| 重启后没有历史记忆 | `session.memory.mode=JVM` 或 `NONE` | 改为 `LOCAL_FILE`、`REDIS` 或 `MYSQL` |
|
||||
| Redis 模式启动失败 | 未配置 Bean 名,或 Bean 类型与 `client-type` 不匹配 | 检查 `bean-name`、`client-type` 和 classpath 依赖 |
|
||||
| MySQL 模式启动失败 | 未配置 `DataSource` Bean,或 Bean 类型错误 | 配置正确的 `data-source-bean-name` |
|
||||
| Shell 返回 `command 'xxx' not allowed by whitelist` | 白名单模式下命令未放行 | 加入白名单,或继续保持禁用 |
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.yomahub.liteflow.property.agent;
|
||||
|
||||
/**
|
||||
* 仅在 {@link MemoryStorageMode#LOCAL_FILE} 模式下生效的配置项,
|
||||
* 对应配置段 {@code liteflow.agent.session.memory.local-file.*}。
|
||||
*
|
||||
* <p>该模式下记忆持久化会落盘到 {@code workspace.root} 之下的
|
||||
* {@link #SUB_DIR} 子目录中,按 {@code sessionId} 再分一层;该目录与
|
||||
* 各 session 自己的 workspace({@code workspace.root/<sessionId>/})平级而不嵌套,
|
||||
* 这样可以避免内置 {@code WorkspaceFileTools}
|
||||
* 读到或覆盖 agent 自己的记忆,也让 {@code cleanup-on-session-expire}
|
||||
* 在清空 workspace 子目录时不会误删持久化的记忆。
|
||||
*
|
||||
* <p>该位置故意硬编码、不暴露为可配置项:保证不同会话之间结构一致,
|
||||
* 且与 Redis、MySQL 等远程后端的"持久化与 workspace 生命周期解耦"语义对齐。
|
||||
* 需要自定义存储位置的用户应通过 SPI 注入自己的
|
||||
* {@code AgentSessionFactory} 实现。
|
||||
*/
|
||||
public class LocalFileMemoryConfig {
|
||||
|
||||
/** 会话 JSON 文件存放的固定子目录名,位于 {@code workspace.root} 之下。 */
|
||||
public static final String SUB_DIR = ".agent-session";
|
||||
}
|
||||
@@ -6,7 +6,7 @@ package com.yomahub.liteflow.property.agent;
|
||||
*
|
||||
* <p>本配置与 {@link SessionConfig} 是正交的关注点:
|
||||
* {@link SessionConfig} 控制 JVM 内 agent 实例的缓存、空闲超时与 LRU 淘汰;
|
||||
* 而本配置决定 agent 的对话历史 <em>持久化到哪里</em>,例如 JVM 堆内、工作区文件、
|
||||
* 而本配置决定 agent 的对话历史 <em>持久化到哪里</em>,例如 JVM 堆内、本地文件、
|
||||
* Redis 或 MySQL。
|
||||
*/
|
||||
public class MemoryStorageConfig {
|
||||
@@ -19,8 +19,8 @@ public class MemoryStorageConfig {
|
||||
*/
|
||||
private MemoryStorageMode mode = MemoryStorageMode.JVM;
|
||||
|
||||
/** {@link MemoryStorageMode#WORKSPACE_FILE} 模式下生效的子配置。 */
|
||||
private WorkspaceMemoryConfig workspace = new WorkspaceMemoryConfig();
|
||||
/** {@link MemoryStorageMode#LOCAL_FILE} 模式下生效的子配置。 */
|
||||
private LocalFileMemoryConfig localFile = new LocalFileMemoryConfig();
|
||||
|
||||
/** {@link MemoryStorageMode#REDIS} 模式下生效的子配置。 */
|
||||
private RedisMemoryConfig redis = new RedisMemoryConfig();
|
||||
@@ -60,12 +60,12 @@ public class MemoryStorageConfig {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public WorkspaceMemoryConfig getWorkspace() {
|
||||
return workspace;
|
||||
public LocalFileMemoryConfig getLocalFile() {
|
||||
return localFile;
|
||||
}
|
||||
|
||||
public void setWorkspace(WorkspaceMemoryConfig workspace) {
|
||||
this.workspace = workspace;
|
||||
public void setLocalFile(LocalFileMemoryConfig localFile) {
|
||||
this.localFile = localFile;
|
||||
}
|
||||
|
||||
public RedisMemoryConfig getRedis() {
|
||||
|
||||
@@ -6,8 +6,8 @@ package com.yomahub.liteflow.property.agent;
|
||||
* <ul>
|
||||
* <li>{@link #NONE} – 不保留也不持久化任何记忆,等价于无状态 agent</li>
|
||||
* <li>{@link #JVM} – 仅保留在 JVM 堆内(默认行为,与 2.15.4 之前版本一致)</li>
|
||||
* <li>{@link #WORKSPACE_FILE} – 通过 AgentScope 的 JsonSession,把记忆以 JSON 文件
|
||||
* 形式持久化到每个会话工作区目录下</li>
|
||||
* <li>{@link #LOCAL_FILE} – 通过 AgentScope 的 JsonSession,把记忆以 JSON 文件
|
||||
* 形式持久化到本地磁盘(与各 session 的 workspace 子目录平级)</li>
|
||||
* <li>{@link #REDIS} – 通过 AgentScope 的 RedisSession 持久化,
|
||||
* 需要用户提供 {@code RedissonClient} / {@code UnifiedJedis} / {@code RedisClient} bean</li>
|
||||
* <li>{@link #MYSQL} – 通过 AgentScope 的 MysqlSession 持久化,
|
||||
@@ -22,8 +22,8 @@ public enum MemoryStorageMode {
|
||||
/** 仅 JVM 堆内缓存,进程重启即丢失;为默认值。 */
|
||||
JVM,
|
||||
|
||||
/** 工作区文件持久化,每个会话一个 JSON 文件,便于排查与离线分析。 */
|
||||
WORKSPACE_FILE,
|
||||
/** 本地文件持久化,每个会话一份 JSON 文件,便于排查与离线分析。 */
|
||||
LOCAL_FILE,
|
||||
|
||||
/** Redis 持久化,适合多实例部署、高并发场景。 */
|
||||
REDIS,
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.yomahub.liteflow.property.agent;
|
||||
|
||||
/**
|
||||
* 仅在 {@link MemoryStorageMode#WORKSPACE_FILE} 模式下生效的配置项,
|
||||
* 对应配置段 {@code liteflow.agent.session.memory.workspace.*}。
|
||||
*
|
||||
* <p>该模式下记忆持久化会落盘到每个会话工作区目录下的固定子目录({@link #SUB_DIR}),
|
||||
* 该位置故意硬编码、不暴露为可配置项:一方面避免与工具产生的业务文件混在一起,
|
||||
* 另一方面保证不同会话之间结构一致。需要自定义存储位置的用户应通过 SPI
|
||||
* 注入自己的 {@code AgentSessionFactory} 实现。
|
||||
*/
|
||||
public class WorkspaceMemoryConfig {
|
||||
|
||||
/** 会话 JSON 文件存放的固定子目录名(位于工作区根目录下)。 */
|
||||
public static final String SUB_DIR = ".agent-session";
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import io.agentscope.core.session.Session;
|
||||
/**
|
||||
* 用于为 {@link io.agentscope.core.session.Session} 接入额外持久化后端的 SPI。
|
||||
*
|
||||
* <p>框架内置模式({@code JVM}、{@code WORKSPACE_FILE}、{@code REDIS}、
|
||||
* <p>框架内置模式({@code JVM}、{@code LOCAL_FILE}、{@code REDIS}、
|
||||
* {@code MYSQL}、{@code NONE})。需要其他后端(例如 PostgreSQL、OSS、
|
||||
* 加密 JSON)的用户,可以在 {@code META-INF/services/}{@link AgentSessionFactory}
|
||||
* 下注册自定义工厂。
|
||||
|
||||
@@ -15,10 +15,10 @@ import java.util.ServiceLoader;
|
||||
* <p>解析顺序:
|
||||
* <ol>
|
||||
* <li>通过 {@link ServiceLoader} 注册的外部工厂</li>
|
||||
* <li>框架内置工厂(JVM、workspace、Redis、MySQL、none)</li>
|
||||
* <li>框架内置工厂(JVM、local-file、Redis、MySQL、none)</li>
|
||||
* </ol>
|
||||
* 出现冲突时外部工厂优先,因此用户可以覆盖内置实现
|
||||
* (例如用自定义加密 JSON 工厂替换默认 workspace 工厂)。
|
||||
* (例如用自定义加密 JSON 工厂替换默认本地文件工厂)。
|
||||
*/
|
||||
public final class AgentSessionFactoryRegistry {
|
||||
|
||||
@@ -27,7 +27,7 @@ public final class AgentSessionFactoryRegistry {
|
||||
static {
|
||||
// 先注册内置实现;如果存在 SPI 实现,再由 SPI 覆盖。
|
||||
register(new InMemoryAgentSessionFactory());
|
||||
register(new WorkspaceAgentSessionFactory());
|
||||
register(new LocalFileAgentSessionFactory());
|
||||
register(new RedisAgentSessionFactory());
|
||||
register(new MysqlAgentSessionFactory());
|
||||
register(new NoneAgentSessionFactory());
|
||||
|
||||
@@ -10,7 +10,7 @@ import io.agentscope.core.session.Session;
|
||||
*
|
||||
* <p>注意:状态仍会在同一个 JVM 内跨调用保留(适合希望在单进程内保留多轮记忆的场景),
|
||||
* 但进程退出后会丢失。如果需要跨重启持久化,请选择
|
||||
* {@code WORKSPACE_FILE}、{@code REDIS} 或 {@code MYSQL}。
|
||||
* {@code LOCAL_FILE}、{@code REDIS} 或 {@code MYSQL}。
|
||||
*/
|
||||
public class InMemoryAgentSessionFactory implements AgentSessionFactory {
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ package com.yomahub.liteflow.agent.session.factory;
|
||||
|
||||
import com.yomahub.liteflow.agent.exception.AgentConfigException;
|
||||
import com.yomahub.liteflow.property.agent.AgentConfig;
|
||||
import com.yomahub.liteflow.property.agent.LocalFileMemoryConfig;
|
||||
import com.yomahub.liteflow.property.agent.MemoryStorageMode;
|
||||
import com.yomahub.liteflow.property.agent.WorkspaceMemoryConfig;
|
||||
import io.agentscope.core.session.JsonSession;
|
||||
import io.agentscope.core.session.Session;
|
||||
|
||||
@@ -14,28 +14,29 @@ import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* 通过把 JSON 文件存储在 {@code workspace.root/.agent-session/<sessionId>/}
|
||||
* 下来支持 {@link MemoryStorageMode#WORKSPACE_FILE}。
|
||||
* 下来支持 {@link MemoryStorageMode#LOCAL_FILE}。
|
||||
*
|
||||
* <p>session 存储子目录特意与 {@code workspace.root/<sessionId>/}
|
||||
* 形式的单 session 工具 workspace 分离,避免
|
||||
* {@link com.yomahub.liteflow.agent.tool.WorkspaceFileTools} 读取或覆盖
|
||||
* agent 自身记忆。
|
||||
* <p>session 存储子目录与各 session 的 workspace({@code workspace.root/<sessionId>/})
|
||||
* 平级而非嵌套:一方面避免 {@link com.yomahub.liteflow.agent.tool.WorkspaceFileTools}
|
||||
* 读到或覆盖 agent 自己的记忆;另一方面让 {@code cleanup-on-session-expire}
|
||||
* 在递归清空 workspace 子目录时不会误删持久化的记忆,
|
||||
* 与 Redis、MySQL 后端的"持久化与 workspace 生命周期解耦"语义保持一致。
|
||||
*/
|
||||
public class WorkspaceAgentSessionFactory implements AgentSessionFactory {
|
||||
public class LocalFileAgentSessionFactory implements AgentSessionFactory {
|
||||
|
||||
@Override
|
||||
public MemoryStorageMode mode() {
|
||||
return MemoryStorageMode.WORKSPACE_FILE;
|
||||
return MemoryStorageMode.LOCAL_FILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session create(AgentConfig cfg) {
|
||||
if (cfg.getWorkspace() == null || cfg.getWorkspace().getRoot() == null) {
|
||||
throw new AgentConfigException(
|
||||
"liteflow.agent.workspace.root is required when session.memory.mode=WORKSPACE_FILE");
|
||||
"liteflow.agent.workspace.root is required when session.memory.mode=LOCAL_FILE");
|
||||
}
|
||||
Path root = Paths.get(cfg.getWorkspace().getRoot()).toAbsolutePath().normalize()
|
||||
.resolve(WorkspaceMemoryConfig.SUB_DIR);
|
||||
.resolve(LocalFileMemoryConfig.SUB_DIR);
|
||||
try {
|
||||
Files.createDirectories(root);
|
||||
} catch (IOException e) {
|
||||
Reference in New Issue
Block a user