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/**",