Skip to content

feat: add Go M0 provider config and TUI foundations#52

Merged
Vasanthdev2004 merged 3 commits into
mainfrom
feat/go-m0-runtime-unify
Jun 4, 2026
Merged

feat: add Go M0 provider config and TUI foundations#52
Vasanthdev2004 merged 3 commits into
mainfrom
feat/go-m0-runtime-unify

Conversation

@Vasanthdev2004

@Vasanthdev2004 Vasanthdev2004 commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Make internal/zeroruntime the canonical Go provider/message/event contract and route the Go agent loop through it.
  • Add a stdlib OpenAI-compatible streaming provider with SSE parsing, tool-call buffering, usage parsing, and redacted provider errors.
  • Add Go provider/config resolution foundations for layered config, env fallback, provider command JSON, normalization, and secret redaction.
  • Add the first reusable Bubble Tea TUI shell package without CLI routing yet.

Validation

  • go test ./...
  • bun run typecheck
  • bun test ./tests --timeout 15000 — 279 pass, 0 fail
  • bun run build
  • bun run smoke:build
  • bun run build:go
  • bun run smoke:go

Notes

  • Three worker subagents implemented the OpenAI provider, config resolver, and TUI package in parallel with disjoint write scopes.
  • Artifact smoke checks were run sequentially because Bun and Go build scripts both write zero.exe on Windows.
  • The TUI package is intentionally not wired to CLI startup yet; the next PR can route no-arg zero to tui.Run once this foundation lands.

Summary by CodeRabbit

  • New Features

    • Interactive terminal UI with slash commands and a streaming assistant transcript.
    • New OpenAI-compatible streaming provider and ability to load provider config via external commands.
    • Runtime streaming callbacks to observe incremental text and usage.
  • Refactor

    • Stream and tool-call handling reworked to unify runtime types and simplify collection.
  • Bug Fixes / Reliability

    • Improved config resolution, secret redaction, and more robust process termination.
  • Tests

    • Expanded unit and integration tests for streaming, tooling, config, and TUI behaviors.

@Vasanthdev2004 Vasanthdev2004 marked this pull request as ready for review June 4, 2026 10:55
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Zero automated PR review

Verdict: No blockers found

Blockers

  • None found.

Validation

  • [pass] Diff hygiene: git diff --check
  • [pass] Typecheck: bun run typecheck
  • [pass] Tests: bun run test
  • [pass] Build: bun run build
  • [pass] Smoke build: bun run smoke:build

Scope

Head: 2a59105a0d6c
Changed files (27): go.mod, go.sum, internal/agent/loop.go, internal/agent/loop_test.go, internal/agent/types.go, internal/cli/app.go, internal/config/command.go, internal/config/command_test.go, internal/config/process_posix.go, internal/config/process_windows.go, internal/config/redact.go, internal/config/resolver.go, and 15 more

This deterministic review checks validation status and basic diff hygiene. A human reviewer still owns product judgment and design quality.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fd653fdb-35e8-4555-863d-f5427fe49cd5

📥 Commits

Reviewing files that changed from the base of the PR and between 085708d and 2a59105.

📒 Files selected for processing (10)
  • internal/config/resolver.go
  • internal/config/resolver_test.go
  • internal/config/types.go
  • internal/providers/openai/provider.go
  • internal/providers/openai/provider_test.go
  • internal/providers/openai/tool_state.go
  • internal/tui/model.go
  • internal/tui/model_test.go
  • internal/zeroruntime/helpers.go
  • internal/zeroruntime/provider_test.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • internal/zeroruntime/provider_test.go
  • internal/providers/openai/tool_state.go
  • internal/config/resolver_test.go
  • internal/config/resolver.go
  • internal/config/types.go
  • internal/providers/openai/provider_test.go
  • internal/zeroruntime/helpers.go
  • internal/tui/model.go

Walkthrough

This PR migrates agent types and streaming to internal/zeroruntime, adds CollectStreamWithOptions with live callbacks, updates the agent run loop to use zeroruntime collection and tool-definition mapping, implements an OpenAI-compatible streaming provider, extends configuration resolution and provider-command loading (with redaction and platform termination), and adds a Bubble Tea TUI with tests.

Changes

Zeroruntime Type and Stream Contract

Layer / File(s) Summary
Type aliases and runtime contract
internal/agent/types.go
Agent exports (Message, Provider, ToolCall, Usage) are now aliases to zeroruntime types.
Stream event type naming
internal/zeroruntime/types.go, internal/zeroruntime/provider_test.go
Tool-call lifecycle event string values changed from underscore to hyphen delimiters; tests validate the contract.
Collector with callbacks
internal/zeroruntime/helpers.go, internal/zeroruntime/provider_test.go
Added CollectOptions and CollectStreamWithOptions supporting OnText/OnUsage callbacks and centralized pending tool-call buffering.

Agent Loop Integration and Tool Schema

Layer / File(s) Summary
Run loop and stream collection
internal/agent/loop.go, internal/agent/loop_test.go
Run seeds messages via zeroruntime.SeedMessages, builds zeroruntime.CompletionRequest, collects stream with CollectStreamWithOptions, checks collected errors/context, appends assistant message, and executes/appends tool-call results; tests updated for zeroruntime events and usage.
Tool advertisement schema mapping
internal/agent/loop.go
toolDefinitions now returns []zeroruntime.ToolDefinition; schemaToRuntimeMap / propertyToRuntimeMap convert registry schemas to runtime JSON shapes and properties.

Providers, Config, CLI, and TUI

Layer / File(s) Summary
OpenAI-compatible provider
internal/providers/openai/*
New provider mapping to OpenAI chat completions with SSE parsing, tool-call buffering/state (tool_state.go), error classification/redaction, request mapping, and extensive streaming/tool/error tests.
CLI/offline and mock providers
internal/cli/app.go, internal/agent/loop_test.go
Offline/mock providers updated to use zeroruntime.CompletionRequest / zeroruntime.StreamEvent; tests updated for message roles, text deltas, usage (including CachedInputTokens), tool-call flows, and advertised tool schema.
Config resolution and provider command
internal/config/*
New resolver with layered precedence, provider-command loader with timeout/termination and stderr redaction, platform-specific process helpers, secret redaction utilities, and tests covering precedence, validation, timeouts, and redaction.
Terminal UI
internal/tui/*
Added Bubble Tea TUI model, transcript reducer, options, run entrypoint, and tests verifying commands, rendering, prompt flow, cancellations, and run-id staleness handling.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Gitlawb/zero#50: Introduces SeedMessages and foundational zeroruntime helpers used here.
  • Gitlawb/zero#51: Prior agent loop refactor whose collectTurn/buildToolCalls helpers are replaced by this PR.

Suggested reviewers

  • anandh8x
  • gnanam1990
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.35% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding provider config and TUI foundations, which aligns with the PR objectives of config resolution, OpenAI provider, and Bubble Tea TUI package.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/go-m0-runtime-unify

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/zeroruntime/helpers.go (1)

40-42: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Surface cancellation in collected error state.

This branch returns partial output with an empty Error, so cancellation can be interpreted as success by callers that only inspect CollectedStream.Error.

💡 Proposed fix
 		case <-ctx.Done():
 			appendOpenToolCalls(&collected, toolCallOrder, pendingToolCalls)
+			collected.Error = ctx.Err().Error()
 			return collected
🤖 Prompt for 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.

In `@internal/zeroruntime/helpers.go` around lines 40 - 42, The cancellation
branch currently returns a partial CollectedStream (variable collected) with no
error, which can be misinterpreted as success; update the ctx.Done() branch in
the function containing appendOpenToolCalls(&collected, toolCallOrder,
pendingToolCalls) so that before returning you set collected.Error (or the
appropriate error field on the CollectedStream) to ctx.Err() (or a
wrapped/contextualized error indicating cancellation) to surface cancellation to
callers; ensure you only mutate the existing collected struct and keep
appendOpenToolCalls usage unchanged.
🤖 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.

Outside diff comments:
In `@internal/zeroruntime/helpers.go`:
- Around line 40-42: The cancellation branch currently returns a partial
CollectedStream (variable collected) with no error, which can be misinterpreted
as success; update the ctx.Done() branch in the function containing
appendOpenToolCalls(&collected, toolCallOrder, pendingToolCalls) so that before
returning you set collected.Error (or the appropriate error field on the
CollectedStream) to ctx.Err() (or a wrapped/contextualized error indicating
cancellation) to surface cancellation to callers; ensure you only mutate the
existing collected struct and keep appendOpenToolCalls usage unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bac90b9e-710e-4168-8716-665ca1933622

📥 Commits

Reviewing files that changed from the base of the PR and between b8e194d and 0819ef3.

📒 Files selected for processing (7)
  • internal/agent/loop.go
  • internal/agent/loop_test.go
  • internal/agent/types.go
  • internal/cli/app.go
  • internal/zeroruntime/helpers.go
  • internal/zeroruntime/provider_test.go
  • internal/zeroruntime/types.go

@Vasanthdev2004 Vasanthdev2004 changed the title feat: unify Go runtime provider contracts feat: add Go M0 provider config and TUI foundations Jun 4, 2026

@anandh8x anandh8x left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's good

  • zeroruntime is now the single source of truth. agent.Message, agent.Provider, agent.ToolCall, agent.Usage are all type aliases for zeroruntime.* (internal/agent/types.go:8-12), and the loop is built on zeroruntime.SeedMessages + zeroruntime.CollectStreamWithOptions (internal/agent/loop.go:36-50). Stream event names were also normalised to kebab-case (internal/zeroruntime/types.go:18-20) and locked behind a name-matches-contract test (TestStreamEventNamesMatchProviderContract, internal/zeroruntime/provider_test.go:46-58). The collectTurn / pendingToolCall / buildToolCalls triplet from #51 has been replaced by a single, well-tested collector with ensurePendingToolCall handling missing-Start resilience.
  • OpenAI provider is built for real SSE. provider.stream (internal/providers/openai/provider.go:42-116) uses bufio.Scanner with a 16 MB max line buffer, a private toolState that buffers per-index tool calls until both id and name arrive, and emits the correct start → delta(s) → end → done sequence. Three targeted tests prove the ordering (TestStreamCompletionBuffersToolArgsUntilIDAndNameArrive, TestStreamCompletionTracksMultipleToolCallsByIndex, TestStreamCompletionDoesNotHangOnEOFWithOpenToolCall). Usage parsing handles prompt_tokens_details.cached_tokens, and the sendEvent helper drops non-error events on ctx.Done (with a non-blocking last-chance send for errors), so cancellation can't deadlock the consumer.
  • Error classification + redaction is layered. classifyError (provider.go:159-172) maps 401/403/429/4xx to auth error:, rate limit error:, provider request error: prefixes; everything else is provider error:. redact does a literal replace of the configured apiKey and a word-by-word sweep for Bearer <token> (tested in TestStreamCompletionClassifiesHTTPErrorsAndRedactsToken). Same redaction discipline is applied in internal/config/redact.go (regexes for sk-..., api[_-]?key=, Bearer ...) and exercised by TestResolveRedactsSecretsFromErrors / TestLoadProviderCommandFailureIncludesExitAndRedactsOutput.
  • Config resolver is genuinely layered and well-typed. Resolve (internal/config/resolver.go:8-46) walks UserConfigPathProjectConfigPathProviderCommand → env → overrides in that order, with mergeProfile filling only empty fields so later layers additively extend. ProviderProfile.UnmarshalJSON accepts both camelCase (apiKey, model) and snake_case (api_key, model_id, base_url) field names (internal/config/types.go:39-65), so a TypeScript-style config continues to parse. Env fallback (OPENAI_API_KEY / OPENAI_BASE_URL / OPENAI_MODEL / ZERO_PROVIDER) auto-promotes a custom base_url to ProviderKindOpenAICompatible (resolver.go:81-93), and the same isOfficialOpenAIBaseURL check is applied both ways so an openai-compatible provider can't accidentally point at the official URL.
  • Provider command is process-managed and bounded. LoadProviderCommand runs the configured shell command with a 5-second time.NewTimer timeout, kills the process group on POSIX (Setpgid: true + syscall.Kill(-pid, SIGKILL), internal/config/process_posix.go) or the whole process tree on Windows (taskkill /T /F, internal/config/process_windows.go). Test TestLoadProviderCommandTimeout asserts the wall-clock elapsed stays under 7 s. The shell invocation pre-calls Windows commands that start with a leading quote (command.go:53-56), and the stderr output is funnelled through redactSecrets before being included in the error.
  • TUI is a clean Bubble Tea shell. model.go follows the Elm pattern with a transcript reducer (internal/tui/transcript.go:48-71) that produces a new slice on every action, a separate parseCommand for /help /clear /exit /tools /permissions (internal/tui/commands.go:21-46), and an OnToolCall / OnToolResult wrapper in runAgent (internal/tui/model.go:158-181) that records rows without breaking the user's callbacks. Esc clears the input + pending flag; Ctrl+C quits via tea.Quit. The PR body is honest that the TUI isn't wired to CLI startup yet — the next PR can route no-arg zero to tui.Run once the resolver+provider wiring lands.
  • Agent loop got simpler with the unification. loop.go:23-99 is now ~80 lines instead of 100, and the test file grew (TestRunAdvertisesRuntimeToolDefinitions, loop_test.go:108-149) to cover the tools.Schemamap[string]any conversion via schemaToRuntimeMap / propertyToRuntimeMap (loop.go:147-184). This is a worthwhile test — without it, a regression in the schema mapper would silently strip tool descriptions before the provider sees them.
  • Three test files give the resolver / command / provider serious coverage. resolver_test.go (7 tests) covers layer precedence, active profile selection, env fallback, official-URL normalisation, validation errors, and redaction. command_test.go (5 tests) covers success, exit-code-with-redaction, timeout wall-clock, invalid JSON, and missing model. provider_test.go (11 tests) covers request shape, model requirement, empty auth/tools, text+usage+done, tool-args buffering, multi-tool tracking, error classification, malformed JSON, context cancel, and EOF-without-DONE.

Observations (non-blocking)

  1. CodeRabbit's nitpick is correct: CollectStreamWithOptions doesn't surface cancellation. internal/zeroruntime/helpers.go:40-42 returns collected with Error == "" when ctx.Done() fires, so a caller that only inspects CollectedStream.Error interprets a cancelled stream as success. One-line fix: collected.Error = ctx.Err().Error() before the appendOpenToolCalls + return. Worth addressing in this PR before it ships — the agent loop's check on collected.Error != "" (internal/agent/loop.go:46-50) would then propagate the cancellation as a proper error to the caller, and the TUI / zero exec CLI would render a useful "context canceled" line instead of an empty FinalAnswer.

  2. The OpenAI provider redact is approximate for Bearer tokens. It splits on whitespace and looks for a word equal-folding to Bearer (with optional trailing :), then replaces the next word. That works for Authorization: Bearer sk-... in normal log lines, but a token like Bearer\nsk-... (rare but possible) or a bearer header value buried mid-string would slip through. For a v1 this is fine; a follow-up using a single regex pass ((?i)\bBearer\s+\S+) would be tighter.

  3. redact.go's prefix preservation has a gap. The prefix list is {"apiKey=", "api_key=", "api-key=", "Bearer "}, but the regex captures api[_-]?key followed by a delimiter (which also matches api key=... with a space). If the input is api key=secret, the regex matches but no prefix in the list matches, so the match is fully replaced with [REDACTED] and the original api key= is lost. Adding "api key=" to the prefix list closes it.

  4. Provider command timeout is a hard-coded 5 s. LoadProviderCommand (internal/config/command.go:10) uses a package constant. A custom provider that does any IO (e.g. fetches a token) could exceed that. Worth making it configurable via ResolveOptions.ProviderCommandTimeout (or similar) so users on slow systems don't have to fork the code.

  5. The TUI doesn't show running tool calls. model.runAgent (internal/tui/model.go:158-181) records OnToolCall rows into a local rows slice and only flushes them when the agent returns. While a long-running tool (e.g. bash with the full 10-minute timeout) is in flight, the user sees assistant: working... and no indication of which tool is running. The fix is to surface the rows incrementally: either via intermediate agentResponseMsg flushes or by switching the tea.Cmd to a stream that yields after each tool. For an M0 TUI this is acceptable; flag it before the TUI replaces zero exec as the default entry point.

  6. TUI transcript has no upper bound. A 100-turn session would append hundreds of rows; View() rebuilds the full string on every render, and the row slice grows unboundedly. Bubble Tea's viewport component handles scrollback, but the current model.go doesn't use one. A max-row cap (e.g. 1000) with truncation, or a viewport migration, is the right next step.

  7. runAgent wraps the user's OnToolCall / OnToolResult callbacks, but the full ToolResult.Output is rendered into a rowToolResult. A read_file of a 10 MB log file would dump 10 MB into a single row, which then has to fit in the transcript and re-render on every keystroke. The same row-cap fix in #6 would help, or the TUI could truncate the rendered Output to a fixed number of bytes with a … (truncated) suffix and the user could expand it via a hotkey.

  8. applyEnv overrides the activeProvider from OPENAI_* env. When only OPENAI_API_KEY is set (without OPENAI_BASE_URL or OPENAI_MODEL), the code returns early (resolver.go:79-83), which is correct. But when an env profile is created, it has Name = cfg.ActiveProvider — i.e. it inherits whatever the user set via ZERO_PROVIDER or earlier layers. If the user has a custom-named provider in their config file and then sets OPENAI_API_KEY in the environment, the env key gets bolted onto the custom-named provider rather than creating a separate openai profile. Probably the right call, but worth a comment in the code so the merge behaviour is explicit.

  9. No migration note for the kebab-case event rename. #47#51 used tool_call_start (snake_case) and #52 switches to tool-call-start (kebab-case). Any third-party provider or test that was constructing StreamEvent{Type: "tool_call_start", ...} will break. The test in TestStreamEventNamesMatchProviderContract will catch a future rename, but a one-line note in the PR description (or a CHANGELOG entry) would be useful since the rename spans three event types and the previous event names were in the public zeroruntime types.

  10. offlineProvider in internal/cli/app.go still uses zeroruntime.MessageRoleUser — confirmed in the diff. The CLI's runExec now receives a real resolver-built provider, so offlineProvider is dead code in this PR (the CLI doesn't wire it up). A quick git grep check or a //nolint will confirm whether anything still references it; if not, removing it (or moving it under a //go:build offline_test tag) is a clean follow-up.

  11. go.mod toolchain bump to go1.24.13 is fine, but worth checking downstream. Anyone building Zero on a Go version < 1.24.2 (i.e. before this PR) will now get a go.mod toolchain mismatch. The toolchain directive is the right answer, but a one-line note in the PR description ("requires Go 1.24.2+") and a CI matrix pin to 1.24.2 minimum would make the floor explicit.

No blockers. The CodeRabbit nitpick (#1) is the one I'd want to see fixed before merge — it's a one-line change that closes a real cancellation-surfaces-as-success bug. The rest are correctness / UX polish for the follow-up PRs (TUI wiring, real-provider command timeout, transcript scrollback).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 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 `@internal/config/resolver.go`:
- Around line 67-69: Trim src.ActiveProvider before checking emptiness and only
copy a non-empty trimmed value into dst.ActiveProvider: replace the current if
src.ActiveProvider != "" { dst.ActiveProvider =
strings.TrimSpace(src.ActiveProvider) } with code that does v :=
strings.TrimSpace(src.ActiveProvider); if v != "" { dst.ActiveProvider = v } and
make the same change for the second occurrence around the src.ActiveProvider
handling (lines ~158-160) so whitespace-only values no longer overwrite a valid
dst.ActiveProvider.

In `@internal/config/types.go`:
- Around line 77-79: The current assignments (e.g., profile.BaseURL =
strings.TrimSpace(firstNonEmpty(raw.BaseURL, raw.BaseURLSnake))) pass untrimmed
raw fields into firstNonEmpty so whitespace-only values can win over valid
aliases; change to trim each candidate before selecting the first non-empty one
(e.g., call strings.TrimSpace on raw.BaseURL and raw.BaseURLSnake before calling
firstNonEmpty) and apply the same change for APIKey/APIKeySnake and
Model/ModelID so that firstNonEmpty operates on trimmed strings rather than on
potential whitespace-only inputs.

In `@internal/providers/openai/provider.go`:
- Line 107: Replace the plain defer response.Body.Close() with an explicit
deferred closure that handles the Close() error to satisfy errcheck; e.g. after
the HTTP call that assigns response, use defer func() { if err :=
response.Body.Close(); err != nil { /* log or ignore intentionally */ } }() so
the returned error is consumed (reference: response.Body.Close in
internal/providers/openai/provider.go).

In `@internal/providers/openai/tool_state.go`:
- Around line 78-87: The closeOpen finalization loop should skip any tool calls
that lack a name to avoid emitting a StreamEventToolCallStart with an empty
ToolName; update the guard around the call so that it also checks call.name ==
"" (or add an explicit check before sending the start event) and continue when
the name is empty, referencing the same loop where call, call.started and
sendEvent(ctx, events, zeroruntime.StreamEvent{...}) are used to prevent
emitting a start event for nameless calls.

In `@internal/tui/model.go`:
- Around line 102-105: The Esc key handler clears input and unsets m.pending
without cancelling an active agent run, and the prompt-start code (e.g., the
method that begins a run—look for startPrompt/runPrompt or where a new prompt
run is initiated) doesn’t guard against an existing pending run; modify KeyEsc
handling to signal cancellation of the active run (e.g., set/close a cancel
channel or cancel a context tied to the current run) instead of just clearing
m.pending, and update the prompt-start path to check m.pending (or attempt to
acquire a run lock) before starting a new run so it returns early when a run is
already in progress; ensure the run sets m.pending = true at start and clears it
only when the run fully terminates (or on cancel) to prevent interleaved runs.
- Around line 210-215: In runAgent the options.OnToolResult handler appends a
transcriptRow using result.Status directly, which can be empty; change the
handler (options.OnToolResult closure) to normalize an empty status to "ok"
before formatting (e.g. if result.Status == "" then use "ok") so the
transcriptRow for rowToolResult always shows a consistent status value.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 000ed0cd-446f-4640-a069-d1051486e3c9

📥 Commits

Reviewing files that changed from the base of the PR and between 0819ef3 and 085708d.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (19)
  • go.mod
  • internal/config/command.go
  • internal/config/command_test.go
  • internal/config/process_posix.go
  • internal/config/process_windows.go
  • internal/config/redact.go
  • internal/config/resolver.go
  • internal/config/resolver_test.go
  • internal/config/types.go
  • internal/providers/openai/provider.go
  • internal/providers/openai/provider_test.go
  • internal/providers/openai/tool_state.go
  • internal/providers/openai/types.go
  • internal/tui/commands.go
  • internal/tui/model.go
  • internal/tui/model_test.go
  • internal/tui/options.go
  • internal/tui/run.go
  • internal/tui/transcript.go
✅ Files skipped from review due to trivial changes (2)
  • internal/tui/options.go
  • internal/tui/model_test.go

Comment thread internal/config/resolver.go Outdated
Comment thread internal/config/types.go
Comment thread internal/providers/openai/provider.go Outdated
Comment thread internal/providers/openai/tool_state.go Outdated
Comment thread internal/tui/model.go
Comment thread internal/tui/model.go
@Vasanthdev2004

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants