Skip to content

Conversation

@krissetto
Copy link
Contributor

Give it a try and let me know if this is worth a cleanup pass

⚠️ Ignore the code for now, plenty of vibes and it has not been thoroughly looked into.

  • Makes the sidebar agents section its own component (as an example for future refactoring of all sections)
  • Cleans up agent view in the sidebar to only show essential agent info (name and model)
  • Allows switching by clicking on the agent in the sidebar
  • Adds proper agent selection dialog with more info per agent and easier to read descriptions, including expandable toolset/tool list

Screencast

Screencast.From.2026-02-01.21-54-38.mp4

@krissetto krissetto changed the title Cleaner agent switching and rendering in the TUI Cleaner agent switching ux in the TUI Feb 1, 2026
@krissetto
Copy link
Contributor Author

/review

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Code Review Summary

Found 1 high-severity issue in the new toolset unwrapping logic that could cause a nil pointer panic.

Issues Found

  • HIGH: Nil pointer dereference risk in getToolsetDisplayName function

What Looks Good

  • Context cancellation properly handled in background goroutine
  • Mutex protection correctly implemented for cache access
  • Click handling and bounds checking are solid
  • Agent picker dialog implementation looks safe

return "think"
case "TodoTool", "todoTool":
return "todo"
case "FetchTool", "fetchTool":
Copy link
Contributor

Choose a reason for hiding this comment

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

Nil pointer dereference risk in toolset unwrapping

The unwrap loop assigns ts.Unwrap() directly to toolset without checking if the result is nil:

for range 5 {
    if ts, ok := toolset.(interface{ Unwrap() tools.ToolSet }); ok {
        toolset = ts.Unwrap()  // ← Could be nil
        continue
    }
    break
}

If any of the Unwrap() implementations (like filterTools.Unwrap(), replaceInstruction.Unwrap(), or toonTools.Unwrap()) return nil (which can happen if the wrapper was constructed with a nil ToolSet field), this will assign nil to toolset. While the subsequent type assertion won't panic directly, continuing with a nil toolset could cause issues.

Recommendation:
Add a nil check after unwrapping:

for range 5 {
    if ts, ok := toolset.(interface{ Unwrap() tools.ToolSet }); ok {
        if unwrapped := ts.Unwrap(); unwrapped != nil {
            toolset = unwrapped
            continue
        }
        break
    }
    break
}

@krissetto krissetto self-assigned this Feb 3, 2026
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.

1 participant