Skip to content

Commit bd8b746

Browse files
authored
fix: better error if attempting to run on Windows, refactor readline stuff (#221)
* fix: better error if attempting to run on Windows, refactored readline stuff into tabcomplete file * refactor: renamed tabcomplete file to readline * fix: removed remaining imports of readline outside of readline.py * test: fixed tests
1 parent 7f1ba2b commit bd8b746

File tree

4 files changed

+50
-39
lines changed

4 files changed

+50
-39
lines changed

gptme/chat.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import logging
33
import os
44
import re
5-
import readline
65
import sys
76
import termios
87
import urllib.parse
@@ -18,6 +17,7 @@
1817
from .logmanager import Log, LogManager, prepare_messages
1918
from .message import Message
2019
from .models import get_model
20+
from .readline import add_history
2121
from .tools import ToolUse, execute_msg, has_tool
2222
from .tools.base import ConfirmFunc
2323
from .tools.browser import read_url
@@ -228,7 +228,7 @@ def prompt_user(value=None) -> str: # pragma: no cover
228228
print("\nInterrupted. Press Ctrl-D to exit.")
229229
clear_interruptible()
230230
if response:
231-
readline.add_history(response)
231+
add_history(response) # readline history
232232
return response
233233

234234

gptme/init.py

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
import atexit
21
import logging
3-
import readline
42
from typing import cast
53

64
from dotenv import load_dotenv
75

86
from .config import config_path, load_config, set_config_value
9-
from .dirs import get_readline_history_file
107
from .llm import init_llm
118
from .models import (
129
PROVIDERS,
1310
Provider,
1411
get_recommended_model,
1512
set_default_model,
1613
)
17-
from .tabcomplete import register_tabcomplete
14+
from .readline import load_readline_history, register_tabcomplete
1815
from .tools import init_tools
1916
from .util import console
2017

@@ -74,7 +71,7 @@ def init(model: str | None, interactive: bool, tool_allowlist: list[str] | None)
7471
set_default_model(model)
7572

7673
if interactive:
77-
_load_readline_history()
74+
load_readline_history()
7875

7976
# for some reason it bugs out shell tests in CI
8077
register_tabcomplete()
@@ -89,36 +86,6 @@ def init_logging(verbose):
8986
logging.getLogger("httpx").setLevel(logging.WARNING)
9087

9188

92-
# default history if none found
93-
# NOTE: there are also good examples in the integration tests
94-
history_examples = [
95-
"What is love?",
96-
"Have you heard about an open-source app called ActivityWatch?",
97-
"Explain 'Attention is All You Need' in the style of Andrej Karpathy.",
98-
"Explain how public-key cryptography works as if I'm five.",
99-
"Write a Python script that prints the first 100 prime numbers.",
100-
"Find all TODOs in the current git project",
101-
]
102-
103-
104-
def _load_readline_history() -> None: # pragma: no cover
105-
logger.debug("Loading history")
106-
# enabled by default in CPython, make it explicit
107-
readline.set_auto_history(True)
108-
# had some bugs where it grew to gigs, which should be fixed, but still good precaution
109-
readline.set_history_length(100)
110-
history_file = get_readline_history_file()
111-
try:
112-
readline.read_history_file(history_file)
113-
except FileNotFoundError:
114-
for line in history_examples:
115-
readline.add_history(line)
116-
except Exception:
117-
logger.exception("Failed to load history file")
118-
119-
atexit.register(readline.write_history_file, history_file)
120-
121-
12289
def _prompt_api_key() -> tuple[str, str, str]: # pragma: no cover
12390
api_key = input("Your OpenAI, Anthropic, or OpenRouter API key: ").strip()
12491
if api_key.startswith("sk-ant-"):

gptme/tabcomplete.py renamed to gptme/readline.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,57 @@
1+
import atexit
12
import logging
2-
import readline
33
from functools import lru_cache
44
from pathlib import Path
55

66
from .commands import COMMANDS
7+
from .dirs import get_readline_history_file
8+
9+
# noreorder
10+
try:
11+
import readline # fmt: skip
12+
except ImportError: # pragma: no cover
13+
raise Exception(
14+
"Unsupported platform: readline not available.\nIf you are on Windows, use WSL or Docker to run gptme."
15+
) from None
16+
717

818
logger = logging.getLogger(__name__)
919

1020

21+
# default history if none found
22+
# NOTE: there are also good examples in the integration tests
23+
history_examples = [
24+
"What is love?",
25+
"Have you heard about an open-source app called ActivityWatch?",
26+
"Explain 'Attention is All You Need' in the style of Andrej Karpathy.",
27+
"Explain how public-key cryptography works as if I'm five.",
28+
"Write a Python script that prints the first 100 prime numbers.",
29+
"Find all TODOs in the current git project",
30+
]
31+
32+
33+
def add_history(line: str) -> None: # pragma: no cover
34+
readline.add_history(line)
35+
36+
37+
def load_readline_history() -> None: # pragma: no cover
38+
logger.debug("Loading history")
39+
# enabled by default in CPython, make it explicit
40+
readline.set_auto_history(True)
41+
# had some bugs where it grew to gigs, which should be fixed, but still good precaution
42+
readline.set_history_length(100)
43+
history_file = get_readline_history_file()
44+
try:
45+
readline.read_history_file(history_file)
46+
except FileNotFoundError:
47+
for line in history_examples:
48+
readline.add_history(line)
49+
except Exception:
50+
logger.exception("Failed to load history file")
51+
52+
atexit.register(readline.write_history_file, history_file)
53+
54+
1155
def register_tabcomplete() -> None: # pragma: no cover
1256
"""Register tab completion for readline."""
1357

tests/test_tabcomplete.py renamed to tests/test_readline.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
import sys
33

4-
from gptme.tabcomplete import _matches
4+
from gptme.readline import _matches
55

66

77
def test_matches():

0 commit comments

Comments
 (0)