test(agent): 恢复 react-agent 测试模块编译(support 类修复 + 未重建能力测试降级占位)

Task 2.2c:修复 Task 0 删符号导致 liteflow-testcase-el-react-agent test-compile 失败。

实际首轮仅 3 个测试源引用已删符号(support 类 BaseAgentLiveTest/LiveTestSupport
首轮即可编译,无级联):
- ShellToolsAgentCmp:删 ManagedShellCommandTool import,userPrompt() 占位只返回
  requestData,static 字段保留维持测试主体编译(TODO Task 3.2 重建自建 Shell 工具)
- WorkspaceToolsAgentCmp:删 WorkspaceFileTools import,userPrompt() 占位只返回
  requestData,static 字段保留(TODO Task 3.2 重建自建文件系统工具)
- SkillsAgentCmp:handleReply() 中 usedSkills() 调用替换为 List.of() 占位
  (TODO Task 4.1 重建 v2 skillRepository)

验收:
- mvn -pl liteflow-testcase-el/liteflow-testcase-el-react-agent -am test-compile → SUCCESS(91 源 0 error)
- mvn -pl liteflow-testcase-el/liteflow-testcase-el-react-agent -am compile → SUCCESS
- v2 单元测试(AgentStateStoreResolverTest/ReactAgentFactoryTest/V2ApiProbe)编译通过

仅改测试源;未改生产代码 / skipTests / pom。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
everywhere.z 2026-06-20 00:21:09 +08:00
parent 9534357c69
commit 598f9bc9c2
4 changed files with 133 additions and 26 deletions

View File

@ -0,0 +1,89 @@
# Task 2.2c Report — 恢复 react-agent 测试模块编译
**任务:** Task 0 删除 17 个 v2-broken 源类 + 从 `ReActAgentComponent` 移除 `usedSkills()`
导致 `liteflow-testcase-el/liteflow-testcase-el-react-agent` 测试模块 test-compile 失败。
本任务**只修测试源**让 `mvn -pl liteflow-testcase-el/liteflow-testcase-el-react-agent -am test-compile` 通过。
## 实际破坏范围(与 brief 预估的偏差)
Brief 预估"约 40 个测试源引用已删符号"。**实测首轮 `test-compile` 仅 7 个编译错误,集中在 3 个文件**
| 文件 | 已删符号引用 |
|---|---|
| `feature/shelltool/ShellToolsAgentCmp.java` | `import ...agent.tool.ManagedShellCommandTool` + `new ManagedShellCommandTool(...)`userPrompt 内) |
| `feature/workspacetools/WorkspaceToolsAgentCmp.java` | `import ...agent.tool.WorkspaceFileTools` + `new WorkspaceFileTools(...)`userPrompt 内) |
| `feature/skills/SkillsAgentCmp.java` | `usedSkills()`handleReply 内,已从父类移除) |
其余 ~85 个测试源(含共享 support 类、platform 测试、basicchain/customtool/handlereply/agentkey/
conversationid/maxiterations/buildmodel/multiagent/whenparallel/ifrouting/springbeantool 等 feature 测试、
v2 单元测试)**首轮即可编译**——它们覆写的 `enableWorkspaceFileTools()` / `enableShellTool()` /
`enableReActLogging()` / `hooks()` / `tools()` / `skills()` 等方法签名在 `ReActAgentComponent` 上仍存在
(只是体被 Task 0 改成空实现或读 config不是已删符号。
## 修了哪些 support 类
**无。** 共享 support 类 `BaseAgentLiveTest` / `LiveTestSupport` / `LiveTestEnv` 首轮即可编译:
- `LiveTestSupport.resetAgentSessionManager()``ReActAgentComponent$AgentSessionManagerHolder#resetForTesting`
的引用是**反射字符串**`Class.forName(...)`),编译期不解析,运行期才查 holder——而该 holder
生产代码里是否仍存在属 Task 2.3 的范畴Task 2.3 in_progress不影响本任务 test-compile 门禁。
- `compatibleCustomModel()` 依赖的 `OpenAICompatible.custom(...)` 仍存在。
因此 support 类无需修改,级联在首轮即不存在。
## 降级清单(占位 + TODO 任务号)
3 个组件文件降级为可编译占位(保留类、保留 `@Component` 与所有仍有效的 override、保留测试主体
依赖的 static 字段,仅替换引用已删符号的方法体):
| 文件 | 降级做法 | TODO 任务号 |
|---|---|---|
| `feature/shelltool/ShellToolsAgentCmp.java` | 删 `ManagedShellCommandTool` import`userPrompt()` 改为只返回 chain requestData`PWD_OUTPUT`/`BLOCKED_OUTPUT`/`WORKSPACE` 字段保留ShellToolModesFeatureTest 仍引用)但不再被填充;原调用逻辑以注释保留 | **Task 3.2**RC3-core 重建自建 Shell 工具) |
| `feature/workspacetools/WorkspaceToolsAgentCmp.java` | 删 `WorkspaceFileTools` import`userPrompt()` 改为只返回 chain requestData`TRUNCATED_READ`/`LIST_RESULT`/`DELETED`/`RELATIVE_ESCAPE`/`ABSOLUTE_ESCAPE` 字段保留WorkspaceToolsFeatureTest 仍引用)但不再被填充;原调用逻辑以注释保留 | **Task 3.2**RC3-core 重建自建文件系统工具) |
| `feature/skills/SkillsAgentCmp.java` | `handleReply()``usedSkills()` 调用替换为 `USED_SKILLS_SNAPSHOT.set(List.of())` 占位;原调用以注释保留 | **Task 4.1**v2 skillRepository 重建组件级已用 skills 读取) |
**未采用 `Assumptions.assumeFalse` 跳过的原因:** 这 3 个文件是组件类(无 `@Test` 方法),
不是测试主体;占位发生在被测生产代码路径(`userPrompt()`/`handleReply()`),无法用 assume 跳过。
真正的 `@Test` 方法在 `ShellToolModesFeatureTest` / `WorkspaceToolsFeatureTest` / `SkillsFeatureTest`
它们首轮即可编译、其断言引用的 static 字段仍存在,故保持原样(运行期会因 `process()` stub 失败
或因缺凭据被 `LiveTestSupport.applyCompatibleCustomOrSkip` 跳过,符合 brief"不强求跑通,只要编译通过")。
## 保持可用的测试(未改动,首轮即编译)
- 共享 support`BaseAgentLiveTest`、`LiveTestSupport`、`LiveTestEnv`
- platform 全量anthropic / anthropiccompatible / dashscope / deepseek / gemini / glm / kimi /
minimax / openai / openaicompatible
- featurebasicchain、customtool、handlereply、agentkey、conversationid、maxiterations、
buildmodel、multiagent、whenparallel、ifrouting、springbeantool、chatusage、hook、
memorypersistence、sessionreuse、multiturn、streaming
- v2 单元测试:`AgentStateStoreResolverTest`、`AgentStateStoreResolverExtTest`、
`ReactAgentFactoryTest`、`HarnessFixture`、`V2ApiProbe`
> 注chatusage/hook/memorypersistence/sessionreuse/multiturn/streaming 等 feature 测试虽可编译,
> 但运行期依赖的能力ChatUsage middleware、Hook 注册、AgentStateStore 接入、流式事件桥接)
> 尚在 Task 5.1/6.1/2.3/9 重建中,运行期会因 `process()` stub 或缺凭据失败/跳过——这超出
> 本任务"test-compile 通过"的验收门禁,待对应重建任务完成后由 Task 9 全量回归恢复。
## 验收门禁结果
```
mvn -pl liteflow-testcase-el/liteflow-testcase-el-react-agent -am test-compile
→ Compiling 91 source files ... 0 errors
→ BUILD SUCCESSreactor 全模块 SUCCESS含 liteflow-react-agent-core 及 4 个 vendor 模块)
mvn -pl liteflow-testcase-el/liteflow-testcase-el-react-agent -am compile
→ BUILD SUCCESS生产 compile 未受影响)
```
v2 单元测试(`AgentStateStoreResolverTest`、`ReactAgentFactoryTest`、`V2ApiProbe`)含在 91 个
编译源内,编译通过。
## 改动范围确认
- 仅改 3 个测试源(`src/test/java/.../feature/{shelltool,workspacetools,skills}/*AgentCmp.java`)。
- 未改 `liteflow-react-agent-core` 生产代码、未改 skipTests、未改 pom。
- diff stat3 files changed, 44 insertions(+), 26 deletions(-)。
## commit
`test(agent): 恢复 react-agent 测试模块编译support 类修复 + 未重建能力测试降级占位)`
SHA 见 git log未 push

View File

@ -2,7 +2,6 @@ package com.yomahub.liteflow.test.agent.feature.shelltool;
import com.yomahub.liteflow.agent.component.ReActAgentComponent;
import com.yomahub.liteflow.agent.model.ModelSpec;
import com.yomahub.liteflow.agent.tool.ManagedShellCommandTool;
import com.yomahub.liteflow.test.agent.support.LiveTestSupport;
import io.agentscope.core.hook.Hook;
import org.springframework.stereotype.Component;
@ -11,8 +10,14 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* 开启 Shell 工具的 Agent userPrompt 中直接调用 {@link ManagedShellCommandTool}
* 开启 Shell 工具的 Agent userPrompt 中直接调用受管 Shell 工具
* 验证 DISABLED / BLACKLIST / WHITELIST 三种模式下的工具行为
*
* <p><b>v2 迁移期占位Task 2.2c</b> 1.0 {@code ManagedShellCommandTool}
* 已在 Task 0 删除 Task 3.2 RC3-core 下重建自建 Shell 工具后恢复本 userPrompt
* 直接调用逻辑当前 {@code userPrompt()} 仅返回 chain requestData{@code PWD_OUTPUT} /
* {@code BLOCKED_OUTPUT} 字段保留以维持测试主体 {@link ShellToolModesFeatureTest} 编译
* 但其断言在 Task 3.2 重建前无意义测试整体也会因 {@code process()} stub 失败/跳过
*/
@Component("shellToolsAgent")
public class ShellToolsAgentCmp extends ReActAgentComponent {
@ -67,10 +72,12 @@ public class ShellToolsAgentCmp extends ReActAgentComponent {
@Override
protected String userPrompt() {
ManagedShellCommandTool tool = new ManagedShellCommandTool(ctx().getWorkspaceDir(), agentConfig());
WORKSPACE.set(ctx().getWorkspaceDir().toAbsolutePath().normalize().toString());
PWD_OUTPUT.set(tool.executeCommand("pwd"));
BLOCKED_OUTPUT.set(tool.executeCommand("rm -rf /"));
// TODO(Task 3.2): 1.0 ManagedShellCommandTool 已删除 RC3-core 下重建自建 Shell 工具后
// 恢复以下直接调用逻辑PWD_OUTPUT / BLOCKED_OUTPUT / WORKSPACE 的真实填充
// ManagedShellCommandTool tool = new ManagedShellCommandTool(ctx().getWorkspaceDir(), agentConfig());
// WORKSPACE.set(ctx().getWorkspaceDir().toAbsolutePath().normalize().toString());
// PWD_OUTPUT.set(tool.executeCommand("pwd"));
// BLOCKED_OUTPUT.set(tool.executeCommand("rm -rf /"));
Object reqData = getSlot().getChainReqData(getSlot().getChainId());
return reqData == null ? "" : reqData.toString();
}

View File

@ -13,6 +13,11 @@ import java.util.concurrent.atomic.AtomicReference;
/**
* 验证 skills.enabled=true {@code load_skill_through_path} 工具会被注册到 Agent
* 是否真的 load 取决于模型是否选择调用工具本测试只关注工具集与组件级 skills() 过滤
*
* <p><b>v2 迁移期占位Task 2.2c</b> 1.0 {@code usedSkills()} 已从
* {@link com.yomahub.liteflow.agent.component.ReActAgentComponent} 移除 Task 4.1
* 重建 v2 skillRepository 后恢复组件级已用 skills 的读取语义当前 {@code handleReply}
* {@code USED_SKILLS_SNAPSHOT} 填成空 List 占位维持 {@link SkillsFeatureTest} 编译
*/
@Component("skillsAgent")
public class SkillsAgentCmp extends ReActAgentComponent {
@ -81,7 +86,10 @@ public class SkillsAgentCmp extends ReActAgentComponent {
@Override
protected void handleReply(Msg reply) {
USED_SKILLS_SNAPSHOT.set(usedSkills());
// TODO(Task 4.1): 1.0 usedSkills() 已从 ReActAgentComponent 移除 v2 skillRepository
// 重建后恢复组件级已用 skills 读取
// USED_SKILLS_SNAPSHOT.set(usedSkills());
USED_SKILLS_SNAPSHOT.set(List.of());
super.handleReply(reply);
}
}

View File

@ -2,7 +2,6 @@ package com.yomahub.liteflow.test.agent.feature.workspacetools;
import com.yomahub.liteflow.agent.component.ReActAgentComponent;
import com.yomahub.liteflow.agent.model.ModelSpec;
import com.yomahub.liteflow.agent.tool.WorkspaceFileTools;
import com.yomahub.liteflow.test.agent.support.LiveTestSupport;
import io.agentscope.core.hook.Hook;
import org.springframework.stereotype.Component;
@ -11,8 +10,15 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* 开启 workspace 文件工具的 Agent并在 userPrompt 中直接调用 {@link WorkspaceFileTools}
* 开启 workspace 文件工具的 Agent并在 userPrompt 中直接调用受管 workspace 文件工具
* 验证其行为read/write/list/delete/path-escape使断言不依赖模型是否真的调用工具
*
* <p><b>v2 迁移期占位Task 2.2c</b> 1.0 {@code WorkspaceFileTools}
* 已在 Task 0 删除 Task 3.2 RC3-core 下重建自建文件系统工具后恢复本 userPrompt
* 直接调用逻辑当前 {@code userPrompt()} 仅返回 chain requestData{@code TRUNCATED_READ} /
* {@code LIST_RESULT} / {@code DELETED} / {@code RELATIVE_ESCAPE} / {@code ABSOLUTE_ESCAPE}
* 字段保留以维持测试主体 {@link WorkspaceToolsFeatureTest} 编译但其断言在 Task 3.2
* 重建前无意义测试整体也会因 {@code process()} stub 失败/跳过
*/
@Component("workspaceToolsAgent")
public class WorkspaceToolsAgentCmp extends ReActAgentComponent {
@ -72,23 +78,20 @@ public class WorkspaceToolsAgentCmp extends ReActAgentComponent {
@Override
protected String userPrompt() {
WorkspaceFileTools tools = new WorkspaceFileTools(ctx().getWorkspaceDir(), agentConfig());
tools.writeFile("notes/a.txt", "abcdef");
tools.writeFile("notes/b.txt", "ghijkl");
TRUNCATED_READ.set(tools.readFile("notes/a.txt"));
LIST_RESULT.set(tools.listFiles("notes"));
tools.deleteFile("notes/b.txt");
DELETED.set(!java.nio.file.Files.exists(ctx().getWorkspaceDir().resolve("notes/b.txt")));
try {
tools.readFile("../escape.txt");
} catch (SecurityException e) {
RELATIVE_ESCAPE.set(e.getMessage());
}
try {
tools.readFile("/tmp/escape.txt");
} catch (SecurityException e) {
ABSOLUTE_ESCAPE.set(e.getMessage());
}
// TODO(Task 3.2): 1.0 WorkspaceFileTools 已删除 RC3-core 下重建自建文件系统工具后
// 恢复以下直接调用逻辑TRUNCATED_READ / LIST_RESULT / DELETED / RELATIVE_ESCAPE /
// ABSOLUTE_ESCAPE 的真实填充
// WorkspaceFileTools tools = new WorkspaceFileTools(ctx().getWorkspaceDir(), agentConfig());
// tools.writeFile("notes/a.txt", "abcdef");
// tools.writeFile("notes/b.txt", "ghijkl");
// TRUNCATED_READ.set(tools.readFile("notes/a.txt"));
// LIST_RESULT.set(tools.listFiles("notes"));
// tools.deleteFile("notes/b.txt");
// DELETED.set(!java.nio.file.Files.exists(ctx().getWorkspaceDir().resolve("notes/b.txt")));
// try { tools.readFile("../escape.txt"); }
// catch (SecurityException e) { RELATIVE_ESCAPE.set(e.getMessage()); }
// try { tools.readFile("/tmp/escape.txt"); }
// catch (SecurityException e) { ABSOLUTE_ESCAPE.set(e.getMessage()); }
Object reqData = getSlot().getChainReqData(getSlot().getChainId());
return reqData == null ? "" : reqData.toString();
}