Skip to content

Commit 9c53762

Browse files
committed
Merge branch 'release/1.2.5'
2 parents 0c0e931 + 2d2b807 commit 9c53762

File tree

16 files changed

+330
-102
lines changed

16 files changed

+330
-102
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ LangGraph for Java. A library for building stateful, multi-agents applications w
1919
- [x] Reducer (_how apply updates to the state attributes_)
2020
- [x] Default provider
2121
- [x] AppenderChannel (_values accumulator_)
22+
- [x] delete messages
2223
- [x] Compiling graph
2324
- [x] Async support (_throught [CompletableFuture]_)
2425
- [x] Streaming support (_throught [java-async-generator]_)
@@ -43,7 +44,7 @@ LangGraph for Java. A library for building stateful, multi-agents applications w
4344
4445
| Date | Release | info
4546
|--------------|----------------| ---
46-
| Jan 22, 2025 | `1.2.4` | official release
47+
| Jan 23, 2025 | `1.2.4` | official release
4748

4849

4950
## Samples

agent-executor/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<parent>
55
<groupId>org.bsc.langgraph4j</groupId>
66
<artifactId>langgraph4j-parent</artifactId>
7-
<version>1.2.4</version>
7+
<version>1.2.5</version>
88
<relativePath>..</relativePath>
99
</parent>
1010

core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.bsc.langgraph4j</groupId>
77
<artifactId>langgraph4j-parent</artifactId>
8-
<version>1.2.4</version>
8+
<version>1.2.5</version>
99
</parent>
1010

1111
<artifactId>langgraph4j-core</artifactId>

core/src/main/java/org/bsc/langgraph4j/state/AppenderChannel.java

Lines changed: 106 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

33
import lombok.extern.slf4j.Slf4j;
44

5-
import java.lang.reflect.Array;
65
import java.util.*;
76
import java.util.function.Supplier;
87

8+
import static java.util.Collections.unmodifiableList;
99
import static java.util.Optional.ofNullable;
10-
import static org.bsc.langgraph4j.utils.CollectionsUtils.listOf;
1110

1211

1312
/**
@@ -20,6 +19,24 @@
2019
@Slf4j
2120
public class AppenderChannel<T> implements Channel<List<T>> {
2221

22+
/**
23+
* A functional interface that is used to remove elements from a list.
24+
*
25+
* @param <T> the type of elements in the list
26+
*/
27+
@FunctionalInterface
28+
public interface RemoveIdentifier<T> {
29+
/**
30+
* Compares the specified element with the element at the given index.
31+
*
32+
* @param <T> the type of elements to compare
33+
* @param element the element to be compared
34+
* @param atIndex the index of the element to compare with
35+
* @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
36+
*/
37+
int compareTo(T element, int atIndex );
38+
}
39+
2340
private final Reducer<List<T>> reducer;
2441
private final Supplier<List<T>> defaultProvider;
2542

@@ -58,16 +75,14 @@ public static <T> AppenderChannel<T> of( Supplier<List<T>> defaultProvider ) {
5875
/**
5976
* Constructs a new instance of {@code AppenderChannel} with the specified default provider.
6077
*
61-
* @param <T> the type of elements in the lists to be processed
6278
* @param defaultProvider a supplier for the default list that will be used when no other list is available
6379
*/
64-
private AppenderChannel( Supplier<List<T>> defaultProvider) {
65-
this.reducer = new Reducer<List<T>>() {
80+
private AppenderChannel( Supplier<List<T>> defaultProvider ) {
81+
this.reducer = new Reducer<>() {
6682
/**
6783
* Combines two lists into one. If the first list is null, the second list is returned.
6884
* Otherwise, the second list is added to the end of the first list and the resulting list is returned.
6985
*
70-
* @param <T> the type of elements in the lists
7186
* @param left the first list; may be null
7287
* @param right the second list
7388
* @return a new list containing all elements from both input lists
@@ -84,6 +99,77 @@ public List<T> apply(List<T> left, List<T> right) {
8499
this.defaultProvider = defaultProvider;
85100
}
86101

102+
/**
103+
* This method removes elements from a given list based on the specified {@link RemoveIdentifier}.
104+
* It creates a copy of the original list, performs the removal operation, and returns an immutable view of the result.
105+
*
106+
* @param <T> The type of elements in the list.
107+
* @param list The list from which elements will be removed.
108+
* @param removeIdentifier An instance of {@link RemoveIdentifier} that defines how to identify elements for removal.
109+
* @return An unmodifiable view of the modified list with specified elements removed.
110+
*/
111+
private List<T> remove(List<T> list, RemoveIdentifier<T> removeIdentifier ) {
112+
var result = new ArrayList<>(list);
113+
removeFromList(result, removeIdentifier);
114+
return unmodifiableList(result);
115+
}
116+
117+
/**
118+
* Removes an element from the list that matches the specified identifier.
119+
*
120+
* <p>This method iterates over the provided list and removes the first element for which the
121+
* {@link RemoveIdentifier#compareTo} method returns zero.</p>
122+
*
123+
* @param result the list to be modified
124+
* @param removeIdentifier the identifier used to find the element to remove
125+
*/
126+
private void removeFromList(List<T> result, RemoveIdentifier<T> removeIdentifier ) {
127+
for( int i = 0; i < result.size(); i++ ) {
128+
if( removeIdentifier.compareTo( result.get(i), i ) == 0 ) {
129+
result.remove(i);
130+
break;
131+
}
132+
}
133+
}
134+
135+
/**
136+
* Represents a record for data removal operations with generic types.
137+
*
138+
* @param <T> the type of elements in the old values list
139+
*/
140+
record RemoveData<T>( List<T> oldValues, List<?> newValues) {
141+
142+
// copy constructor. make sure to copy the list to make them modifiable
143+
public RemoveData {
144+
oldValues = new ArrayList<>(oldValues);
145+
newValues = new ArrayList<>(newValues);
146+
}
147+
};
148+
149+
/**
150+
* Evaluates the removal of identifiers from the new values list and updates the RemoveData object accordingly.
151+
*
152+
* @param oldValues a {@code List} of old values
153+
* @param newValues a {@code List} of new values containing {@code RemoveIdentifier}s to be evaluated for removal
154+
* @return a {@literal RemoveData<T>} object with updated old and new values after removing identifiers
155+
*/
156+
@SuppressWarnings("unchecked")
157+
private RemoveData<T> evaluateRemoval(List<T> oldValues, List<?> newValues ) {
158+
159+
final var result = new RemoveData<>( oldValues, newValues );
160+
161+
newValues.stream()
162+
.filter( value -> value instanceof RemoveIdentifier<?> )
163+
.forEach( value -> {
164+
result.newValues().remove( value );
165+
var removeIdentifier = (RemoveIdentifier<T>) value;
166+
removeFromList( result.oldValues(), removeIdentifier );
167+
168+
});
169+
return result;
170+
171+
}
172+
87173
/**
88174
* Updates the value for a given key in the channel.
89175
*
@@ -95,28 +181,39 @@ public List<T> apply(List<T> left, List<T> right) {
95181
*
96182
* @throws UnsupportedOperationException If the channel does not support updates, typically due to an immutable list being used.
97183
*/
184+
@SuppressWarnings("unchecked")
98185
public Object update( String key, Object oldValue, Object newValue) {
99186

100187
if( newValue == null ) {
101188
return oldValue;
102189
}
190+
191+
boolean oldValueIsList = oldValue instanceof List<?>;
192+
103193
try {
194+
if( oldValueIsList && newValue instanceof RemoveIdentifier<?> ) {
195+
return remove( (List<T>)oldValue, (RemoveIdentifier<T>)newValue);
196+
}
104197
List<?> list = null;
105198
if (newValue instanceof List) {
106-
list = (List<?>) newValue;
199+
list = (List<Object>) newValue;
107200
} else if (newValue.getClass().isArray()) {
108-
list = Arrays.asList((Object[]) newValue);
201+
list = Arrays.asList((T[])newValue);
109202
}
110203
if (list != null) {
111204
if (list.isEmpty()) {
112205
return oldValue;
113206
}
207+
if( oldValueIsList ) {
208+
var result = evaluateRemoval( (List<T>)oldValue, list );
209+
return Channel.super.update(key, result.oldValues(), result.newValues());
210+
}
114211
return Channel.super.update(key, oldValue, list);
115212
}
116213
// this is to allow single value other than List or Array
117214
try {
118215
T typedValue = (T)newValue;
119-
return Channel.super.update(key, oldValue, listOf(typedValue));
216+
return Channel.super.update(key, oldValue, List.of(typedValue));
120217
} catch (ClassCastException e) {
121218
log.error("Unsupported content type: {}", newValue.getClass());
122219
throw e;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.bsc.langgraph4j.state;
2+
3+
import java.util.Objects;
4+
5+
/**
6+
* Represents a record that implements the {@link AppenderChannel.RemoveIdentifier<T>} interface.
7+
*
8+
* @param <T> the type of the value to be associated with this RemoveByHash instance
9+
*/
10+
public record RemoveByHash<T>(T value ) implements AppenderChannel.RemoveIdentifier<T> {
11+
/**
12+
* Compares the hash code of this object with another element at a specific index.
13+
*
14+
* @param <T> the type parameter of the element to compare with
15+
* @param element the element to compare with
16+
* @param atIndex the index of the element in the context (ignored in comparison)
17+
* @return the difference between the hash codes of this object and the given element
18+
*/
19+
@Override
20+
public int compareTo(T element, int atIndex) {
21+
return Objects.hashCode(value) - Objects.hashCode(element);
22+
}
23+
24+
/**
25+
* Creates a new {@code RemoveByHash} instance with the specified value.
26+
*
27+
* @param <T> the type of the value
28+
* @param value the value to store in the {@code RemoveByHash}
29+
* @return a new {@code RemoveByHash} instance
30+
*/
31+
public static <T> RemoveByHash<T> of ( T value ) {
32+
return new RemoveByHash<>(value);
33+
}
34+
}

0 commit comments

Comments
 (0)