diff --git a/pom.xml b/pom.xml index aac9ed3..7839199 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ 2.16.2 2.2 1.4.0 - 1.18.32 + 1.18.42 2.0.12 1.4.14 3.1.8 diff --git a/src/main/java/io/leavesfly/jimi/agent/AgentSpecLoader.java b/src/main/java/io/leavesfly/jimi/agent/AgentSpecLoader.java index 3e5f06d..bd124fb 100644 --- a/src/main/java/io/leavesfly/jimi/agent/AgentSpecLoader.java +++ b/src/main/java/io/leavesfly/jimi/agent/AgentSpecLoader.java @@ -1,8 +1,8 @@ package io.leavesfly.jimi.agent; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.leavesfly.jimi.exception.AgentSpecException; +import io.leavesfly.jimi.util.ResourceUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -15,7 +15,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -281,11 +280,13 @@ private AgentSpec parseAgentSpecFromResource(Map data, String ag // 处理系统提示词路径 - 使用虚拟路径标识资源 if (data.containsKey("system_prompt")) { String promptFile = (String) data.get("system_prompt"); - Path virtualPath = Paths.get("classpath:agents/" + agentName + "/" + promptFile); + // Path virtualPath = Paths.get("classpath:agents/" + agentName + "/" + promptFile); + Path virtualPath = ResourceUtils.resolveFromClasspath("agents/" + agentName + "/" + promptFile); builder.systemPromptPath(virtualPath); } else if (data.containsKey("system_prompt_path")) { String promptFile = (String) data.get("system_prompt_path"); - Path virtualPath = Paths.get("classpath:agents/" + agentName + "/" + promptFile); + // Path virtualPath = Paths.get("classpath:agents/" + agentName + "/" + promptFile); + Path virtualPath = ResourceUtils.resolveFromClasspath("agents/" + agentName + "/" + promptFile); builder.systemPromptPath(virtualPath); } @@ -316,7 +317,8 @@ private AgentSpec parseAgentSpecFromResource(Map data, String ag for (Map.Entry> entry : subagentsData.entrySet()) { String subagentPath = (String) entry.getValue().get("path"); // 构造 classpath 虚拟路径 - Path resolvedPath = Paths.get("classpath:agents/" + subagentPath); + // Path resolvedPath = Paths.get("classpath:agents/" + subagentPath); + Path resolvedPath = ResourceUtils.resolveFromClasspath("agents/" + subagentPath); SubagentSpec subagent = SubagentSpec.builder() .path(resolvedPath) @@ -382,7 +384,10 @@ private AgentSpec parseAgentSpec(Map data, Path agentFile) { for (Map.Entry> entry : subagentsData.entrySet()) { String subagentPath = (String) entry.getValue().get("path"); // 将相对路径转换为绝对路径 - Path resolvedPath = agentsRootDir.resolve(subagentPath); + Path resolvedPath = agentsRootDir == null ? + Path.of(subagentPath) + : + agentsRootDir.resolve(subagentPath); SubagentSpec subagent = SubagentSpec.builder() .path(resolvedPath) @@ -410,7 +415,7 @@ public Path getDefaultAgentPath() { URL resource = getClass().getClassLoader().getResource(resourcePath); if (resource != null) { log.debug("Found default agent in classpath: {}", resourcePath); - return Paths.get("classpath:" + resourcePath); + return ResourceUtils.resolveFromClasspath(resourcePath); } throw new AgentSpecException("Default agent not found in classpath: " + resourcePath); } diff --git a/src/main/java/io/leavesfly/jimi/skill/SkillLoader.java b/src/main/java/io/leavesfly/jimi/skill/SkillLoader.java index 0276567..aa0e2a9 100644 --- a/src/main/java/io/leavesfly/jimi/skill/SkillLoader.java +++ b/src/main/java/io/leavesfly/jimi/skill/SkillLoader.java @@ -1,6 +1,7 @@ package io.leavesfly.jimi.skill; import com.fasterxml.jackson.databind.ObjectMapper; +import io.leavesfly.jimi.util.ResourceUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -17,10 +18,6 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.Enumeration; /** * Skill加载器 @@ -130,7 +127,7 @@ public List loadSkillsFromClasspath(SkillScope scope) { if (skill != null) { skill.setScope(scope); // 使用虚拟路径标识 - skill.setSkillFilePath(Paths.get("classpath:" + resourcePath)); + skill.setSkillFilePath(ResourceUtils.resolveFromClasspath(resourcePath)); skills.add(skill); log.debug("Loaded skill from classpath: {} ({})", skill.getName(), resourcePath); diff --git a/src/main/java/io/leavesfly/jimi/tool/file/WriteFile.java b/src/main/java/io/leavesfly/jimi/tool/file/WriteFile.java index e02653f..c8c37cd 100644 --- a/src/main/java/io/leavesfly/jimi/tool/file/WriteFile.java +++ b/src/main/java/io/leavesfly/jimi/tool/file/WriteFile.java @@ -144,8 +144,11 @@ public Mono execute(Params params) { try { // 处理转义序列(将字面量 \n、\t、\r 转换为真正的控制字符) - String processedContent = unescapeContent(params.content); - + // String processedContent = unescapeContent(params.content); + + // 转义的逻辑感觉不对,特别是在代码场景下不需要转义,否则会造成代码有问题 + String processedContent = params.content; + // 写入文件 if ("overwrite".equals(params.mode)) { Files.writeString(targetPath, processedContent); diff --git a/src/main/java/io/leavesfly/jimi/util/ResourceUtils.java b/src/main/java/io/leavesfly/jimi/util/ResourceUtils.java new file mode 100644 index 0000000..1394a3c --- /dev/null +++ b/src/main/java/io/leavesfly/jimi/util/ResourceUtils.java @@ -0,0 +1,22 @@ +package io.leavesfly.jimi.util; + +import io.leavesfly.jimi.exception.AgentSpecException; + +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class ResourceUtils { + public static Path resolveFromClasspath(String resourcePath) { + URL resource = ResourceUtils.class.getClassLoader().getResource(resourcePath); + try { + if (resource != null) { + return Paths.get(resource.toURI()); + } + } catch (URISyntaxException e) { + throw new RuntimeException("Resource resolve failed: " + resourcePath, e); + } + throw new RuntimeException("Resource not found: " + resourcePath); + } +} diff --git a/src/main/resources/.jimi/template-config.json b/src/main/resources/.jimi/template-config.json index 47fc260..d37bd9a 100644 --- a/src/main/resources/.jimi/template-config.json +++ b/src/main/resources/.jimi/template-config.json @@ -12,6 +12,16 @@ "sleep_ms": 3000 } }, + "kimi": { + "type": "kimi", + "base_url": "https://api.moonshot.cn/v1", + "api_key": "YOUR_API_KEY_HERE", + "rate_limit": { + "window_ms": 4000, + "max_requests": 4, + "sleep_ms": 3000 + } + }, "ollama": { "type": "ollama", "base_url": "http://localhost:11434/v1", @@ -69,6 +79,21 @@ "provider": "ollama", "model": "qwen3:4b-thinking-2507-q8_0", "max_context_size": 100000 + }, + "kimi-k2-turbo-preview": { + "provider": "kimi", + "model": "kimi-k2-turbo-preview", + "max_context_size": 200000 + }, + "kimi-k2-thinking": { + "provider": "kimi", + "model": "kimi-k2-thinking", + "max_context_size": 200000 + }, + "kimi-k2-thinking-turbo": { + "provider": "kimi", + "model": "kimi-k2-thinking-turbo", + "max_context_size": 200000 } }, "loop_control": { @@ -98,7 +123,9 @@ "storage_path": ".jimi/code_graph", "auto_load": true, "auto_save": true, - "include_patterns": ["**/*.java"], + "include_patterns": [ + "**/*.java" + ], "exclude_patterns": [ "**/test/**", "**/tests/**",