action_ai 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 026dc5bbd0ff082b147fc05e6e9e2784d0f89da393249857c383e38da57c79ac
4
- data.tar.gz: ffeec65357f212fd305ad480a7a5f35c2b96ba9880acfcafbdaf437885f532b0
3
+ metadata.gz: f5b0c31e7ae5b9944a95f32563d3873adea7134ea32e11ebfc5dbc2a81eafec9
4
+ data.tar.gz: d20750877288e1e1306a58a08f6b1aeea02985d749df8ce763262e0cc68314e6
5
5
  SHA512:
6
- metadata.gz: 742b0b2a62dc5ab713b5fa3cb64aa255a197835b0ef027f6e79bc0903f4c3497f1b13836a2792dfd75852423d08dd7fd65dbc81108c92d143b6f812a64ac9172
7
- data.tar.gz: 9999ac05bfd4eca661dbe84156b2d06a8a6ab0006ae64d7bc2d2f0c334b125e62ea8ed4f03ba24c6248f90b0d305ca9848a10cfa19040c06815face10bdc251a
6
+ metadata.gz: 84b92d55d7310f17e3746457cd76ecdae5dbed20aee80276b61d30824b38093d13c3f4753b69925e819dac9471bcfd5d1c1733aa46c78dd68969d0350c24a0c7
7
+ data.tar.gz: 0bbec9e620ec3fa03151b8dc4d6223b8a1de5d6b18cb4731c96df73d1bd2a9fb25a862c4dc3cbe27093468376a61c90d32f6763ef95f88f9c2f78118a077934e
data/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.2.0] - 2026-06-30
6
+
7
+ ### Added
8
+
9
+ - Implicit `ask` behavior for AI actions without explicit prompts, matching Action Controller-style ergonomics.
10
+ - Action chaining, enabling users to construct complex AI workflows from discrete jobs.
11
+
12
+ ### Fixed
13
+
14
+ - `echo` test model to support multiple chat interactions.
15
+
5
16
  ## [0.1.0] - 2026-05-05
6
17
 
7
18
  Refactored from Action Mailer.
data/README.rdoc CHANGED
@@ -16,6 +16,8 @@ shape for AI interactions rather than building an unrelated API from scratch.
16
16
 
17
17
  The framework works by initializing any instance variables you want to be
18
18
  available in the prompt template.
19
+ Like +render+ in Action Controller, the implicit +ask+ will be triggered
20
+ automatically at the end of the action unless you have already called it.
19
21
 
20
22
  This can be as simple as:
21
23
 
@@ -25,10 +27,16 @@ This can be as simple as:
25
27
  def code(task, language)
26
28
  @task = task
27
29
  @language = language
28
- ask
29
30
  end
30
31
  end
31
32
 
33
+ If you need to customize the prompt execution (e.g., pass options or a custom prompt),
34
+ you can call +ask+ explicitly:
35
+
36
+ def run(spec_file)
37
+ ask "Run the attached spec", with: spec_file
38
+ end
39
+
32
40
  After the action method completes, the framework will automatically:
33
41
  1. Render the prompt from the corresponding template (e.g., +app/ai/prompts/generator/code.erb+)
34
42
  2. Send it to the configured AI model via +ask+
@@ -64,6 +72,22 @@ Or you can just chain the methods together like:
64
72
 
65
73
  Generator.code("Parse CSV and dedupe", :ruby).content # Returns AI's response for the prompt
66
74
 
75
+ You can also chain multiple agent actions to compose a small workflow before reading the final response:
76
+
77
+ class WorkflowAgent < ApplicationAI
78
+ def collect(topic)
79
+ @topic = topic
80
+ ask "Collect #{@topic}"
81
+ end
82
+
83
+ def refine(style:)
84
+ ask "Refine #{@topic} as #{style}"
85
+ end
86
+ end
87
+
88
+ WorkflowAgent.collect("release notes").refine(style: "bullet list").content
89
+ # => collected release notes refined as bullet list
90
+
67
91
  == Setting defaults
68
92
 
69
93
  It is possible to set default values that will be used in every method in your
@@ -278,6 +278,7 @@ module ActionAI
278
278
  # <tt>execution_job</tt>. Agents can set this to use a custom queue name.
279
279
  class Agent < AbstractController::Base
280
280
  include Callbacks
281
+ include ImplicitInteraction
281
282
  include QueuedExecution
282
283
  include Rescuable
283
284
  include Parameterized
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionAI
4
+ # # Action AI Implicit Interaction
5
+ #
6
+ # Handles implicit interactions for an agent action that does not explicitly
7
+ # respond with `ask`.
8
+ #
9
+ # If no explicit `ask` is performed by the action, the implicit response is
10
+ # to call `ask` with the default prompt rendering.
11
+ module ImplicitInteraction
12
+ def send_action(...)
13
+ super
14
+ .tap { default_interaction unless performed? }
15
+ end
16
+
17
+ def default_interaction = ask
18
+ end
19
+ end
@@ -77,6 +77,23 @@ module ActionAI
77
77
  # end
78
78
  def later(...) = enqueue_execution(...)
79
79
 
80
+ ruby2_keywords def method_missing(method, *args, &)
81
+ case method.name
82
+ when *@agent_class.action_methods
83
+ processed_agent.process(@action = method, *(@args = args), &)
84
+ self
85
+ else
86
+ super
87
+ end
88
+ end
89
+
90
+ def respond_to_missing?(method, include_private = false)
91
+ [
92
+ method.name.in?(@agent_class.action_methods),
93
+ super,
94
+ ].any?
95
+ end
96
+
80
97
  private
81
98
  # Returns the processed Agent instance. We keep this instance
82
99
  # on hand so we can run callbacks and delegate exception handling to it.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionAI
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/action_ai.rb CHANGED
@@ -48,6 +48,7 @@ module ActionAI
48
48
  autoload :TestCase
49
49
  autoload :TestHelper
50
50
  autoload :Interaction
51
+ autoload :ImplicitInteraction
51
52
  autoload :ExecutionJob
52
53
  autoload :QueuedExecution
53
54
 
@@ -26,7 +26,10 @@ module RubyLLM
26
26
  private
27
27
 
28
28
  def echo_response(messages, **) = {
29
- content: RubyLLM.concat_content(messages.map(&:content)),
29
+ content: RubyLLM.concat_content(messages
30
+ .reverse_each.take_while { it.role != :assistant }.reverse
31
+ .map(&:content)
32
+ ),
30
33
  }
31
34
  end
32
35
  end
metadata CHANGED
@@ -1,169 +1,185 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_ai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Alexander Senko
7
+ - Alexander Senko
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
- - !ruby/object:Gem::Dependency
13
- name: activesupport
14
- requirement: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - ">="
17
- - !ruby/object:Gem::Version
18
- version: '0'
19
- type: :runtime
20
- prerelease: false
21
- version_requirements: !ruby/object:Gem::Requirement
22
- requirements:
23
- - - ">="
24
- - !ruby/object:Gem::Version
25
- version: '0'
26
- - !ruby/object:Gem::Dependency
27
- name: actionpack
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: '0'
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: '0'
40
- - !ruby/object:Gem::Dependency
41
- name: actionview
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: '0'
47
- type: :runtime
48
- prerelease: false
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: '0'
54
- - !ruby/object:Gem::Dependency
55
- name: activejob
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: '0'
61
- type: :runtime
62
- prerelease: false
63
- version_requirements: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- version: '0'
68
- - !ruby/object:Gem::Dependency
69
- name: ruby_llm
70
- requirement: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: '0'
75
- type: :runtime
76
- prerelease: false
77
- version_requirements: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: '0'
82
- - !ruby/object:Gem::Dependency
83
- name: memery
84
- requirement: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- version: '0'
89
- type: :runtime
90
- prerelease: false
91
- version_requirements: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - ">="
94
- - !ruby/object:Gem::Version
95
- version: '0'
96
- - !ruby/object:Gem::Dependency
97
- name: rails-dom-testing
98
- requirement: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: '2.2'
103
- type: :runtime
104
- prerelease: false
105
- version_requirements: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: '2.2'
110
- description: AI on Rails. Compose, run, and test AI prompts using the familiar controller/view
111
- pattern.
12
+ - !ruby/object:Gem::Dependency
13
+ name: activesupport
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ -
17
+ - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: "0"
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ -
25
+ - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: "0"
28
+ - !ruby/object:Gem::Dependency
29
+ name: actionpack
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ -
33
+ - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ -
41
+ - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ - !ruby/object:Gem::Dependency
45
+ name: actionview
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ -
49
+ - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ type: :runtime
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ -
57
+ - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ - !ruby/object:Gem::Dependency
61
+ name: activejob
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ -
65
+ - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ -
73
+ - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ - !ruby/object:Gem::Dependency
77
+ name: ruby_llm
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ -
81
+ - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ type: :runtime
85
+ prerelease: false
86
+ version_requirements: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ -
89
+ - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: "0"
92
+ - !ruby/object:Gem::Dependency
93
+ name: memery
94
+ requirement: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ -
97
+ - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: "0"
100
+ type: :runtime
101
+ prerelease: false
102
+ version_requirements: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ -
105
+ - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: "0"
108
+ - !ruby/object:Gem::Dependency
109
+ name: rails-dom-testing
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ -
113
+ - ~>
114
+ - !ruby/object:Gem::Version
115
+ version: "2.2"
116
+ type: :runtime
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ -
121
+ - ~>
122
+ - !ruby/object:Gem::Version
123
+ version: "2.2"
124
+ description: "AI on Rails. Compose, run, and test AI prompts using the familiar controller/view pattern."
112
125
  email: Alexander.Senko@gmail.com
113
126
  executables: []
114
127
  extensions: []
115
128
  extra_rdoc_files: []
116
129
  files:
117
- - CHANGELOG.md
118
- - MIT-LICENSE
119
- - README.rdoc
120
- - lib/action_ai.rb
121
- - lib/action_ai/agent.rb
122
- - lib/action_ai/callbacks.rb
123
- - lib/action_ai/deprecator.rb
124
- - lib/action_ai/execution_job.rb
125
- - lib/action_ai/interaction.rb
126
- - lib/action_ai/log_subscriber.rb
127
- - lib/action_ai/parameterized.rb
128
- - lib/action_ai/preview.rb
129
- - lib/action_ai/prompt_helper.rb
130
- - lib/action_ai/queued_execution.rb
131
- - lib/action_ai/railtie.rb
132
- - lib/action_ai/rescuable.rb
133
- - lib/action_ai/test_case.rb
134
- - lib/action_ai/test_helper.rb
135
- - lib/action_ai/version.rb
136
- - lib/rails/generators/ai/USAGE
137
- - lib/rails/generators/ai/ai_generator.rb
138
- - lib/rails/generators/ai/templates/agent.rb.tt
139
- - lib/rails/generators/ai/templates/application_agent.rb.tt
140
- - lib/ruby_llm/providers/test.rb
141
- - lib/ruby_llm/providers/test/echo.rb
142
- - lib/ruby_llm/tester.rb
143
- homepage: https://github.com/Alexander-Senko/action_ai
130
+ - CHANGELOG.md
131
+ - MIT-LICENSE
132
+ - README.rdoc
133
+ - lib/action_ai.rb
134
+ - lib/action_ai/agent.rb
135
+ - lib/action_ai/callbacks.rb
136
+ - lib/action_ai/deprecator.rb
137
+ - lib/action_ai/execution_job.rb
138
+ - lib/action_ai/implicit_interaction.rb
139
+ - lib/action_ai/interaction.rb
140
+ - lib/action_ai/log_subscriber.rb
141
+ - lib/action_ai/parameterized.rb
142
+ - lib/action_ai/preview.rb
143
+ - lib/action_ai/prompt_helper.rb
144
+ - lib/action_ai/queued_execution.rb
145
+ - lib/action_ai/railtie.rb
146
+ - lib/action_ai/rescuable.rb
147
+ - lib/action_ai/test_case.rb
148
+ - lib/action_ai/test_helper.rb
149
+ - lib/action_ai/version.rb
150
+ - lib/rails/generators/ai/USAGE
151
+ - lib/rails/generators/ai/ai_generator.rb
152
+ - lib/rails/generators/ai/templates/agent.rb.tt
153
+ - lib/rails/generators/ai/templates/application_agent.rb.tt
154
+ - lib/ruby_llm/providers/test.rb
155
+ - lib/ruby_llm/providers/test/echo.rb
156
+ - lib/ruby_llm/tester.rb
157
+ homepage: "https://github.com/Alexander-Senko/action_ai"
144
158
  licenses:
145
- - MIT
159
+ - MIT
146
160
  metadata:
147
- bug_tracker_uri: https://github.com/Alexander-Senko/action_ai/issues
148
- changelog_uri: https://github.com/Alexander-Senko/action_ai/blob/v0.1.0/CHANGELOG.md
149
- source_code_uri: https://github.com/Alexander-Senko/action_ai/tree/v0.1.0
150
- rubygems_mfa_required: 'true'
161
+ bug_tracker_uri: "https://github.com/Alexander-Senko/action_ai/issues"
162
+ changelog_uri: "https://github.com/Alexander-Senko/action_ai/blob/v0.2.0/CHANGELOG.md"
163
+ source_code_uri: "https://github.com/Alexander-Senko/action_ai/tree/v0.2.0"
164
+ rubygems_mfa_required: "true"
151
165
  rdoc_options: []
152
166
  require_paths:
153
- - lib
167
+ - lib
154
168
  required_ruby_version: !ruby/object:Gem::Requirement
155
169
  requirements:
156
- - - ">="
157
- - !ruby/object:Gem::Version
158
- version: '3.4'
170
+ -
171
+ - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: "3.4"
159
174
  required_rubygems_version: !ruby/object:Gem::Requirement
160
175
  requirements:
161
- - - ">="
162
- - !ruby/object:Gem::Version
163
- version: '0'
176
+ -
177
+ - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: "0"
164
180
  requirements:
165
- - none
166
- rubygems_version: 3.7.0.dev
181
+ - none
182
+ rubygems_version: 4.1.0.dev
167
183
  specification_version: 4
168
184
  summary: AI prompt composition and running framework
169
185
  test_files: []