Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion lib/roast/cogs/agent/providers/claude.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ def initialize(invocation_result)
def invoke(input)
invocations = [] #: Array[ClaudeInvocation]
input.prompts.each do |prompt|
invocation = ClaudeInvocation.new(@config, prompt, invocations.last&.result&.session || input.session)
previous_session = invocations.last&.result&.session
invocation = ClaudeInvocation.new(
@config,
prompt,
previous_session || input.session,
fork_session: previous_session.nil?,
)
invocation.run!
invocations << invocation
break unless invocation.result.success
Expand Down
10 changes: 7 additions & 3 deletions lib/roast/cogs/agent/providers/claude/claude_invocation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ def initialize
end
end

#: (Agent::Config, String, String?) -> void
def initialize(config, prompt, session)
#: (Agent::Config, String, String?, ?fork_session: bool) -> void
def initialize(config, prompt, session, fork_session: true)
@base_command = config.valid_command #: (String | Array[String])?
@model = config.valid_model #: String?
@append_system_prompt = config.valid_append_system_prompt #: String?
Expand All @@ -69,6 +69,7 @@ def initialize(config, prompt, session)
@show_response = config.show_response? #: bool
@prompt = prompt
@session = session
@fork_session = fork_session #: bool
end

#: () -> void
Expand Down Expand Up @@ -184,7 +185,10 @@ def command_line
command.push("--model", @model) if @model
command.push("--system-prompt", @replace_system_prompt) if @replace_system_prompt
command.push("--append-system-prompt", @append_system_prompt) if @append_system_prompt
command.push("--fork-session", "--resume", @session) if @session.present?
if @session.present?
command.push("--fork-session") if @fork_session
command.push("--resume", @session)
end
command << "--dangerously-skip-permissions" unless @apply_permissions
command
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def failure_status
assert_equal "Additional instructions", command[prompt_index + 1]
end

test "command_line includes session flags when session is set" do
test "command_line includes fork-session and resume when session is set" do
invocation = ClaudeInvocation.new(@config, "Test prompt", "session_123")

command = invocation.send(:command_line)
Expand All @@ -244,6 +244,26 @@ def failure_status
assert_equal "session_123", command[resume_index + 1]
end

test "command_line includes resume without fork-session when fork_session is false" do
invocation = ClaudeInvocation.new(@config, "Test prompt", "session_123", fork_session: false)

command = invocation.send(:command_line)

refute_includes command, "--fork-session"
assert_includes command, "--resume"
resume_index = command.index("--resume")
assert_equal "session_123", command[resume_index + 1]
end

test "command_line omits fork-session when no session is given even if fork_session is true" do
invocation = ClaudeInvocation.new(@config, "Test prompt", nil, fork_session: true)

command = invocation.send(:command_line)

refute_includes command, "--fork-session"
refute_includes command, "--resume"
end

test "command_line includes dangerously-skip-permissions when permissions skipped" do
@config.skip_permissions!
command = @invocation.send(:command_line)
Expand Down
37 changes: 37 additions & 0 deletions test/roast/cogs/agent/providers/claude_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,43 @@ def mock_status(success:)
assert_equal ["session_from_first"], sessions_seen
end

test "invoke does not fork session for subsequent invocations" do
input = Agent::Input.new
input.prompts = ["Main task", "Finalizer"]

fork_flags = []
call_count = 0
CommandRunner.stubs(:execute).with do |args, **kwargs|
call_count += 1
fork_flags << args.include?("--fork-session")
result_json = { type: "result", subtype: "success", result: "done", session_id: "session_1" }.to_json
kwargs[:stdout_handler]&.call(result_json)
true
end.returns(["", "", mock_status(success: true)])

@provider.invoke(input)

assert_equal [false, false], fork_flags
end

test "invoke forks session for first invocation when input has session" do
input = Agent::Input.new
input.prompts = ["Main task", "Finalizer"]
input.session = "external_session"

fork_flags = []
CommandRunner.stubs(:execute).with do |args, **kwargs|
fork_flags << args.include?("--fork-session")
result_json = { type: "result", subtype: "success", result: "done", session_id: "new_session" }.to_json
kwargs[:stdout_handler]&.call(result_json)
true
end.returns(["", "", mock_status(success: true)])

@provider.invoke(input)

assert_equal [true, false], fork_flags
end

test "invoke stops on first failed invocation" do
input = Agent::Input.new
input.prompts = ["Main task", "Finalizer 1", "Finalizer 2"]
Expand Down
Loading