From b64706c26a4760f40d4def97aa1e6374b835d499 Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Sun, 19 Apr 2026 19:08:23 +0800 Subject: [PATCH] feat(core): add AgentConfig POJOs for ReAct agent configuration Introduce AgentConfig and nested POJOs (WorkspaceConfig, SessionConfig, ShellConfig, DefaultsConfig, PlatformCredential, ShellMode) as pure data holders with sensible defaults and zero third-party dependencies. Add JUnit 5 test dependency and surefire override to liteflow-core for TDD. Co-Authored-By: Claude Opus 4.7 --- liteflow-core/pom.xml | 17 +++++++ .../liteflow/property/agent/AgentConfig.java | 35 +++++++++++++ .../property/agent/DefaultsConfig.java | 8 +++ .../property/agent/PlatformCredential.java | 17 +++++++ .../property/agent/SessionConfig.java | 16 ++++++ .../liteflow/property/agent/ShellConfig.java | 25 ++++++++++ .../liteflow/property/agent/ShellMode.java | 7 +++ .../property/agent/WorkspaceConfig.java | 23 +++++++++ .../property/agent/AgentConfigTest.java | 50 +++++++++++++++++++ 9 files changed, 198 insertions(+) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/AgentConfig.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/DefaultsConfig.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/PlatformCredential.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/SessionConfig.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/ShellConfig.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/ShellMode.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/WorkspaceConfig.java create mode 100644 liteflow-core/src/test/java/com/yomahub/liteflow/property/agent/AgentConfigTest.java diff --git a/liteflow-core/pom.xml b/liteflow-core/pom.xml index 63fc7d6ba..c3f078993 100644 --- a/liteflow-core/pom.xml +++ b/liteflow-core/pom.xml @@ -72,5 +72,22 @@ com.github.ben-manes.caffeine caffeine + + org.junit.jupiter + junit-jupiter + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + false + + + + diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/AgentConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/AgentConfig.java new file mode 100644 index 000000000..71f7d5684 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/AgentConfig.java @@ -0,0 +1,35 @@ +package com.yomahub.liteflow.property.agent; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class AgentConfig { + private WorkspaceConfig workspace = new WorkspaceConfig(); + private SessionConfig session = new SessionConfig(); + private ShellConfig shell = new ShellConfig(); + private DefaultsConfig defaults = new DefaultsConfig(); + private PlatformCredential openai = new PlatformCredential(); + private PlatformCredential anthropic = new PlatformCredential(); + private PlatformCredential gemini = new PlatformCredential(); + private PlatformCredential dashscope = new PlatformCredential(); + private Map openaiCompatible = new LinkedHashMap<>(); + + public WorkspaceConfig getWorkspace() { return workspace; } + public void setWorkspace(WorkspaceConfig v) { this.workspace = v; } + public SessionConfig getSession() { return session; } + public void setSession(SessionConfig v) { this.session = v; } + public ShellConfig getShell() { return shell; } + public void setShell(ShellConfig v) { this.shell = v; } + public DefaultsConfig getDefaults() { return defaults; } + public void setDefaults(DefaultsConfig v) { this.defaults = v; } + public PlatformCredential getOpenai() { return openai; } + public void setOpenai(PlatformCredential v) { this.openai = v; } + public PlatformCredential getAnthropic() { return anthropic; } + public void setAnthropic(PlatformCredential v) { this.anthropic = v; } + public PlatformCredential getGemini() { return gemini; } + public void setGemini(PlatformCredential v) { this.gemini = v; } + public PlatformCredential getDashscope() { return dashscope; } + public void setDashscope(PlatformCredential v) { this.dashscope = v; } + public Map getOpenaiCompatible() { return openaiCompatible; } + public void setOpenaiCompatible(Map v) { this.openaiCompatible = v; } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/DefaultsConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/DefaultsConfig.java new file mode 100644 index 000000000..7c4e4c600 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/DefaultsConfig.java @@ -0,0 +1,8 @@ +package com.yomahub.liteflow.property.agent; + +public class DefaultsConfig { + private int maxIterations = 15; + + public int getMaxIterations() { return maxIterations; } + public void setMaxIterations(int v) { this.maxIterations = v; } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/PlatformCredential.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/PlatformCredential.java new file mode 100644 index 000000000..aa6e981b8 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/PlatformCredential.java @@ -0,0 +1,17 @@ +package com.yomahub.liteflow.property.agent; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class PlatformCredential { + private String apiKey; + private String baseUrl; + private Map extra = new LinkedHashMap<>(); + + public String getApiKey() { return apiKey; } + public void setApiKey(String apiKey) { this.apiKey = apiKey; } + public String getBaseUrl() { return baseUrl; } + public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; } + public Map getExtra() { return extra; } + public void setExtra(Map extra) { this.extra = extra; } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/SessionConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/SessionConfig.java new file mode 100644 index 000000000..78caa927c --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/SessionConfig.java @@ -0,0 +1,16 @@ +package com.yomahub.liteflow.property.agent; + +import java.time.Duration; + +public class SessionConfig { + private Duration idleTimeout = Duration.ofMinutes(30); + private Duration cleanupInterval = Duration.ofMinutes(1); + private int maxSessions = 10_000; + + public Duration getIdleTimeout() { return idleTimeout; } + public void setIdleTimeout(Duration v) { this.idleTimeout = v; } + public Duration getCleanupInterval() { return cleanupInterval; } + public void setCleanupInterval(Duration v) { this.cleanupInterval = v; } + public int getMaxSessions() { return maxSessions; } + public void setMaxSessions(int v) { this.maxSessions = v; } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/ShellConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/ShellConfig.java new file mode 100644 index 000000000..e9b753c9d --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/ShellConfig.java @@ -0,0 +1,25 @@ +package com.yomahub.liteflow.property.agent; + +import java.time.Duration; +import java.util.Arrays; +import java.util.List; + +public class ShellConfig { + private ShellMode mode = ShellMode.WHITELIST; + private List whitelist = Arrays.asList( + "ls", "cat", "grep", "find", "head", "tail", "wc", "sed", "awk", "python3", "node"); + private List blacklist = Arrays.asList("rm", "sudo", "shutdown", "mkfs", "dd"); + private Duration timeout = Duration.ofSeconds(30); + private long maxOutputBytes = 1024L * 1024; + + public ShellMode getMode() { return mode; } + public void setMode(ShellMode v) { this.mode = v; } + public List getWhitelist() { return whitelist; } + public void setWhitelist(List v) { this.whitelist = v; } + public List getBlacklist() { return blacklist; } + public void setBlacklist(List v) { this.blacklist = v; } + public Duration getTimeout() { return timeout; } + public void setTimeout(Duration v) { this.timeout = v; } + public long getMaxOutputBytes() { return maxOutputBytes; } + public void setMaxOutputBytes(long v) { this.maxOutputBytes = v; } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/ShellMode.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/ShellMode.java new file mode 100644 index 000000000..7fab6e30f --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/ShellMode.java @@ -0,0 +1,7 @@ +package com.yomahub.liteflow.property.agent; + +public enum ShellMode { + WHITELIST, + BLACKLIST, + DISABLED +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/WorkspaceConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/WorkspaceConfig.java new file mode 100644 index 000000000..c8fac6ef1 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/WorkspaceConfig.java @@ -0,0 +1,23 @@ +package com.yomahub.liteflow.property.agent; + +public class WorkspaceConfig { + private String root; + private boolean autoCreate = true; + private boolean cleanupOnSessionExpire = true; + private boolean cleanupOnJvmShutdown = false; + private long maxFileBytes = 10L * 1024 * 1024; + private int maxListSize = 1000; + + public String getRoot() { return root; } + public void setRoot(String root) { this.root = root; } + public boolean isAutoCreate() { return autoCreate; } + public void setAutoCreate(boolean autoCreate) { this.autoCreate = autoCreate; } + public boolean isCleanupOnSessionExpire() { return cleanupOnSessionExpire; } + public void setCleanupOnSessionExpire(boolean v) { this.cleanupOnSessionExpire = v; } + public boolean isCleanupOnJvmShutdown() { return cleanupOnJvmShutdown; } + public void setCleanupOnJvmShutdown(boolean v) { this.cleanupOnJvmShutdown = v; } + public long getMaxFileBytes() { return maxFileBytes; } + public void setMaxFileBytes(long v) { this.maxFileBytes = v; } + public int getMaxListSize() { return maxListSize; } + public void setMaxListSize(int v) { this.maxListSize = v; } +} diff --git a/liteflow-core/src/test/java/com/yomahub/liteflow/property/agent/AgentConfigTest.java b/liteflow-core/src/test/java/com/yomahub/liteflow/property/agent/AgentConfigTest.java new file mode 100644 index 000000000..9429d4c7e --- /dev/null +++ b/liteflow-core/src/test/java/com/yomahub/liteflow/property/agent/AgentConfigTest.java @@ -0,0 +1,50 @@ +package com.yomahub.liteflow.property.agent; + +import org.junit.jupiter.api.Test; +import java.time.Duration; +import static org.junit.jupiter.api.Assertions.*; + +class AgentConfigTest { + + @Test + void defaults_are_sensible() { + AgentConfig c = new AgentConfig(); + assertNotNull(c.getWorkspace()); + assertNotNull(c.getSession()); + assertNotNull(c.getShell()); + assertNotNull(c.getDefaults()); + assertNotNull(c.getOpenaiCompatible()); + assertTrue(c.getOpenaiCompatible().isEmpty()); + + WorkspaceConfig w = c.getWorkspace(); + assertNull(w.getRoot()); + assertTrue(w.isAutoCreate()); + assertTrue(w.isCleanupOnSessionExpire()); + assertFalse(w.isCleanupOnJvmShutdown()); + assertEquals(10 * 1024 * 1024, w.getMaxFileBytes()); + assertEquals(1000, w.getMaxListSize()); + + SessionConfig s = c.getSession(); + assertEquals(Duration.ofMinutes(30), s.getIdleTimeout()); + assertEquals(Duration.ofMinutes(1), s.getCleanupInterval()); + assertEquals(10_000, s.getMaxSessions()); + + ShellConfig sh = c.getShell(); + assertEquals(ShellMode.WHITELIST, sh.getMode()); + assertNotNull(sh.getWhitelist()); + assertNotNull(sh.getBlacklist()); + assertEquals(Duration.ofSeconds(30), sh.getTimeout()); + assertEquals(1024 * 1024, sh.getMaxOutputBytes()); + + assertEquals(15, c.getDefaults().getMaxIterations()); + } + + @Test + void platform_credentials_are_independent_instances() { + AgentConfig c = new AgentConfig(); + c.getOpenai().setApiKey("k1"); + assertNull(c.getAnthropic().getApiKey()); + assertNull(c.getGemini().getApiKey()); + assertNull(c.getDashscope().getApiKey()); + } +}