langgraph_rb 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +9 -0
- data/README.md +350 -0
- data/SUMMARY.md +170 -0
- data/examples/advanced_example.rb +388 -0
- data/examples/basic_example.rb +211 -0
- data/examples/simple_test.rb +266 -0
- data/langgraph_rb.gemspec +43 -0
- data/lib/langgraph_rb/command.rb +132 -0
- data/lib/langgraph_rb/edge.rb +141 -0
- data/lib/langgraph_rb/graph.rb +268 -0
- data/lib/langgraph_rb/node.rb +112 -0
- data/lib/langgraph_rb/runner.rb +360 -0
- data/lib/langgraph_rb/state.rb +70 -0
- data/lib/langgraph_rb/stores/memory.rb +265 -0
- data/lib/langgraph_rb/version.rb +3 -0
- data/lib/langgraph_rb.rb +15 -0
- data/test_runner.rb +160 -0
- metadata +151 -0
data/test_runner.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative 'lib/langgraph_rb'
|
4
|
+
|
5
|
+
puts "🧪 LangGraphRB Test Runner"
|
6
|
+
puts "=" * 50
|
7
|
+
|
8
|
+
# Test 1: Basic State Management
|
9
|
+
puts "\n1️⃣ Testing State Management..."
|
10
|
+
|
11
|
+
state = LangGraphRB::State.new(
|
12
|
+
{ counter: 0, messages: [] },
|
13
|
+
{
|
14
|
+
counter: ->(old, new) { (old || 0) + new },
|
15
|
+
messages: LangGraphRB::State.add_messages
|
16
|
+
}
|
17
|
+
)
|
18
|
+
|
19
|
+
updated_state = state.merge_delta({
|
20
|
+
counter: 5,
|
21
|
+
messages: [{ role: 'user', content: 'Hello' }]
|
22
|
+
})
|
23
|
+
|
24
|
+
updated_state = updated_state.merge_delta({
|
25
|
+
counter: 3,
|
26
|
+
messages: [{ role: 'assistant', content: 'Hi there!' }]
|
27
|
+
})
|
28
|
+
|
29
|
+
puts "✅ Counter (should be 8): #{updated_state[:counter]}"
|
30
|
+
puts "✅ Messages count (should be 2): #{updated_state[:messages].length}"
|
31
|
+
|
32
|
+
# Test 2: Basic Graph Execution
|
33
|
+
puts "\n2️⃣ Testing Basic Graph Execution..."
|
34
|
+
|
35
|
+
graph = LangGraphRB::Graph.new do
|
36
|
+
node :double do |state|
|
37
|
+
{ result: (state[:number] || 0) * 2 }
|
38
|
+
end
|
39
|
+
|
40
|
+
node :add_ten do |state|
|
41
|
+
{ result: (state[:result] || 0) + 10 }
|
42
|
+
end
|
43
|
+
|
44
|
+
set_entry_point :double
|
45
|
+
edge :double, :add_ten
|
46
|
+
set_finish_point :add_ten
|
47
|
+
end
|
48
|
+
|
49
|
+
graph.compile!
|
50
|
+
result = graph.invoke({ number: 5 })
|
51
|
+
puts "✅ Result (should be 20): #{result[:result]}"
|
52
|
+
|
53
|
+
# Test 3: Conditional Routing
|
54
|
+
puts "\n3️⃣ Testing Conditional Routing..."
|
55
|
+
|
56
|
+
routing_graph = LangGraphRB::Graph.new do
|
57
|
+
node :check_number do |state|
|
58
|
+
num = state[:number] || 0
|
59
|
+
{
|
60
|
+
number: num,
|
61
|
+
is_positive: num > 0,
|
62
|
+
is_even: num % 2 == 0
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
node :positive_handler do |state|
|
67
|
+
{ message: "Number #{state[:number]} is positive!" }
|
68
|
+
end
|
69
|
+
|
70
|
+
node :negative_handler do |state|
|
71
|
+
{ message: "Number #{state[:number]} is negative or zero!" }
|
72
|
+
end
|
73
|
+
|
74
|
+
set_entry_point :check_number
|
75
|
+
|
76
|
+
conditional_edge :check_number, ->(state) {
|
77
|
+
state[:is_positive] ? :positive_handler : :negative_handler
|
78
|
+
}
|
79
|
+
|
80
|
+
set_finish_point :positive_handler
|
81
|
+
set_finish_point :negative_handler
|
82
|
+
end
|
83
|
+
|
84
|
+
routing_graph.compile!
|
85
|
+
|
86
|
+
pos_result = routing_graph.invoke({ number: 7 })
|
87
|
+
puts "✅ Positive test: #{pos_result[:message]}"
|
88
|
+
|
89
|
+
neg_result = routing_graph.invoke({ number: -3 })
|
90
|
+
puts "✅ Negative test: #{neg_result[:message]}"
|
91
|
+
|
92
|
+
# Test 4: Commands
|
93
|
+
puts "\n4️⃣ Testing Commands..."
|
94
|
+
|
95
|
+
command_graph = LangGraphRB::Graph.new do
|
96
|
+
node :decision_maker do |state|
|
97
|
+
if state[:should_skip]
|
98
|
+
LangGraphRB::Commands.update_and_goto(
|
99
|
+
{ message: "Skipped processing" },
|
100
|
+
LangGraphRB::Graph::FINISH
|
101
|
+
)
|
102
|
+
else
|
103
|
+
{ message: "Processing normally" }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
node :normal_processing do |state|
|
108
|
+
{ message: state[:message] + " -> completed" }
|
109
|
+
end
|
110
|
+
|
111
|
+
set_entry_point :decision_maker
|
112
|
+
edge :decision_maker, :normal_processing
|
113
|
+
set_finish_point :normal_processing
|
114
|
+
end
|
115
|
+
|
116
|
+
command_graph.compile!
|
117
|
+
|
118
|
+
skip_result = command_graph.invoke({ should_skip: true })
|
119
|
+
puts "✅ Skip result: #{skip_result[:message]}"
|
120
|
+
|
121
|
+
normal_result = command_graph.invoke({ should_skip: false })
|
122
|
+
puts "✅ Normal result: #{normal_result[:message]}"
|
123
|
+
|
124
|
+
# Test 5: Checkpointing
|
125
|
+
puts "\n5️⃣ Testing Checkpointing..."
|
126
|
+
|
127
|
+
store = LangGraphRB::Stores::InMemoryStore.new
|
128
|
+
thread_id = "test_thread_#{Time.now.to_i}"
|
129
|
+
|
130
|
+
checkpoint_graph = LangGraphRB::Graph.new do
|
131
|
+
node :step1 do |state|
|
132
|
+
{ step: 1, data: "Step 1 complete" }
|
133
|
+
end
|
134
|
+
|
135
|
+
node :step2 do |state|
|
136
|
+
{ step: 2, data: state[:data] + " -> Step 2 complete" }
|
137
|
+
end
|
138
|
+
|
139
|
+
set_entry_point :step1
|
140
|
+
edge :step1, :step2
|
141
|
+
set_finish_point :step2
|
142
|
+
end
|
143
|
+
|
144
|
+
checkpoint_graph.compile!
|
145
|
+
|
146
|
+
# Execute with checkpointing
|
147
|
+
result = checkpoint_graph.invoke(
|
148
|
+
{ input: "test" },
|
149
|
+
store: store,
|
150
|
+
thread_id: thread_id
|
151
|
+
)
|
152
|
+
|
153
|
+
puts "✅ Checkpointed execution result: #{result[:data]}"
|
154
|
+
|
155
|
+
# Verify checkpoints were saved
|
156
|
+
steps = store.list_steps(thread_id)
|
157
|
+
puts "✅ Checkpoints saved: #{steps.length} steps"
|
158
|
+
|
159
|
+
puts "\n🎉 All tests passed! LangGraphRB is working correctly."
|
160
|
+
puts "=" * 50
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: langgraph_rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Julian Toro
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-07-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '13.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '13.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.14'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.14'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.0'
|
97
|
+
description: "LangGraphRB is a Ruby library inspired by LangGraph for building stateful,
|
98
|
+
multi-actor applications \nusing directed graphs. It provides a framework for orchestrating
|
99
|
+
complex workflows with support for \nparallel execution, checkpointing, human-in-the-loop
|
100
|
+
interactions, and map-reduce operations.\n"
|
101
|
+
email:
|
102
|
+
- fulit103@gmail.com
|
103
|
+
executables: []
|
104
|
+
extensions: []
|
105
|
+
extra_rdoc_files: []
|
106
|
+
files:
|
107
|
+
- Gemfile
|
108
|
+
- README.md
|
109
|
+
- SUMMARY.md
|
110
|
+
- examples/advanced_example.rb
|
111
|
+
- examples/basic_example.rb
|
112
|
+
- examples/simple_test.rb
|
113
|
+
- langgraph_rb.gemspec
|
114
|
+
- lib/langgraph_rb.rb
|
115
|
+
- lib/langgraph_rb/command.rb
|
116
|
+
- lib/langgraph_rb/edge.rb
|
117
|
+
- lib/langgraph_rb/graph.rb
|
118
|
+
- lib/langgraph_rb/node.rb
|
119
|
+
- lib/langgraph_rb/runner.rb
|
120
|
+
- lib/langgraph_rb/state.rb
|
121
|
+
- lib/langgraph_rb/stores/memory.rb
|
122
|
+
- lib/langgraph_rb/version.rb
|
123
|
+
- test_runner.rb
|
124
|
+
homepage: https://github.com/fulit103/langgraph_rb
|
125
|
+
licenses:
|
126
|
+
- MIT
|
127
|
+
metadata:
|
128
|
+
homepage_uri: https://github.com/fulit103/langgraph_rb
|
129
|
+
source_code_uri: https://github.com/fulit103/langgraph_rb
|
130
|
+
changelog_uri: https://github.com/fulit103/langgraph_rb/blob/main/CHANGELOG.md
|
131
|
+
post_install_message:
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: 3.0.0
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
requirements: []
|
146
|
+
rubygems_version: 3.5.18
|
147
|
+
signing_key:
|
148
|
+
specification_version: 4
|
149
|
+
summary: A Ruby library for building stateful, multi-actor applications with directed
|
150
|
+
graphs
|
151
|
+
test_files: []
|