ISS-82: Add Pre-Built Message History To Runner#86
Conversation
- Add public Message, ToolCall, ToolResult types in pkg/runner - Add validateMessages() with role, type-consistency, and call-ID checks - Add toProviderMessages()/fromProviderMessage() conversion helpers - Add Messages to runner.Options (skip Prompt/Stdin when set) - Add Messages to runner.Result, populate from req.Messages after run - Add MessageCount to DryRunInfo, update dry-run display - Update MarshalJSON to include messages array with empty [] defaults - Update memory append to use first user message from pre-built history - Add firstUserMessageContent() helper for memory task text - Fix conversation loop to append assistant messages before tool results - Add comprehensive tests: single-shot, tool loop, streaming, validation, dry-run, memory append, empty slice fallback, JSON serialization
|
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (17)
✅ Files skipped from review due to trivial changes (13)
📝 WalkthroughWalkthroughThis PR enables agents to accept pre-built message history via Options.Messages. It adds Message/ToolCall/ToolResult types, validation, converters to/from provider messages, run-loop integration (skipping stdin/prompt when provided), dry-run/result serialization for messages, and tests covering conversions, validation, run behavior, and fixtures. ChangesPre-built Message History
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pkg/runner/messages_test.go`:
- Around line 11-151: Refactor the individual tests in messages_test.go
(TestOptionsMessagesField, TestResultMessagesField, TestDryRunInfoMessageCount,
TestMessageTypeCanBeConstructed, TestToProviderMessages,
TestFromProviderMessage, TestRoundTripConversion and the remaining cases
mentioned) into table-driven tests using slices of structs with fields like
name, input, want (and any helper fields for expected ToolCalls/ToolResults),
then iterate the table with t.Run to assert expectations; keep the same
assertions (checking Options.Messages, Result.Messages, DryRunInfo.MessageCount,
Message fields, toProviderMessages/fromProviderMessage round-trips and
ToolCalls/ToolResults) but centralized in looped subtests to follow the
[]struct{name,input,want} pattern mandated by the testing guidelines.
In `@pkg/runner/messages.go`:
- Around line 11-15: Remove the package-level mutable map validRoles and replace
it with a side-effect-free helper predicate (e.g., an unexported
isValidRole(role string) bool) that uses a local switch or an immutable literal
lookup to validate roles; update all places that reference validRoles to call
isValidRole instead so you eliminate global mutable state while preserving the
same checks.
In `@pkg/runner/result_test.go`:
- Around line 63-164: The two one-off tests TestResultMarshalJSON_WithMessages
and TestResultMarshalJSON_WithMessagesAndToolCalls should be merged into a
single table-driven test (e.g., TestResultMarshalJSON) using a []struct{name
string, input Result, validate func(parsed map[string]interface{}) error} (or a
want struct describing expected message counts and fields) and iterating over
cases with t.Run(tc.name, func(t *testing.T){...}); locate the existing Result
instances and JSON marshal/unmarshal/assert logic in those functions and move
them into table entries, then run the same marshal/unmarshal flow and call the
per-case validate or compare fields (messages, tool_calls, tool_results, ids,
contents, is_error) to assert expected values.
In `@pkg/runner/run_test.go`:
- Around line 292-338: Refactor the standalone pre-built message tests
(including TestRun_PreBuiltMessages_Streaming and the other cases in the 589-957
range) into a table-driven test using a []struct{name string, opts Options,
mockResponses []testutil.MockLLMResponse, wantContent string, wantInputTokens
int, wantOutputTokens int, wantStdoutContains string} (or similar) and iterate
with for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ... }) };
inside each subtest set up the mock server using tt.mockResponses, call Run with
tt.opts, assert result fields against tt.want* and assert stdout contains
tt.wantStdoutContains when applicable (preserve the existing streaming test
behavior), and extract repeated setup code (setupTestEnv, newMockStdoutStderr,
env vars) into small helpers to keep each table entry concise.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7e400f4a-a89e-4965-b4a1-af785445f701
⛔ Files ignored due to path filters (2)
docs/plans/051_runner_message_history_implement.mdis excluded by!docs/**docs/plans/051_runner_message_history_spec.mdis excluded by!docs/**
📒 Files selected for processing (8)
cmd/run.gopkg/runner/messages.gopkg/runner/messages_test.gopkg/runner/options.gopkg/runner/result.gopkg/runner/result_test.gopkg/runner/run.gopkg/runner/run_test.go
Updated all test fixtures to use openrouter/openai/gpt-4o-mini model. Updated smoke/golden/fixture tests to use OPENROUTER_API_KEY instead of OPENAI_API_KEY / ANTHROPIC_API_KEY. Added OPENROUTER_API_KEY env var to GitHub Actions test step. Regenerated golden files to match the new model.
Summary
This update adds pre-built message history support to the runner, enabling callers to provide a complete conversation sequence directly via
Options.Messagesinstead of relying on stdin/prompt input. It includes comprehensive message validation, bidirectional conversion between internal and provider message formats, and updated dry-run/result output to reflect pre-built history. Additionally, test fixtures and golden files are updated to use the OpenRouter GPT-4o mini model as the default, and CI/CD is configured to provide the necessary API key.Changelog
Added
Options.MessagesfieldMessage,ToolCall, andToolResultstructs for representing conversation historyvalidateMessages) enforcing allowed roles and role-specific constraintsChanged
Run()now treats pre-built messages as first-class input, bypassing stdin/prompt resolutioncmd/testdata/agents/updated fromopenai/gpt-4ooranthropic/claude-sonnet-4-20250514toopenrouter/openai/gpt-4o-miniOPENROUTER_API_KEYenvironment variable from repository secrets