Conversation
…1525) Fixes kagent-dev#1524 --------- Signed-off-by: Jesus Munoz <jesus.munoz@solo.io> Signed-off-by: n9te9 <ai.kanaria.ai@gmail.com>
## Summary - **PyJWT**: `>=2.8.0` → `>=2.12.0` — fixes CVE-2026-32597 (accepts unknown `crit` header extensions) - **pyOpenSSL**: `25.3.0` → `>=26.0.0` — fixes CVE-2026-27459 - **pyasn1**: `0.6.2` → `>=0.6.3` — fixes CVE-2026-30922 - **google.golang.org/grpc**: `v1.79.2` → `v1.79.3` — fixes CVE-2026-33186 (authorization bypass via missing leading slash in :path) - **kagent-tools** helm dep: `0.1.1` → `0.1.2` ## CVE Details | Package | CVE | Severity | Fixed In | |---------|-----|----------|----------| | google.golang.org/grpc | CVE-2026-33186 | CRITICAL | 1.79.3 | | PyJWT | CVE-2026-32597 | HIGH | 2.12.0 | | pyOpenSSL | CVE-2026-27459 | HIGH | 26.0.0 | | pyasn1 | CVE-2026-30922 | HIGH | 0.6.3 | ## Test plan - [ ] `uv sync` in Python workspace resolves without conflicts - [ ] `make -C python test` passes - [ ] `go mod tidy` succeeds with no diff - [ ] Trivy scan passes in CI 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: n9te9 <ai.kanaria.ai@gmail.com>
Signed-off-by: Dmytro Rashko <dmitriy.rashko@amdocs.com> Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io> Co-authored-by: Eitan Yarmush <eitan.yarmush@solo.io> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: n9te9 <ai.kanaria.ai@gmail.com>
Signed-off-by: n9te9 <ai.kanaria.ai@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces an isolated, experimental Bubble Tea–based TUI (k9s-inspired) behind a new CLI entrypoint to prototype a new navigation/layout architecture without impacting the existing session-first TUI.
Changes:
- Added
internal/experimental_tuiwith initial router (RootModel), an agent list screen, demo data/provider, and basic UI components (table, status, gauge). - Wired a new
experimental-tuiCobra command into the CLI (currently gated toENVIRONMENT=local). - Introduced initial domain models (
Agent,ModelProvider) to standardize data needed by views.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| go/core/cli/internal/experimental_tui/screen/root.go | Adds stack-based screen router for push/pop navigation. |
| go/core/cli/internal/experimental_tui/screen/agent_list.go | Adds initial agent list screen with keybindings and table rendering. |
| go/core/cli/internal/experimental_tui/domain/provider.go | Defines ModelProvider interface for model metadata/cost/context info. |
| go/core/cli/internal/experimental_tui/domain/agent.go | Adds Agent domain model and helper methods for metrics/labels. |
| go/core/cli/internal/experimental_tui/demo.go | Provides a demo ModelProvider implementation for mock rendering. |
| go/core/cli/internal/experimental_tui/component/table.go | Implements table rendering for agents (ID/name/status/context gauge). |
| go/core/cli/internal/experimental_tui/component/status.go | Adds (currently minimal) status badge rendering helper. |
| go/core/cli/internal/experimental_tui/component/guage.go | Adds context usage gauge renderer (note: filename typo). |
| go/core/cli/internal/experimental_tui/app.go | Adds Run() entrypoint to launch the experimental program with demo data. |
| go/core/cli/internal/cli/agent/run.go | Adds RunExperimentalTUI wrapper called from Cobra. |
| go/core/cli/cmd/kagent/main.go | Registers the new experimental-tui command (currently env-gated). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func Run() error { | ||
| m := screen.NewRootModel(screen.NewAgentListModel(demoAgents)) | ||
|
|
||
| p := tea.NewProgram(m) | ||
| if _, err := p.Run(); err != nil { | ||
| fmt.Printf("Error running program: %v", err) | ||
| os.Exit(1) | ||
| } |
There was a problem hiding this comment.
Run() returns an error but currently prints the error and calls os.Exit(1), which makes it hard for callers (and tests) to handle failures and also makes the return value misleading. Consider returning the p.Run() error instead of exiting, and let the Cobra command decide whether to os.Exit. Also consider using tea.WithAltScreen() (as the existing TUI does) to avoid leaving the UI rendered in the user’s terminal buffer.
| experimentaltui.Run() | ||
| return nil | ||
| } |
There was a problem hiding this comment.
RunExperimentalTUI ignores the error returned by experimentaltui.Run() and always returns nil. This will hide failures from the CLI command and makes the error handling in main.go ineffective; return the error from experimentaltui.Run() instead.
| experimentaltui.Run() | |
| return nil | |
| } | |
| return experimentaltui.Run() | |
| } |
| experimentalTuiCmd := &cobra.Command{ | ||
| Use: "experimental-tui", | ||
| Short: "Run the experimental TUI (for development/testing)", | ||
| Long: `Run the experimental TUI (for development/testing)`, | ||
| Run: func(cmd *cobra.Command, args []string) { | ||
| if err := cli.RunExperimentalTUI(cmd.Context(), runCfg); err != nil { | ||
| fmt.Fprintf(os.Stderr, "Error running experimental TUI: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
| }, | ||
| } | ||
|
|
||
| commands := []*cobra.Command{installCmd, uninstallCmd, invokeCmd, bugReportCmd, versionCmd, dashboardCmd, getCmd, initCmd, buildCmd, deployCmd, addMcpCmd, runCmd, mcp.NewMCPCmd(), envdoc.NewEnvCmd()} | ||
| if os.Getenv("ENVIRONMENT") == "local" { | ||
| commands = append(commands, experimentalTuiCmd) | ||
| } |
There was a problem hiding this comment.
The PR description says this command is a "hidden experimental-tui command", but the implementation conditionally registers it only when ENVIRONMENT == local. If the intent is "hidden but available", prefer always registering the command and marking it hidden via Cobra (e.g., Hidden: true) rather than gating it behind an environment variable.
| package component | ||
|
|
||
| import ( |
There was a problem hiding this comment.
File name appears to be misspelled (guage vs gauge). Renaming it to gauge.go will improve discoverability/searchability and avoid propagating the typo in future references.
| func (m RootModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | ||
| switch msg := msg.(type) { | ||
| case PushScreenMessage: | ||
| m.stack = append(m.stack, msg.Screen) | ||
| return m, msg.Screen.Init() | ||
| case PopScreenMessage: | ||
| if len(m.stack) > 1 { | ||
| m.stack = m.stack[:len(m.stack)-1] | ||
| } | ||
| return m, nil | ||
| } |
There was a problem hiding this comment.
The new stack-based router logic in RootModel.Update (push/pop behavior) is core navigation infrastructure but currently has no unit tests. Since this logic is easy to regress when new screens are added, add focused tests that assert push/pop ordering and that messages are forwarded to the top screen.
| func (a Agent) ContextUsageRate() float64 { | ||
| max := a.Provider.MaxContextTokens() | ||
| if max == 0 { | ||
| return 0 | ||
| } | ||
|
|
||
| current := float64(a.Provider.InputTokens() + a.Provider.OutputTokens()) | ||
| return current / float64(max) | ||
| } |
There was a problem hiding this comment.
Several methods (e.g., ContextUsageRate, TokenRatio, Model) dereference a.Provider without a nil check, so the zero-value Agent{} (or any agent built without setting Provider) will panic at runtime. Consider enforcing non-nil provider by construction (e.g., unexport Provider and require NewAgent), or make these methods nil-safe (return 0/"" when Provider is nil).
| statusBadge := agent.Status | ||
| if w := lipgloss.Width(string(statusBadge)); w > columnWidth.Status { | ||
| columnWidth.Status = w | ||
| } | ||
| gauge := RenderUsageGauge(agent.ContextUsageRate(), colGaugeWidth) | ||
| if w := lipgloss.Width(gauge); w > columnWidth.Gauge { | ||
| columnWidth.Gauge = w | ||
| } | ||
| } |
There was a problem hiding this comment.
columnWidth.Gauge is being updated using the rendered gauge string width, but later it is passed back into RenderUsageGauge as the bar width. This causes the gauge to grow (since the rendered string includes brackets/percent), breaking column alignment. Keep a separate fixed bar width (e.g., colGaugeWidth) and compute the gauge column width deterministically, or store bar width in columnWidth.Gauge and never overwrite it with lipgloss.Width(gauge).
Context
As discussed in #1494, we are revamping the CLI TUI to provide a more intuitive, k9s-inspired experience for agent management.
Since the existing TUI relies heavily on a session-first architecture, modifying it directly carries a high risk of breaking current functionality. To ensure a safe and iterative development process, this PR lays the foundation for the new TUI by introducing a clean-slate charmbracelet/bubbletea architecture behind a hidden experimental-tui command.
This initial PR focuses strictly on establishing the UI framework, state routing, and layout components using mock data, serving as a Proof of Concept (PoC) for the new UX paradigm before we wire it up to the Kubernetes client.
Changes
CLI Entrypoint: Added a hidden experimental-tui command to cmd/kagent/main.go to safely test the new TUI.
New Architecture: Created the internal/experimental_tui package to completely isolate the new implementation from the existing TUI codebase.
State Router: Implemented a stack-based navigation router (screen/root.go) capable of seamlessly pushing and popping different screen models.
Domain Models: Added Agent and ModelProvider structs/interfaces in domain/ to standardize the data structures required for the views.
UI Components: Built reusable lipgloss components in component/, including a responsive data table, status badges, and a context usage gauge.
Agent List Screen: Implemented the initial agent_list.go screen featuring vim-like keybindings (j/k to navigate, q to quit), currently populated with a DemoProvider to demonstrate the layout and interaction mechanics.