x_aeon_agents 1.2.0 β†’ 2.0.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: 1b574fe3b6c21e4cbae12dca8cbf3388aa789014a64288bad4e34f576b4966f3
4
- data.tar.gz: 5e5f82866ab3a64765e42432085cd1d377b469c0fd7c59bd0a27e8cb1c5d0bee
3
+ metadata.gz: e3d6851438a928d374ce8f950e86122553eeb9f27e5e2f9c2dd149fa51f52fe7
4
+ data.tar.gz: 8a6bfdb35ae71c18033e6a8eb9111567e3dc7d3b900d7e66bf6e76411763c0e3
5
5
  SHA512:
6
- metadata.gz: 1856c8f3d29c2cee16b838069604048965d23ea8dce516da639e22d25e4dc1732299fd9819ce22972a0ae72fe81c5b9a9ef29e276daa178b5a84ae7d7c8c06c2
7
- data.tar.gz: 1038e588d96bc6e72be99dba5087c70d8f8309e7a6fccdc26ddedfb3bd23a78ff441bc4aacba3cbd02932eef28412380ac163f23c3d41d9de7d05ea8cc286d1d
6
+ metadata.gz: df4b5684cf386d5886638caf8e1ea316f8e87d09f52ea744872af01fc238d356ce0b16412715ab9826797d17d299f7e983b1769b9101822df74f1a1f56f9cb7d
7
+ data.tar.gz: 75b83097f7230170cd275a6253ec00f8245ebe0b8984099990c821b7ef0a2d1a4796639f39a21fc69074dda1b61b35cf4d75d1d1b1e917d7bb07df4bb0bdbda0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # [v2.0.0](https://github.com/Muriel-Salvan/x_aeon_agents/compare/v1.3.0...v2.0.0) (2026-10-15 22:46:39)
2
+
3
+ ### Breaking changes
4
+
5
+ * [Make PR base ref configurable for requirement and issue implementation](https://github.com/Muriel-Salvan/x_aeon_agents/commit/8a16c8f4c3c7705239a763248a4e2fb0e2150c01)
6
+
7
+ # [v1.3.0](https://github.com/Muriel-Salvan/x_aeon_agents/compare/v1.2.0...v1.3.0) (2026-10-13 14:54:19)
8
+
9
+ ### Features
10
+
11
+ * [feat: add --no-interactive flag and interactive config option](https://github.com/Muriel-Salvan/x_aeon_agents/commit/51db8e5a1723e5c89311131ac73ed7ede23a9d21)
12
+
1
13
  # [v1.2.0](https://github.com/Muriel-Salvan/x_aeon_agents/compare/v1.1.1...v1.2.0) (2026-09-11 17:57:31)
2
14
 
3
15
  ### Features
data/README.md CHANGED
@@ -195,7 +195,7 @@ Each of these secrets can alternatively be retrieved by custom code declared in
195
195
  - πŸ“ **AI commit messages** β€” analyze staged changes and generate a meaningful message, with flexible staging strategies (`all`, `if_empty`, `none`)
196
196
  - πŸš€ **Automated Pull Request creation** β€” push the branch to GitHub and open a PR against a configurable base ref with an AI-written description
197
197
  - πŸ› **GitHub issue implementation** β€” turn an issue (and its comments) into working code, committing changes and opening a PR automatically
198
- - πŸ› οΈ **Arbitrary requirement implementation** β€” pass free-form requirements to a Developer agent that plans, codes and tests the changes, optionally committing and opening a PR
198
+ - πŸ› οΈ **Arbitrary requirement implementation** β€” pass free-form requirements to a Developer agent that plans, codes and tests the changes, optionally committing and opening a PR against a configurable base ref
199
199
  - πŸ“š **README generation** β€” build a full README from the codebase with 10 toggleable sections (about, quick start, requirements, features, public API, documentation, how-it-works, development, contributing, license)
200
200
  - πŸ” **Git diff interpretation** β€” summarize the working-tree changes and the intent behind them relative to any base ref
201
201
  - πŸ’¬ **One-shot prompts** β€” send a single prompt to the AI agent and print the response
@@ -204,7 +204,7 @@ Each of these secrets can alternatively be retrieved by custom code declared in
204
204
  - 🌿 **Task bootstrapping** β€” create a feature branch, set up a git worktree, push it upstream and open it in the editor, with `setup_project` and `on_open_worktree` hooks
205
205
  - 🧩 **Composable agent framework** β€” orchestrating agents (planner ➜ coder ➜ tester ➜ committer ➜ documenter ➜ PR creator) built on `ai-agents`/`composable_agents`, backed by a Cline/OpenRouter provider via RubyLLM
206
206
  - βš™οΈ **Extensible config DSL** β€” optional `.x_aeon_agents.rb` file with secrets handling, per-agent model tuning (`configure_agent`) and a project test command
207
- - πŸ’Ύ **Session persistence & debugging** β€” global `--session-id` to resume AI conversations and a `--debug` flag for verbose logging
207
+ - πŸ’Ύ **Session persistence & debugging** β€” global `--session-id` to resume AI conversations, a `--debug` flag for verbose logging and a `--no-interactive` flag to skip interactive review prompts
208
208
  - πŸ“¦ **Reusable Ruby library** β€” require the gem and trigger agents programmatically (e.g. `Agents::CommitterAgent.new.run`)
209
209
 
210
210
  ## Public API
@@ -266,13 +266,14 @@ Files are looked up in the following locations and evaluated from the lowest pri
266
266
  3. The path given by the `X_AEON_AGENTS_CONFIG` environment variable, if set β€” overrides both
267
267
 
268
268
  > [!NOTE]
269
- > All existing files are evaluated in this order (not just the first one found), and explicit CLI flags (`--debug`) still override everything. The file is evaluated in a cleanroom: only the DSL methods below are exposed at its top level, but regular Ruby code works inside the blocks given to those methods.
269
+ > All existing files are evaluated in this order (not just the first one found), and explicit CLI flags (`--debug`, `--interactive`) still override everything. The file is evaluated in a cleanroom: only the DSL methods below are exposed at its top level, but regular Ruby code works inside the blocks given to those methods.
270
270
 
271
271
  #### Possible methods
272
272
 
273
273
  | Method | Description |
274
274
  | --- | --- |
275
275
  | `debug(value)` | Enable debug logging |
276
+ | `interactive(value)` | Enable interactive content reviews (defaults to `true`) |
276
277
  | `data_dir 'dir'` | Data directory where X-Aeon Agents stores its data |
277
278
  | `cline_api_key { ... }` / `openrouter_api_key { ... }` / `github_token { ... }` | Define the code retrieving a secret |
278
279
  | `setup_project { ... }` | Steps to install the project's dependencies in a fresh worktree |
@@ -286,6 +287,12 @@ Files are looked up in the following locations and evaluated from the lowest pri
286
287
  debug true
287
288
  ```
288
289
 
290
+ - **`interactive(value)`** β€” set the interactive mode: when disabled, content reviews (commit comments, implementation plans…) are accepted as-is, without opening any file nor prompting the user. Defaults to `true`:
291
+
292
+ ```ruby
293
+ interactive false
294
+ ```
295
+
289
296
  - **`data_dir(path)`** β€” set the data directory where X-Aeon Agents stores its data (sessions, etc.). Defaults to `.x_aeon_agents`:
290
297
 
291
298
  ```ruby
@@ -357,6 +364,7 @@ Public methods:
357
364
  - `data_dir` / `data_dir=` β€” data directory (`.x_aeon_agents` by default). [doc](https://www.rubydoc.info/gems/x-aeon_agents/XAeonAgents/Config#data_dir-class_method)
358
365
  - `default_cline_cli_args` / `default_cline_cli_args=` β€” default Cline CLI arguments. [doc](https://www.rubydoc.info/gems/x-aeon_agents/XAeonAgents/Config#default_cline_cli_args-class_method)
359
366
  - `debug` / `debug=` β€” enable debug logging. [doc](https://www.rubydoc.info/gems/x-aeon_agents/XAeonAgents/Config#debug-class_method)
367
+ - `interactive` / `interactive=` β€” enable interactive content reviews (defaults to true). [doc](https://www.rubydoc.info/gems/x-aeon_agents/XAeonAgents/Config#interactive-class_method)
360
368
  - `config_paths` β€” candidate paths of the optional `.x_aeon_agents.rb` config file. [doc](https://www.rubydoc.info/gems/x-aeon_agents/XAeonAgents/Config#config_paths-class_method)
361
369
  - `logger` β€” the shared logger instance. [doc](https://www.rubydoc.info/gems/x-aeon_agents/XAeonAgents/Config#logger-class_method)
362
370
 
@@ -440,7 +448,7 @@ The documented public methods (browseable on RubyDoc.info):
440
448
 
441
449
  - The [`xaa`](https://github.com/Muriel-Salvan/x_aeon_agents/blob/main/bin/xaa) executable boots [Zeitwerk](https://github.com/fxn/zeitwerk) auto-loading and calls `XAeonAgents::Cli.start(ARGV)`.
442
450
  - The CLI ([`lib/x_aeon_agents/cli.rb`](https://github.com/Muriel-Salvan/x_aeon_agents/blob/main/lib/x_aeon_agents/cli.rb)) is a [Thor](https://github.com/rails/thor) application: every sub-command (`commit`, `create-pr`, `review-comments`, `implement-issue`, `generate-readme`…) maps **1:1** to an agent class.
443
- - On startup it loads the optional `.x_aeon_agents.rb` config (home directory, then project directory) so project-level settings override global ones, and explicit CLI flags (`--session-id`, `--debug`) override both.
451
+ - On startup it loads the optional `.x_aeon_agents.rb` config (home directory, then project directory) so project-level settings override global ones, and explicit CLI flags (`--session-id`, `--debug`, `--interactive`) override both.
444
452
 
445
453
  ### Agents as composable workflows 🧩
446
454
 
@@ -16,12 +16,13 @@ module XAeonAgents
16
16
  # Constructor
17
17
  #
18
18
  # @param commit [Boolean] Should we commit files at every step?
19
- # @param pull_request [Boolean] Should we create a Github Pull Request with this implementation?
19
+ # @param pr_base_ref [String, nil] The git ref (branch name) of the base of the Github Pull Request to
20
+ # create with this implementation, or nil to not create any Pull Request
20
21
  # @param agent_params [Hash{Symbol => Object}] Extra agent parameters
21
- def initialize(commit: false, pull_request: false, **agent_params)
22
+ def initialize(commit: false, pr_base_ref: nil, **agent_params)
22
23
  super(name: 'Developer', **agent_params)
23
24
  @commit = commit
24
- @pull_request = pull_request
25
+ @pr_base_ref = pr_base_ref
25
26
  end
26
27
 
27
28
  # Execute the agent to generate some output artifacts based on some input artifacts.
@@ -34,7 +35,8 @@ module XAeonAgents
34
35
  task(:setup_requirements, name: 'Setup requirements', intent: 'Initialize requirements from the current commit') do
35
36
  @artifacts.merge!(
36
37
  requirements:,
37
- base_sha: Helpers.git.gcommit('HEAD').sha
38
+ base_sha: Helpers.git.gcommit('HEAD').sha,
39
+ pr_base_ref: @pr_base_ref
38
40
  )
39
41
  end
40
42
 
@@ -208,7 +210,7 @@ module XAeonAgents
208
210
  )
209
211
  logger.info "Documenter changes: #{Helpers.git.status_info.changed.keys.join(', ')}"
210
212
 
211
- if @commit || @pull_request
213
+ if @commit || @pr_base_ref
212
214
  task(
213
215
  new_agent(
214
216
  CommitterAgent,
@@ -220,7 +222,7 @@ module XAeonAgents
220
222
  )
221
223
  end
222
224
 
223
- if @pull_request
225
+ if @pr_base_ref
224
226
  task(
225
227
  new_agent(
226
228
  PullRequestCreatorAgent,
@@ -14,12 +14,13 @@ module XAeonAgents
14
14
  # Constructor
15
15
  #
16
16
  # @param commit [Boolean] Whether to commit changes automatically
17
- # @param pull_request [Boolean] Whether to create a pull request automatically
17
+ # @param pr_base_ref [String, nil] The git ref (branch name) of the base of the Pull Request to create,
18
+ # or nil to not create any Pull Request
18
19
  # @param agent_params [Hash{Symbol => Object}] Extra agent parameters
19
- def initialize(commit: false, pull_request: false, **agent_params)
20
+ def initialize(commit: false, pr_base_ref: nil, **agent_params)
20
21
  super(name: 'Issue implementer', **agent_params)
21
22
  @commit = commit
22
- @pull_request = pull_request
23
+ @pr_base_ref = pr_base_ref
23
24
  end
24
25
 
25
26
  # Execute the agent to implement a GitHub issue.
@@ -35,7 +36,7 @@ module XAeonAgents
35
36
  issue = Helpers.github.issue(Helpers.github_repo, github_issue_number)
36
37
  issue_comments = Helpers.github.issue_comments(Helpers.github_repo, github_issue_number)
37
38
  task(
38
- new_agent(DeveloperAgent, commit: @commit, pull_request: @pull_request),
39
+ new_agent(DeveloperAgent, commit: @commit, pr_base_ref: @pr_base_ref),
39
40
  requirements: build_requirements(issue, issue_comments),
40
41
  intent: 'Develop the gathered requirements'
41
42
  )
@@ -9,7 +9,7 @@ module XAeonAgents
9
9
  # @return [Hash{Symbol => Object}] Set of input artifacts description, per artifact name
10
10
  def input_artifacts_contracts
11
11
  {
12
- base_sha: 'The git ref of the base of the feature branch',
12
+ pr_base_ref: 'The git ref (branch name) of the base to create the Pull Request against',
13
13
  requirements: {
14
14
  description: 'The initial requirements',
15
15
  optional: true
@@ -28,10 +28,10 @@ module XAeonAgents
28
28
 
29
29
  # Execute the agent to generate some output artifacts based on some input artifacts.
30
30
  #
31
- # @param base_sha [String] The git reference of the base of the branch.
31
+ # @param pr_base_ref [String] The git ref (branch name) used as base of the Pull Request.
32
32
  # @param requirements [String, nil] The initial requirements, or nil if none.
33
33
  # @return [Hash{Symbol => Object}] Output artifacts content
34
- def run(base_sha:, requirements: nil)
34
+ def run(pr_base_ref:, requirements: nil)
35
35
  super
36
36
  raise 'Unable to find the Github repository' unless Helpers.github_repo
37
37
 
@@ -56,7 +56,7 @@ module XAeonAgents
56
56
  if @artifacts[:existing_pr_url].nil?
57
57
  # Create new PR
58
58
  git_diff_interpreter_agent = new_agent(GitDiffInterpreterAgent)
59
- task(git_diff_interpreter_agent, intent: 'Analyze changes in the whole branch', git_ref_base: base_sha)
59
+ task(git_diff_interpreter_agent, intent: 'Analyze changes in the whole branch', git_ref_base: pr_base_ref)
60
60
  task(:create_pr, name: 'Create Pull Request', intent: "Create a Pull Request for the branch #{head_branch} on repo #{repo_name}") do
61
61
  sections = [@artifacts[:change_intent].strip]
62
62
  sections << <<~EO_SECTION if requirements
@@ -135,7 +135,7 @@ module XAeonAgents
135
135
  EO_SECTION
136
136
  new_pr = Helpers.github.create_pull_request(
137
137
  repo_name,
138
- base_sha,
138
+ pr_base_ref,
139
139
  head_branch,
140
140
  @artifacts[:one_line_summary].strip,
141
141
  sections.map(&:strip).join("\n\n")
@@ -100,7 +100,14 @@ module XAeonAgents
100
100
  @artifacts[:plan] = 'No implementation plan'
101
101
  @artifacts[:files_diffs] = 'No changes'
102
102
  else
103
- task(new_agent(DeveloperAgent, commit: true, pull_request: true), intent: 'Develop new requirements devise from review comments')
103
+ task(
104
+ new_agent(
105
+ DeveloperAgent,
106
+ commit: true,
107
+ pr_base_ref: Helpers.github.pull_request(Helpers.github_repo, @artifacts[:pr_number]).base.ref
108
+ ),
109
+ intent: 'Develop new requirements devise from review comments'
110
+ )
104
111
  end
105
112
 
106
113
  @artifacts[:open_comments_to_agents].each.with_index do |comment, comment_idx|
@@ -8,6 +8,9 @@ module XAeonAgents
8
8
  # Defaults to nil so the absence of the flag can be told apart from an
9
9
  # explicit --no-debug (which lets the config file or ENV take precedence).
10
10
  class_option :debug, type: :boolean, default: nil, desc: 'Enable debug mode'
11
+ # Defaults to nil so the absence of the flag can be told apart from an
12
+ # explicit --no-interactive (which lets the config file take precedence).
13
+ class_option :interactive, type: :boolean, default: nil, desc: 'Enable interactive prompts with the user'
11
14
 
12
15
  # --------------------------------------------------------------------------- #
13
16
  # review-comments: Address Pull Request review comments
@@ -100,7 +103,7 @@ module XAeonAgents
100
103
  # Push changes on Github and create a Pull Request.
101
104
  def create_pr
102
105
  agent_kwargs = {
103
- base_sha: options[:base]
106
+ pr_base_ref: options[:base]
104
107
  }
105
108
  agent_kwargs[:requirements] = options[:requirements] if options[:requirements]
106
109
  Agents::PullRequestCreatorAgent.new(session_id: options[:session_id]).run(**agent_kwargs)
@@ -207,21 +210,25 @@ module XAeonAgents
207
210
  long_desc <<~LONGDESC
208
211
  Reads the content (and comments) of a GitHub issue and delegates the
209
212
  implementation to the Developer agent. The agent commits changes and
210
- opens a Pull Request automatically.
213
+ opens a Pull Request against the base given with the --pr-base option
214
+ (defaults to main).
211
215
 
212
216
  Examples:
213
217
 
214
218
  $ xaa implement-issue 15
215
219
 
220
+ $ xaa implement-issue 15 --pr-base master
221
+
216
222
  $ xaa implement-issue 15 --session-id my-session
217
223
  LONGDESC
224
+ option :pr_base, type: :string, default: 'main', desc: 'Base git ref of the GitHub Pull Request to create'
218
225
  # Implements a GitHub issue using AI.
219
226
  #
220
227
  # @param github_issue_number [Integer] The GitHub issue number to implement
221
228
  def implement_issue(github_issue_number)
222
229
  Agents::IssueImplementerAgent.new(
223
230
  commit: true,
224
- pull_request: true,
231
+ pr_base_ref: options[:pr_base],
225
232
  session_id: options[:session_id]
226
233
  ).run(github_issue_number: Integer(github_issue_number))
227
234
  end
@@ -235,21 +242,24 @@ module XAeonAgents
235
242
  Pass free-form requirements to the Developer agent, which will analyze
236
243
  the codebase and produce the requested changes.
237
244
 
245
+ The --pr-base option gives the base ref of the Pull Request to create:
246
+ omit the option to not create any Pull Request.
247
+
238
248
  Examples:
239
249
 
240
250
  $ xaa implement "Add authentication middleware"
241
251
 
242
- $ xaa implement "Refactor the database layer" --commit --pr --session-id my-session
252
+ $ xaa implement "Refactor the database layer" --commit --pr-base main --session-id my-session
243
253
  LONGDESC
244
254
  option :commit, type: :boolean, default: false, desc: 'Commit files at every step'
245
- option :pr, type: :boolean, default: false, desc: 'Create a GitHub Pull Request for the changes'
255
+ option :pr_base, type: :string, default: nil, desc: 'Base git ref of the GitHub Pull Request to create (omit for no Pull Request)'
246
256
  # Implements arbitrary requirements using AI.
247
257
  #
248
258
  # @param requirements [String] Free-form requirements describing the desired changes
249
259
  def implement(requirements)
250
260
  Agents::DeveloperAgent.new(
251
261
  commit: options[:commit],
252
- pull_request: options[:pr],
262
+ pr_base_ref: options[:pr_base],
253
263
  session_id: options[:session_id]
254
264
  ).run(requirements:)
255
265
  end
@@ -390,6 +400,7 @@ module XAeonAgents
390
400
  super
391
401
  Config.load
392
402
  Config.debug = options[:debug] unless options[:debug].nil?
403
+ Config.interactive = options[:interactive] unless options[:interactive].nil?
393
404
  end
394
405
  end
395
406
  end
@@ -98,6 +98,19 @@ module XAeonAgents
98
98
  @debug ||= ENV['X_AEON_AGENTS_DEBUG'] == '1'
99
99
  end
100
100
 
101
+ # @return [Boolean] The interactive mode, controlling whether content reviews prompt the user
102
+ attr_writer :interactive
103
+
104
+ # Get the interactive mode.
105
+ # Defaults to true when never explicitly set, and honors an explicit false.
106
+ #
107
+ # @return [Boolean] The interactive mode
108
+ def interactive
109
+ return true if @interactive.nil?
110
+
111
+ @interactive
112
+ end
113
+
101
114
  # Candidate absolute paths of the configuration file, ordered by increasing
102
115
  # priority (lowest first): user home directory, current directory, then the
103
116
  # path given by the X_AEON_AGENTS_CONFIG environment variable if set.
@@ -15,6 +15,16 @@ module XAeonAgents
15
15
 
16
16
  expose :debug
17
17
 
18
+ # Set the interactive mode, controlling whether content reviews prompt the user.
19
+ #
20
+ # Parameters::
21
+ # * *value* (Boolean): The interactive mode to set
22
+ def interactive(value)
23
+ Config.interactive = value
24
+ end
25
+
26
+ expose :interactive
27
+
18
28
  # Set the data directory used by X-Aeon Agents to store its data.
19
29
  #
20
30
  # Parameters::
@@ -140,6 +140,10 @@ module XAeonAgents
140
140
 
141
141
  # Allow user to review and edit content before using it
142
142
  #
143
+ # When the interactive mode is disabled (Config.interactive), no review file
144
+ # is written, nothing is opened and no user input is asked: the given content
145
+ # is accepted as-is and an empty user prompt is returned.
146
+ #
143
147
  # @param reviews_dir [String] Directory that can be used to store files to be reviewed
144
148
  # @param name [String] Name used for the temporary file
145
149
  # @param description [String] Description shown to the user
@@ -147,8 +151,8 @@ module XAeonAgents
147
151
  # @param promptable [Boolean] Indicates if user can issue a prompt as an answer
148
152
  # @param content [String] Initial content to present
149
153
  # @return [Array<String>] 2 values are returned:
150
- # - [String] Content after user review (same as content if editable is false)
151
- # - [String] User prompt
154
+ # - [String] Content after user review (same as content if editable is false or the interactive mode is disabled)
155
+ # - [String] User prompt (empty when the interactive mode is disabled)
152
156
  def review_content(
153
157
  reviews_dir: "#{Config.data_dir}/reviews",
154
158
  name: 'content.txt',
@@ -157,6 +161,10 @@ module XAeonAgents
157
161
  promptable: false,
158
162
  content: ''
159
163
  )
164
+ # When the interactive mode is disabled, accept the content as-is without
165
+ # writing any review file nor asking anything to the user.
166
+ return [content, ''] unless Config.interactive
167
+
160
168
  content_file = "#{reviews_dir}/#{Time.now.utc.strftime('%F-%H-%M-%S')}-#{name}"
161
169
  FileUtils.mkdir_p File.dirname(content_file)
162
170
  File.write(content_file, content)
@@ -2,5 +2,5 @@ module XAeonAgents
2
2
  # @!group Global API
3
3
 
4
4
  # Gem version
5
- VERSION = '1.2.0'
5
+ VERSION = '2.0.0'
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: x_aeon_agents
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Muriel Salvan