diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-14 10:55:38 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-14 10:55:38 +0200 |
| commit | 8b0531bec5e9229ca41ab7bf143e319f66ed0a22 (patch) | |
| tree | c705122a5d645cf77e4162a93f3bbfc56fa5c84c | |
| parent | 2b4c2d4bbb47b59fb8bf7fec027efd36b1352857 (diff) | |
Resolve multi-word agent names in file DSLdevelop
| -rw-r--r-- | lib/dslkeywords/file.rb | 38 | ||||
| -rw-r--r-- | test/lib/dslkeywords/agent_test.rb | 40 |
2 files changed, 70 insertions, 8 deletions
diff --git a/lib/dslkeywords/file.rb b/lib/dslkeywords/file.rb index 08f8f48..1e40691 100644 --- a/lib/dslkeywords/file.rb +++ b/lib/dslkeywords/file.rb @@ -156,9 +156,7 @@ module RCM attr_reader :agent_name, :prompt_name def agent(spec = nil, prompt_name = nil) - agent_name = normalize_agent_reference(spec) - prompt_name = normalize_agent_reference(prompt_name) - agent_name, prompt_name = agent_name.split(/\s+/, 2) if prompt_name.nil? && agent_name&.include?(' ') + agent_name, prompt_name = resolved_agent_spec(spec, prompt_name) if agent_name.nil? || prompt_name.nil? raise InvalidAgentSpec, 'Expected exactly one agent name and one prompt name' @@ -218,6 +216,40 @@ module RCM normalized.gsub(/\s+/, ' ') end + def resolved_agent_spec(spec, prompt_name) + agent_name = normalize_agent_reference(spec) + prompt_name = normalize_agent_reference(prompt_name) + candidates = resolved_agent_candidates(agent_name, prompt_name) + + return candidates.first if candidates.one? + raise InvalidAgentSpec, 'Ambiguous agent specification' if candidates.length > 1 + return [agent_name, prompt_name] unless prompt_name.nil? + return [agent_name, nil] unless agent_name&.include?(' ') + + agent_name.split(/\s+/, 2) + end + + def resolved_agent_candidates(agent_name, prompt_name) + phrase = [agent_name, prompt_name].compact.join(' ') + parts = phrase.split(/\s+/) + return [] if parts.length < 2 + + (1...parts.length).filter_map do |index| + candidate_agent_name = parts[0...index].join(' ') + candidate_prompt_name = parts[index..].join(' ') + next unless definition_registered?(AgentDefinition, candidate_agent_name) + next unless definition_registered?(PromptDefinition, candidate_prompt_name) + + [candidate_agent_name, candidate_prompt_name] + end + end + + def definition_registered?(klass, name) + dsl.class.object(klass.id_for(name)) + rescue klass::InvalidName + false + end + def evaluate_agent_processing! raise MissingAgentInput, "File #{@file_path} does not exist for agent processing" unless ::File.file?(@file_path) diff --git a/test/lib/dslkeywords/agent_test.rb b/test/lib/dslkeywords/agent_test.rb index d3fc49f..b09a2ec 100644 --- a/test/lib/dslkeywords/agent_test.rb +++ b/test/lib/dslkeywords/agent_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# rubocop:disable Metrics/ClassLength, Metrics/MethodLength +# rubocop:disable Metrics/ClassLength, Metrics/MethodLength, Metrics/AbcSize require 'minitest/autorun' require 'fileutils' require 'rbconfig' @@ -117,22 +117,52 @@ class RCMAgentTest < Minitest::Test File.write(file_path, 'abc123') configure_from_scratch do - agent 'reverse via file' do + agent reverse via file do command end - prompt 'no op' do + prompt no op do '' end file file_path do - agent 'reverse via file', 'no op' + agent reverse via file no op end end assert_equal '321cba', File.read(file_path) end + def test_agent_spec_raises_when_multiword_split_is_ambiguous + file_path = path('ambiguous.txt') + command = mock_agent_command(:pass_through) + File.write(file_path, 'hello') + + assert_raises(RCM::File::InvalidAgentSpec) do + configure_from_scratch do + agent alpha do + command + end + + agent alpha beta do + command + end + + prompt gamma do + '' + end + + prompt beta gamma do + '' + end + + file file_path do + agent alpha beta gamma + end + end + end + end + def test_agent_can_use_file_path_placeholder file_path = path('placeholder.txt') command = mock_agent_command(:basename, 'FILE_PATH') @@ -346,4 +376,4 @@ class RCMAgentTest < Minitest::Test end end -# rubocop:enable Metrics/ClassLength, Metrics/MethodLength +# rubocop:enable Metrics/ClassLength, Metrics/MethodLength, Metrics/AbcSize |
