Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
0f8287f
Improved DummyTool and DummyChatModel with some enhancements and needs
stefanofornari Mar 3, 2026
0fbe48e
Added new Util tools classes with an echo tool
stefanofornari Mar 4, 2026
8e3a542
Updated all tools providing @P() description so that they will be pro…
stefanofornari Mar 4, 2026
7b18c28
- Added ToolNotFoundException
stefanofornari Mar 5, 2026
55d17b5
- Added ExecutionJSONObject.java and its test
stefanofornari Mar 5, 2026
d042a1e
- finally added the full HackerWithoutTool and integrated it in
stefanofornari Mar 8, 2026
15d7373
Merge branch 'main' into ste/us/276_Interactive_mode_for_models_that_…
stefanofornari Mar 9, 2026
1f1199a
Update pom.xml
jGauravGupta Mar 9, 2026
c257797
Update langchain4j version to 1.11.0
jGauravGupta Mar 9, 2026
3a71114
Merge branch 'main' into ste/us/276_Interactive_mode_for_models_that_…
stefanofornari Mar 11, 2026
0bbd6d0
Merged main
stefanofornari Mar 11, 2026
cbaf5f5
Merge branch 'ste/us/276_Interactive_mode_for_models_that_do_not_supp…
stefanofornari Mar 11, 2026
943e8d5
Fixed issue with paths on windowns
stefanofornari Mar 12, 2026
3d9a346
Fixed issue with paths on windowns
stefanofornari Mar 12, 2026
4e6aec4
Removed wrong DummyChatModel and fixed the new version
stefanofornari Mar 12, 2026
71a7285
Fixed issue with paths on windowns
stefanofornari Mar 13, 2026
f88861e
Merge branch 'main' into ste/us/276_Interactive_mode_for_models_that_…
stefanofornari Mar 13, 2026
9775491
Fixed issue with paths on windowns...
stefanofornari Mar 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 38 additions & 13 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>17</maven.compiler.release>
<javalang4j.version>1.10.0</javalang4j.version>
<langchain4j.version>1.11.0</langchain4j.version>
<netbeans.version>RELEASE290</netbeans.version>
</properties>

Expand Down Expand Up @@ -267,48 +267,48 @@
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${javalang4j.version}</version>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama</artifactId>
<version>${javalang4j.version}</version>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-local-ai</artifactId>
<version>${javalang4j.version}-beta18</version>
<version>${langchain4j.version}-beta19</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-mistral-ai</artifactId>
<version>${javalang4j.version}</version>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-anthropic</artifactId>
<version>${javalang4j.version}</version>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-google-ai-gemini</artifactId>
<version>${javalang4j.version}</version>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-agentic</artifactId>
<version>${javalang4j.version}-beta18</version>
<version>${langchain4j.version}-beta19</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${javalang4j.version}</version>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-http-client-jdk</artifactId>
<version>${javalang4j.version}</version>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>com.knuddels</groupId>
Expand All @@ -318,13 +318,38 @@
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.27.0</version>
<version>0.27.1</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20240303</version>
<version>20251224</version>
</dependency>
<dependency>
<!--
TOON
-->
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>tools.jackson.module</groupId>
<artifactId>jackson-module-afterburner</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.21</version>
</dependency>

<dependency>
<groupId>dev.toonformat</groupId>
<artifactId>jtoon</artifactId>
<version>1.0.8</version>
</dependency>
<!-- -->
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
Expand Down Expand Up @@ -671,7 +696,7 @@
<dependency>
<groupId>com.github.stefanofornari</groupId>
<artifactId>lambda-loop</artifactId>
<version>0.5.0</version>
<version>0.6.1</version>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
Expand Down
21 changes: 17 additions & 4 deletions src/main/java/io/github/jeddict/ai/agent/EditorTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.github.jeddict.ai.agent;

import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import java.io.IOException;
import java.util.regex.Pattern;
Expand All @@ -39,8 +40,14 @@ public EditorTools(final String basedir) throws IOException {
* @return a status message
*/
@Tool("Insert a line of code at a given line number (0-based) in a file by path")
public String insertLineInFile(String path, int lineNumber, String lineText)
throws Exception {
public String insertLineInFile(
@P("the file path relative to the project")
final String path,
@P("the line number (0-based) where to insert the text")
final int lineNumber,
@P("the line to insert")
final String lineText
) throws Exception {
progress("✏️ Inserting line at " + lineNumber + " in file: " + path);

return withDocument(path, doc -> {
Expand Down Expand Up @@ -77,8 +84,14 @@ public String insertLineInFile(String path, int lineNumber, String lineText)
* @return status message
*/
@Tool("Insert a line of code at a given line number (0-based) in a file by path")
public String insertLineAfterMethod(String path, String methodName, String lineText)
throws Exception {
public String insertLineAfterMethod(
@P("the file path relative to the project")
final String path,
@P("the method or constructor name where to insert after")
final String methodName,
@P("the text to insert as a new line")
final String lineText
) throws Exception {
progress("✏️ Inserting line after method '" + methodName + "' in file: " + path);
String content = withDocument(path, doc -> doc.getText(0, doc.getLength()), false);
if (content.startsWith("Could not")) {
Expand Down
80 changes: 80 additions & 0 deletions src/main/java/io/github/jeddict/ai/agent/ExecutionJSONObject.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Copyright 2026 the original author or authors from the Jeddict project (https://jeddict.github.io/).
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package io.github.jeddict.ai.agent;

import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import static ste.lloop.Loop.on;

/**
* Object to represent a tool execution. It basically consists of
* a name and a list of arguments. Each argument can be a string or an array
* of strings (for now, more types may be supported in the future).
* If an error arises while converting the arguments to JSON, it falls back
* to an execution of the tool "echo" with a proper error message.
*/
public class ExecutionJSONObject {

public String name;
public JSONObject arguments;

public ExecutionJSONObject(final String name) {
this(name, "");
}

public ExecutionJSONObject(final String name, final String content) {
try {
this.name = name;
this.arguments = new JSONObject("{" + content + "}");
} catch (final Throwable t) {
this.name = "echo";
this.arguments = new JSONObject();
arguments.put(
"message",
"ERR error parsing tool execution for %s, make sure it is in well formed JSON:\n%s"
.formatted(name, content)
);
}
}

public String name() {
return name;
}

public Object[] arguments() {
final List values = new ArrayList();
on(arguments.keys()).loop((key) -> {
values.add(arguments.get(key));
});
return values.toArray();
}

public Object[] arguments(String... args) {
final Object[] values = new Object[args.length];
on(args).loop((i, arg) -> {
values[i] = arguments.opt(arg);
if (values[i] instanceof JSONArray jarray) {
values[i] = jarray.toList();
} else if (values[i] == JSONObject.NULL) {
values[i] = null;
}
});
return values;
}
}
37 changes: 25 additions & 12 deletions src/main/java/io/github/jeddict/ai/agent/ExplorationTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package io.github.jeddict.ai.agent;

import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -94,7 +95,7 @@ private static boolean isJavaFile(String path) {
* listClassesInFile("src/main/java/com/example/MyClass.java");
* // -> "Class: com.example.MyClass"
* </pre>
*
*
* <p><b>Output format:</b></p>
* <pre>
* Class: fully.qualified.ClassName
Expand All @@ -110,7 +111,10 @@ private static boolean isJavaFile(String path) {
*/
@Tool("JAVA ONLY: List all classes declared in a given Java file by path")
@ToolPolicy(READONLY)
public String listClassesInFile(String path) throws Exception {
public String listClassesInFile(
@P("the file path relative to the project")
final String path
) throws Exception {

if (!isJavaFile(path)) {
return "Not a Java source file: " + path;
Expand Down Expand Up @@ -143,7 +147,7 @@ public String listClassesInFile(String path) throws Exception {
* listMethodsInFile("src/main/java/com/example/MyClass.java");
* // -> "Method: public void sayHello()"
* </pre>
*
*
* <p><b>Output format:</b></p>
* <pre>
* Method: methodSignature
Expand All @@ -159,7 +163,10 @@ public String listClassesInFile(String path) throws Exception {
*/
@Tool("JAVA ONLY: List all methods of a class in a given Java file by path")
@ToolPolicy(READONLY)
public String listMethodsInFile(String path) throws Exception {
public String listMethodsInFile(
@P("the file path relative to the project")
final String path
) throws Exception {

if (!isJavaFile(path)) {
return "Not a Java source file: " + path;
Expand Down Expand Up @@ -206,7 +213,7 @@ public String listMethodsInFile(String path) throws Exception {
* </ul>
* </li>
* </ol>
*
*
* <p>
* The search is performed using the symbol's <b>simple name</b> only. Fully
* qualified names are not required and are not matched directly.</p>
Expand All @@ -220,15 +227,15 @@ public String listMethodsInFile(String path) throws Exception {
* <li>Overloaded methods are returned by name only, without signature
* differentiation.</li>
* </ul>
*
*
* <p>
* <b>Examples:</b></p>
* <pre>
* searchSymbol("UserService"); // Class: com.example.service.UserService
* searchSymbol("findUser"); // Method: com.example.service.UserService.findUser
* searchSymbol("userRepository");// Field: com.example.service.UserService.userRepository
* </pre>
*
*
* <p><b>Output format:</b></p>
* <pre>
* Class: fully.qualified.ClassName
Expand All @@ -254,8 +261,10 @@ public String listMethodsInFile(String path) throws Exception {
"If no symbol is found, returns 'No matches found.'. " +
"If the project has no Java sources, returns an explanatory message.")
@ToolPolicy(READONLY)
public String searchSymbol(String symbolName)
throws Exception {
public String searchSymbol(
@P("simple name of the Java class, method, or field to search for")
final String symbolName
) throws Exception {
progress("Searching symbol " + symbolName);

Sources sources = lookup.lookup(Sources.class);
Expand Down Expand Up @@ -353,7 +362,7 @@ public String searchSymbol(String symbolName)
* NetBeans {@code WhereUsedQuery}.
* If no usages are found, {@code "No usages found."} is returned.
* </p>
*
*
* @param path relative path to a .java file
* @param symbolName Java symbol name
* @return formatted usage list
Expand All @@ -365,8 +374,12 @@ public String searchSymbol(String symbolName)
+ "If no usages are found, returns 'No usages found.'."
)
@ToolPolicy(READONLY)
public String findUsages(String path, String symbolName)
throws Exception {
public String findUsages(
@P("path relative path to a .java file")
final String path,
@P("symbolName Java symbol name")
final String symbolName
) throws Exception {
if (!isJavaFile(path)) {
return "Not a Java source file: " + path;
}
Expand Down
Loading
Loading