Skip to content

Conversation

@ericcurtin
Copy link
Contributor

@ericcurtin ericcurtin commented Oct 15, 2025

Much more fully featured readline-like implementation which advanced keyboard usage.

Summary by Sourcery

Provide an enhanced interactive "run" prompt by introducing a custom readline-like implementation with advanced keyboard shortcuts, multi-line input markers, history and command handling, while falling back to a basic input mode when not running in a terminal

New Features:

  • Add generateInteractiveWithReadline for an advanced interactive mode with custom prompts, multi-line paste support, history and keyboard shortcuts
  • Add generateInteractiveBasic as a fallback interactive mode for non-terminal environments
  • Implement cmd/cli/readline package to manage terminal raw mode, input buffering, history persistence and cross-platform terminal control

Enhancements:

  • Replace inline interactive loop in run command with terminal detection and modular interactive handlers
  • Introduce slash commands (/help, /?, /bye, /exit) and unknown command feedback in interactive sessions
  • Remove outdated static startup message from CLI docs to reflect new prompt behavior

Build:

  • Update go.mod to adjust containerd/containerd and golang.org/x/crypto versions and add dependencies for readline functionality

Documentation:

  • Remove old example lines about "Interactive chat mode started" in README and reference docs

Copilot AI review requested due to automatic review settings October 15, 2025 03:17
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Oct 15, 2025

Reviewer's Guide

This PR replaces the basic scanner-based chat prompt with a fully featured readline-like interface by integrating a new 'readline' package, adding enhanced interactive and fallback modes in run.go, adjusting dependencies to support the new package, and updating documentation to reflect the changes.

Sequence diagram for enhanced interactive chat input with readline

sequenceDiagram
    actor User
    participant CLI
    participant Readline
    participant DesktopClient
    User->>CLI: Start interactive chat
    CLI->>Readline: Initialize readline prompt
    alt Readline initialization fails
        Readline-->>CLI: Error
        CLI->>CLI: Fallback to basic input
    else Readline initialized
        Readline-->>CLI: Ready for input
        loop For each user input
            User->>Readline: Enter message (supports advanced editing)
            Readline->>CLI: Return input line
            CLI->>DesktopClient: chatWithMarkdown(userInput)
            DesktopClient-->>CLI: Response
            CLI->>User: Display response
        end
    end
Loading

Class diagram for new readline package types

classDiagram
    class Prompt {
        +string Prompt
        +string AltPrompt
        +string Placeholder
        +string AltPlaceholder
        +bool UseAlt
        +prompt() string
        +placeholder() string
    }
    class Buffer {
        +int DisplayPos
        +int Pos
        +arraylist.List~rune~ Buf
        +arraylist.List~bool~ LineHasSpace
        +Prompt* Prompt
        +int LineWidth
        +int Width
        +int Height
        +Add(r rune)
        +Remove()
        +Delete()
        +MoveLeft()
        +MoveRight()
        +MoveLeftWord()
        +MoveRightWord()
        +MoveToStart()
        +MoveToEnd()
        +ClearScreen()
        +Replace(r []rune)
        +String() string
        +IsEmpty() bool
    }
    class History {
        +arraylist.List~string~ Buf
        +bool Autosave
        +int Pos
        +int Limit
        +string Filename
        +bool Enabled
        +Add(s string)
        +Prev() string
        +Next() string
        +Size() int
        +Save() error
        +Clear()
        +Compact()
    }
    class Terminal {
        +chan rune outchan
        +bool rawmode
        +any termios
        +Read() (rune, error)
    }
    class Instance {
        +Prompt* Prompt
        +Terminal* Terminal
        +History* History
        +bool Pasting
        +Readline() (string, error)
        +HistoryEnable()
        +HistoryDisable()
    }
    Prompt <.. Buffer
    Prompt <.. Instance
    Terminal <.. Instance
    History <.. Instance
Loading

Class diagram for updated run.go interactive mode functions

classDiagram
    class RunCommand {
        +generateInteractiveWithReadline(cmd, desktopClient, backend, model, apiKey)
        +generateInteractiveBasic(cmd, desktopClient, backend, model, apiKey)
        +readMultilineInput(cmd, scanner)
    }
    class Readline {
        +New(Prompt) (*Instance, error)
        +Instance.Readline() (string, error)
    }
    RunCommand --> Readline: uses
    RunCommand --> DesktopClient: uses
    RunCommand --> chatWithMarkdown: calls
Loading

File-Level Changes

Change Details Files
Integrate enhanced interactive prompt with readline support
  • Import and initialize the readline module in run.go
  • Add generateInteractiveWithReadline and generateInteractiveBasic functions
  • Modify newRunCmd to select readline or basic mode based on terminal detection
  • Remove the old inline scanner-based loop
cmd/cli/commands/run.go
Add new readline package for advanced terminal input
  • Implement Buffer, Prompt, Terminal, Instance, History, and types modules
  • Include platform-specific termios handling (Unix and Windows)
  • Support editing commands: cursor movement, word navigation, history, multiline, and paste
cmd/cli/readline/buffer.go
cmd/cli/readline/readline.go
cmd/cli/readline/history.go
cmd/cli/readline/types.go
cmd/cli/readline/term_windows.go
cmd/cli/readline/term.go
cmd/cli/readline/term_linux.go
cmd/cli/readline/term_bsd.go
cmd/cli/readline/readline_unix.go
cmd/cli/readline/errors.go
cmd/cli/readline/readline_windows.go
Adjust module dependencies to support readline functionality
  • Update root go.mod (containerd, golang.org/x/crypto versions, add go-fuzz-headers)
  • Add github.com/emirpasic/gods/v2 and go-runewidth to cmd/cli/go.mod
  • Remove obsolete indirect entries
go.mod
cmd/cli/go.mod
Update documentation to remove outdated instructions
  • Remove obsolete "Interactive chat mode started..." messages
  • Align examples in README and reference docs with new prompt behavior
cmd/cli/README.md
cmd/cli/docs/reference/docker_model_run.yaml
cmd/cli/docs/reference/model_run.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ericcurtin, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly upgrades the interactive prompt experience for the run command by integrating a new, custom readline-like implementation. This enhancement provides users with a much more powerful and intuitive command-line interface, featuring advanced keyboard shortcuts for text manipulation, robust multiline input handling, and persistent command history. The change aims to improve user productivity and interaction fluidity when using the run command, while also ensuring a seamless fallback to a basic input mode for non-terminal environments or in case of initialization issues.

Highlights

  • Advanced Readline Implementation: Introduces a new readline package for the run command, offering a more fully-featured interactive prompt with advanced terminal capabilities.
  • Enhanced Keyboard Usage: Provides a wide array of advanced keyboard shortcuts for efficient text editing, cursor navigation (e.g., Ctrl+a, Ctrl+e, Alt+b, Alt+f), and deletion operations (e.g., Ctrl+k, Ctrl+u, Ctrl+w).
  • Multiline Input Support: Improves the handling of multiline messages, including support for bracketed paste functionality and clearer prompts for extended input.
  • Command History: Implements persistent command history, allowing users to easily navigate and reuse previous inputs with arrow keys. History can be disabled via the DOCKER_MODEL_NOHISTORY environment variable.
  • Graceful Fallback: Automatically reverts to a basic interactive input mode if the advanced readline features cannot be initialized or if the environment is not a terminal, ensuring continued functionality.
  • Dependency Updates: Adds new Go dependencies (github.com/emirpasic/gods/v2, github.com/mattn/go-runewidth, golang.org/x/sys) to support the new readline functionality and updates existing ones.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • Several loops (e.g. in Buffer.DisplaySize and History.Save) use “for … range Size()” where Size() returns an int; update these to ordinary for-loops (for i := 0; i < Size(); i++) so they actually iterate over elements.
  • The new readline package is very large and mixes buffer management, terminal control, and history in one module—consider breaking it into smaller subpackages or files to improve readability and maintainability.
  • generateInteractiveWithReadline and generateInteractiveBasic share similar chat and multiline-input handling logic; extract common functionality to reduce duplication and make the flow more DRY.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Several loops (e.g. in Buffer.DisplaySize and History.Save) use “for … range Size()” where Size() returns an int; update these to ordinary for-loops (for i := 0; i < Size(); i++) so they actually iterate over elements.
- The new readline package is very large and mixes buffer management, terminal control, and history in one module—consider breaking it into smaller subpackages or files to improve readability and maintainability.
- generateInteractiveWithReadline and generateInteractiveBasic share similar chat and multiline-input handling logic; extract common functionality to reduce duplication and make the flow more DRY.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR introduces a fully-featured readline-like implementation to replace the basic input handling in the CLI. The implementation adds advanced keyboard usage support, history management, multi-line input handling, and platform-specific terminal control.

  • Implements cross-platform terminal control with raw mode support for enhanced keyboard input
  • Adds readline functionality with history, cursor movement, and line editing features
  • Integrates the new readline implementation into the interactive chat mode

Reviewed Changes

Copilot reviewed 17 out of 19 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
go.mod Updates dependencies and adds new indirect dependencies
cmd/cli/readline/*.go New readline package implementing terminal control, input buffer management, history, and cross-platform support
cmd/cli/go.mod Adds new direct dependencies for readline functionality
cmd/cli/commands/run.go Replaces basic input with enhanced readline-based interactive mode
cmd/cli/docs/reference/*.md Removes outdated "Interactive chat mode started" message from documentation
cmd/cli/README.md Updates example to remove the outdated startup message

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link
Contributor

@gemini-code-assist gemini-code-assist 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

This pull request introduces a sophisticated readline-like implementation for the interactive run prompt, significantly improving the user experience with features like command history, advanced keyboard shortcuts, and better multi-line input handling. The implementation is extensive, adding a new readline package with cross-platform support for terminal operations.

My review focuses on several areas:

  • Critical bugs: I found a potential panic in command parsing and a significant security concern with a downgraded cryptography library.
  • High-severity issues: I've pointed out a bug in history saving that could lead to data loss, and risks associated with using an alpha dependency and another downgraded dependency.
  • Medium-severity issues: I've noted areas for improvement in code robustness, efficiency, and design clarity within the new readline package.

Overall, this is a great feature addition. Addressing the critical and high-severity issues is strongly recommended before merging.

@ericcurtin ericcurtin force-pushed the new-run-prompt branch 2 times, most recently from e5bc540 to 772df83 Compare October 15, 2025 03:29
Copilot AI review requested due to automatic review settings October 15, 2025 03:29
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 16 out of 17 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

cmd/cli/readline/buffer.go:1

  • The magic number 8 for tab size should be defined as a named constant to improve maintainability and make it configurable if needed.
package readline

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Much more fully featured readline-like implementation which advanced
keyboard usage.

Signed-off-by: Eric Curtin <[email protected]>
@p1-0tr
Copy link

p1-0tr commented Oct 15, 2025

Seems we may be heading toward a good moment to revive - docker/model-cli#144 ?

@ericcurtin
Copy link
Contributor Author

Genuinely I'm happy to continue here, we don't need 65k lines of code for a simple feature like this. Have you tested both to see what the UX is like?

@p1-0tr
Copy link

p1-0tr commented Oct 15, 2025

Genuinely I'm happy to continue here, we don't need 65k lines of code for a simple feature like this. Have you tested both to see what the UX is like?

IIRC most of that change was vendor code.

Edit: yep, on our side there is ~1k lines of code in that PR

@ericcurtin
Copy link
Contributor Author

ericcurtin commented Oct 15, 2025

Genuinely I'm happy to continue here, we don't need 65k lines of code for a simple feature like this. Have you tested both to see what the UX is like?

IIRC most of that change was vendor code.

Did you test this implementation vs that one? The difference is drastic.

fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, " Ctrl + l Clear the screen")
fmt.Fprintln(os.Stderr, " Ctrl + c Stop the model from responding")
fmt.Fprintln(os.Stderr, " Ctrl + d Exit (/bye)")
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
fmt.Fprintln(os.Stderr, " Ctrl + d Exit (/bye)")
fmt.Fprintln(os.Stderr, " Ctrl + d Delete the character under the cursor. If the input line is empty, exit the chat (/bye)")

Copy link
Contributor

Choose a reason for hiding this comment

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

I just tried and it's actually the same as /bye

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This makes sense! Ctrl-d is exit prompt in all shells, I guess you can't type /bye mid-prompt which this is highlighting.

@p1-0tr
Copy link

p1-0tr commented Oct 15, 2025

Did you test this implementation vs that one? The difference is drastic.

Not yet, I wasn't assuming they do the same thing. More that if we are aiming for a richer CLI interface we could benefit from using sth like bubbletea.

@ericcurtin
Copy link
Contributor Author

Did you test this implementation vs that one? The difference is drastic.

Not yet, I wasn't assuming they do the same thing. More that if we are aiming for a richer CLI interface we could benefit from using sth like bubbletea.

The bubbletea PR is badly broken, tried bubbletea and huh... Not impressed

@ericcurtin
Copy link
Contributor Author

Genuinely I'm happy to continue here, we don't need 65k lines of code for a simple feature like this. Have you tested both to see what the UX is like?

IIRC most of that change was vendor code.

Edit: yep, on our side there is ~1k lines of code in that PR

It's still important to stay lean binary size and dependancies are not 100% free, still require maintenance, large dependancies increase the chance of CVE's appearing.

@p1-0tr
Copy link

p1-0tr commented Oct 15, 2025

TBH I don't think binary size should differ that much (plus it's golang, so the lean binary ship has long sailed 🙈). But if we don't believe bubble tea fits our bill, that's fair enough for me.

Copy link
Contributor

@ilopezluna ilopezluna left a comment

Choose a reason for hiding this comment

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

MHO, the UX in this PR is much better than what we currently have, so I vote to merge it. Once users benefit from the improved UX, we can focus on optimization.

In general, unless we find a blocker, I’m in favor of merging anything that improves the UX. There’s always time to optimize later.

fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, " Ctrl + l Clear the screen")
fmt.Fprintln(os.Stderr, " Ctrl + c Stop the model from responding")
fmt.Fprintln(os.Stderr, " Ctrl + d Exit (/bye)")
Copy link
Contributor

Choose a reason for hiding this comment

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

I just tried and it's actually the same as /bye

@ericcurtin
Copy link
Contributor Author

I think we should merge though because of better UX.

I do appreciate the issues we are finding though, I think we should fill up our issue tracker with these.

@ericcurtin ericcurtin merged commit c0ddc7a into main Oct 15, 2025
9 checks passed
@ericcurtin ericcurtin deleted the new-run-prompt branch October 15, 2025 10:32
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.

5 participants