agent_c 2.71828 → 2.718281

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8321a1602d20f566b59365d641fecb934340b043d6544e43b01b2951e947282b
4
- data.tar.gz: bf3cd0d58944294f4e83e080ac7aebfff8677798c96426411e559c8f7e7f6a7d
3
+ metadata.gz: 84e8303cd68cc23d402d7c1e30928afd098d096adab7a82d278f49461935f409
4
+ data.tar.gz: dd379a4df652263f1f0af5ad5253f5d89900c0c8a3f205fb86caabaebab60b6c
5
5
  SHA512:
6
- metadata.gz: 5dbe7a3d1ca921db961a5a3685c01f4e539b0358506cb45f9d6a04c462cb0657efa45eff16eea4f65c00bdb6f113b40551b38e71f5d61ceadf8463cec1ea9007
7
- data.tar.gz: 4b407bc2cf7086536bce703b209552b8753c6b3eef37b096437728095945d247a5b6643113487ad739339e407b6e4c43c6b0cdd72aeca3f75551ab9e1ac763e0
6
+ metadata.gz: bd35cf2044c68580cf7b4acd2b054bbe0b30d72567af28ecda93e91a95dd57171229bab3861a29d6df2fc9ea3359d493fd1d55553d128e3b2a396d0dc722545a
7
+ data.tar.gz: '059f59eb9e1e859d95fe345a58a57e4da4ed1d02dd6b433e4c89c5e53b09e0f794b3e07c19157c61c3bcde6f7c6e33796c36e592a644b38be8a708d1134a6681'
@@ -2,6 +2,11 @@
2
2
 
3
3
  This document contains useful patterns and techniques for working with AgentC pipelines.
4
4
 
5
+ ## Index
6
+
7
+ - [Custom I18n Attributes](#custom-i18n-attributes)
8
+ - [Rewinding to Previous Steps](#rewinding-to-previous-steps)
9
+
5
10
  ## Custom I18n Attributes
6
11
 
7
12
  By default, when using i18n interpolation in your prompts, AgentC will use `record.attributes` to provide values for interpolation. However, you can customize this behavior by implementing an `i18n_attributes` method on your record.
@@ -69,3 +74,128 @@ agent_step(:my_step)
69
74
  ### Return Value
70
75
 
71
76
  The `i18n_attributes` method should return a Hash with symbol or string keys. These keys will be used for interpolation in your i18n strings.
77
+
78
+ ## Rewinding to Previous Steps
79
+
80
+ The `rewind_to!` method allows you to restart execution from a previously completed step. This is useful when you need to retry or re-execute steps based on runtime conditions.
81
+
82
+ ### Use Case
83
+
84
+ This is useful when:
85
+ - An agent determines that a previous step needs to be re-executed
86
+ - You want to implement retry logic based on validation results
87
+ - You need to loop through steps until certain conditions are met
88
+ - A later step discovers that earlier work needs to be redone
89
+
90
+ ### Basic Usage
91
+
92
+ ```ruby
93
+ class Store < AgentC::Store
94
+ record(:refactor) do
95
+ schema do
96
+ t.boolean(
97
+ :review_passed,
98
+ default: false
99
+ )
100
+
101
+ t.string(
102
+ :review_feedback,
103
+ default: "none"
104
+ )
105
+ end
106
+ end
107
+ end
108
+
109
+ class MyPipeline < AgentC::Pipeline
110
+ # prompt:
111
+ # Perform the refactor.
112
+ # Here is feedback from the reviewer (if any):
113
+ # %{review_feedback}
114
+ agent_step(:perform_refactor)
115
+
116
+ # capture the diff
117
+ step(:capture_diff) do
118
+ record.update!(diff: git.diff)
119
+ end
120
+
121
+ # prompt:
122
+ # Review this diff: %{diff}
123
+ # schema:
124
+ # review_passed:
125
+ # type: boolean
126
+ # review_feedback:
127
+ # type: string
128
+ agent_step(:review_refactor)
129
+
130
+ step(:verify_output) do
131
+ # if the review hasn't passed,
132
+ # then review_feedback is now
133
+ # present and will be passed
134
+ # back in to refactor step above
135
+ unless record.review_passed
136
+ rewind_to!(:perform_refactor)
137
+ end
138
+ end
139
+ end
140
+ ```
141
+
142
+ ### How It Works
143
+
144
+ When you call `rewind_to!(step_name)`, the pipeline:
145
+ 1. Validates that the specified step has already been completed
146
+ 2. Validates that the step name appears only once in `completed_steps`
147
+ 3. Removes the specified step and all subsequent steps from `completed_steps`
148
+ 4. Continues execution from the rewound step
149
+
150
+ ### Important Notes
151
+
152
+ **Infinite loops**: There's no automatic infinite loop detection. Use your record's state to count rewinds if you are concerned about a potential infinite loop.
153
+
154
+ **Must be called from within a step**: The `rewind_to!` method must be invoked from within a pipeline step during execution.
155
+
156
+ **Step must be completed**: You can only rewind to steps that have already been completed in the current pipeline run. Attempting to rewind to a step that hasn't been completed will raise an `ArgumentError`.
157
+
158
+ **Step must be unique**: If a step name appears multiple times in `completed_steps`, attempting to rewind to it will raise an `ArgumentError`. This prevents ambiguous rewind operations.
159
+
160
+ **State considerations**: When rewinding, be aware that any side effects from the original execution of the rewound steps will remain unless explicitly cleaned up. The pipeline doesn't automatically rollback database changes or other state modifications.
161
+
162
+ ### Example: Retry Logic
163
+
164
+ ```ruby
165
+ class ProcessWithRetry < AgentC::Pipeline
166
+ step(:attempt_processing) do
167
+ result = process_with_agent
168
+ record.update!(
169
+ attempt_count: record.attempt_count + 1,
170
+ last_result: result
171
+ )
172
+ end
173
+
174
+ step(:check_result) do
175
+ if record.last_result.failed? && record.attempt_count < 3
176
+ # Retry by going back to the processing step
177
+ rewind_to!(:attempt_processing)
178
+ elsif record.last_result.failed?
179
+ task.fail!("Failed after 3 attempts")
180
+ else
181
+ record.update!(status: "completed")
182
+ end
183
+ end
184
+ end
185
+ ```
186
+
187
+ ### Error Handling
188
+
189
+ If you try to rewind to a step that hasn't been completed yet:
190
+
191
+ ```ruby
192
+ step(:early_step) do
193
+ rewind_to!(:later_step) # ArgumentError: Cannot rewind to a step that's not been completed yet
194
+ end
195
+ ```
196
+
197
+ If a step name appears multiple times in `completed_steps`:
198
+
199
+ ```ruby
200
+ # This will raise an ArgumentError about non-distinct step names
201
+ rewind_to!(:duplicate_step)
@@ -123,18 +123,17 @@ module AgentC
123
123
 
124
124
  log("start")
125
125
 
126
- self.class.steps.each do |step|
126
+ while(task.pending?)
127
127
  break if task.failed?
128
128
 
129
+ step = self.class.steps.find { !task.completed_steps.include?(_1.name.to_s) }
130
+ break if step.nil?
131
+
132
+ @rewind_to = nil
129
133
 
130
134
  store.transaction do
131
135
  log_prefix = "step: '#{step.name}'"
132
136
 
133
- if task.completed_steps.include?(step.name.to_s)
134
- log("#{log_prefix} already completed, skipping")
135
- next
136
- end
137
-
138
137
  log("#{log_prefix} start")
139
138
 
140
139
  instance_exec(&step.block)
@@ -142,6 +141,31 @@ module AgentC
142
141
  if task.failed?
143
142
  log("#{log_prefix} failed, executing on_failures")
144
143
  self.class.on_failures.each { instance_exec(&_1)}
144
+ elsif @rewind_to
145
+ matching_steps = task.completed_steps.select { _1 == @rewind_to }
146
+
147
+ if matching_steps.count == 0
148
+ raise ArgumentError, <<~TXT
149
+ Cannot rewind to a step that's not been completed yet:
150
+
151
+ rewind_to!(#{@rewind_to.inspect})
152
+ completed_steps: #{task.completed_steps.inspect}
153
+ TXT
154
+ elsif matching_steps.count > 1
155
+ raise ArgumentError, <<~TXT
156
+ Cannot rewind to a step with a non-distinct name. The step
157
+ name appears multiple times:
158
+
159
+ rewind_to!(#{@rewind_to.inspect})
160
+ completed_steps: #{task.completed_steps.inspect}
161
+ TXT
162
+ end
163
+
164
+ log("#{log_prefix} rewind_to! #{@rewind_to.inspect}")
165
+ task
166
+ .completed_steps
167
+ .index(@rewind_to)
168
+ .then { task.update!(completed_steps: task.completed_steps[0..._1]) }
145
169
  else
146
170
  log("#{log_prefix} done")
147
171
  task.completed_steps << step.name.to_s
@@ -173,6 +197,10 @@ module AgentC
173
197
  task.store
174
198
  end
175
199
 
200
+ def rewind_to!(step)
201
+ @rewind_to = step.to_s
202
+ end
203
+
176
204
  def repo
177
205
  @repo ||= @git.call(workspace.dir)
178
206
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AgentC
4
- VERSION = "2.71828"
4
+ VERSION = "2.718281"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: agent_c
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.71828'
4
+ version: '2.718281'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pete Kinnecom