From 15bd1bb52b364189cde01b5777cf5e0e78eac20f Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 21 May 2024 14:36:41 +0100 Subject: [PATCH 01/10] Update to latest Textual, fix dependencies, add inline mode --- elia_chat/__main__.py | 52 ++++++++++++++------------------ elia_chat/config.py | 2 +- elia_chat/elia.scss | 16 +++++++--- elia_chat/screens/chat_screen.py | 2 +- elia_chat/widgets/chat.py | 2 +- elia_chat/widgets/chat_list.py | 2 +- pyproject.toml | 5 ++- requirements-dev.lock | 7 +---- requirements.lock | 7 +---- 9 files changed, 43 insertions(+), 52 deletions(-) diff --git a/elia_chat/__main__.py b/elia_chat/__main__.py index d879e52..87227fb 100644 --- a/elia_chat/__main__.py +++ b/elia_chat/__main__.py @@ -6,7 +6,7 @@ import pathlib from textwrap import dedent import tomllib -from typing import Any, Tuple +from typing import Any import click from click_default_group import DefaultGroup @@ -17,7 +17,6 @@ from elia_chat.config import LaunchConfig from elia_chat.database.import_chatgpt import import_chatgpt_data from elia_chat.database.database import create_database, sqlite_file_name -from elia_chat.launch_args import QuickLaunchArgs from elia_chat.locations import config_file console = Console() @@ -51,13 +50,32 @@ def cli() -> None: @cli.command() @click.argument("prompt", nargs=-1, type=str, required=False) -def default(prompt: tuple[str, ...]): +@click.option( + "-m", + "--model", + type=str, + default="", + help="The model to use for the chat", +) +@click.option( + "-i", + "--inline", + is_flag=True, + help="Run in inline mode, without launching full TUI.", + default=False, +) +def default(prompt: tuple[str, ...], model: str, inline: bool): prompt = prompt or ("",) joined_prompt = " ".join(prompt) create_db_if_not_exists() file_config = load_or_create_config_file() - app = Elia(LaunchConfig(**file_config), startup_prompt=joined_prompt) - app.run() + cli_config = {} + if model: + cli_config["default_model"] = model + + launch_config: dict[str, Any] = {**file_config, **cli_config} + app = Elia(LaunchConfig(**launch_config), startup_prompt=joined_prompt) + app.run(inline=inline) @cli.command() @@ -110,29 +128,5 @@ def import_file_to_db(file: pathlib.Path) -> None: console.print(f"[green]ChatGPT data imported from {str(file)!r}") -@cli.command() -@click.argument("message", nargs=-1, type=str, required=True) -@click.option( - "-m", - "--model", - type=str, - default="gpt-3.5-turbo", - help="The model to use for the chat", -) -def chat(message: Tuple[str, ...], model: str) -> None: - """ - Start Elia with a chat message - """ - quick_launch_args = QuickLaunchArgs( - launch_prompt=" ".join(message), - launch_prompt_model_name=model, - ) - launch_config = LaunchConfig( - default_model=quick_launch_args.launch_prompt_model_name, - ) - app = Elia(launch_config, quick_launch_args.launch_prompt) - app.run() - - if __name__ == "__main__": cli() diff --git a/elia_chat/config.py b/elia_chat/config.py index c29e618..bfd91df 100644 --- a/elia_chat/config.py +++ b/elia_chat/config.py @@ -58,7 +58,7 @@ def get_builtin_openai_models() -> list[EliaChatModel]: ), EliaChatModel( id="elia-gpt-4o", - name="openai/gpt-4o", + name="gpt-4o", display_name="GPT-4o", provider="OpenAI", product="ChatGPT", diff --git a/elia_chat/elia.scss b/elia_chat/elia.scss index 8aae495..fcfd1f6 100644 --- a/elia_chat/elia.scss +++ b/elia_chat/elia.scss @@ -30,6 +30,10 @@ Tabs .underline--bar { Screen { background: $background; padding: 0 2 1 2; + &:inline { + height: 50vh; + padding: 0 2; + } } ModalScreen { @@ -75,6 +79,9 @@ Chat { height: auto; padding: 1 2; background: $background; + &:inline { + padding: 0 2 1 2; + } & #model-static { color: $text-muted; @@ -163,6 +170,11 @@ AppHeader { width: 1fr; padding: 1 2; height: auto; + + &:inline { + padding: 0 2 1 2; + } + & .app-title { color: $text-muted; } @@ -380,10 +392,6 @@ Tabs:focus .underline--bar { color: $text 35%; } -TokenAnalysis { - height: auto; -} - MessageInfo #inner-container ContentSwitcher { height: auto; padding: 1 2; diff --git a/elia_chat/screens/chat_screen.py b/elia_chat/screens/chat_screen.py index d03a7f6..c26edde 100644 --- a/elia_chat/screens/chat_screen.py +++ b/elia_chat/screens/chat_screen.py @@ -15,7 +15,7 @@ class ChatScreen(Screen[None]): BINDINGS = [ Binding( key="escape", - action="focus('prompt')", + action="app.focus('prompt')", description="Focus prompt", key_display="esc", ), diff --git a/elia_chat/widgets/chat.py b/elia_chat/widgets/chat.py index 857f6a2..7fc26d7 100644 --- a/elia_chat/widgets/chat.py +++ b/elia_chat/widgets/chat.py @@ -86,13 +86,13 @@ class FirstMessageSent(Message): chat_data: ChatData def compose(self) -> ComposeResult: + yield AgentIsTyping() yield ChatHeader(chat=self.chat_data, model=self.model) with VerticalScroll(id="chat-container") as vertical_scroll: vertical_scroll.can_focus = False yield ChatPromptInput(id="prompt") - yield AgentIsTyping() async def on_mount(self, _: events.Mount) -> None: """ diff --git a/elia_chat/widgets/chat_list.py b/elia_chat/widgets/chat_list.py index 4e33173..9e2b372 100644 --- a/elia_chat/widgets/chat_list.py +++ b/elia_chat/widgets/chat_list.py @@ -57,7 +57,7 @@ def __init__(self, chat: ChatData, config: LaunchConfig) -> None: class ChatList(OptionList): BINDINGS = [ Binding( - "escape", "screen.focus('home-prompt')", "Focus prompt", key_display="esc" + "escape", "app.focus('home-prompt')", "Focus prompt", key_display="esc" ), Binding("j,down", "cursor_down", "Down", show=False), Binding("k,up", "cursor_up", "Up", show=False), diff --git a/pyproject.toml b/pyproject.toml index 2b9cafb..392a98f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,15 +6,14 @@ authors = [ { name = "Darren Burns", email = "darrenb900@gmail.com" } ] dependencies = [ - "textual[syntax]==0.58.1", + "textual[syntax]==0.62.0", "sqlmodel>=0.0.9", "humanize>=4.6.0", "click>=8.1.6", "xdg-base-dirs>=6.0.1", - "pydantic-settings>=2.2.1", "aiosqlite>=0.20.0", "click-default-group>=1.2.4", - "litellm>=1.35.38", + "litellm==1.35.38", "greenlet>=3.0.3", "google-generativeai>=0.5.3", ] diff --git a/requirements-dev.lock b/requirements-dev.lock index 93aacb4..687c7d5 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -76,7 +76,6 @@ googleapis-common-protos==1.63.0 # via grpcio-status greenlet==3.0.3 # via elia-chat - # via sqlalchemy grpcio==1.63.0 # via google-api-core # via grpcio-status @@ -160,12 +159,9 @@ pyasn1-modules==0.4.0 pydantic==2.6.1 # via google-generativeai # via openai - # via pydantic-settings # via sqlmodel pydantic-core==2.16.2 # via pydantic -pydantic-settings==2.2.1 - # via elia-chat pygments==2.17.2 # via rich pyinstrument==4.6.2 @@ -173,7 +169,6 @@ pyparsing==3.1.2 # via httplib2 python-dotenv==1.0.1 # via litellm - # via pydantic-settings pyyaml==6.0.1 # via huggingface-hub # via pre-commit @@ -198,7 +193,7 @@ sqlalchemy==2.0.25 # via sqlmodel sqlmodel==0.0.14 # via elia-chat -textual==0.58.1 +textual==0.62.0 # via elia-chat # via textual-dev textual-dev==1.4.0 diff --git a/requirements.lock b/requirements.lock index 25ed829..c756492 100644 --- a/requirements.lock +++ b/requirements.lock @@ -67,7 +67,6 @@ googleapis-common-protos==1.63.0 # via grpcio-status greenlet==3.0.3 # via elia-chat - # via sqlalchemy grpcio==1.63.0 # via google-api-core # via grpcio-status @@ -134,19 +133,15 @@ pyasn1-modules==0.4.0 pydantic==2.6.1 # via google-generativeai # via openai - # via pydantic-settings # via sqlmodel pydantic-core==2.16.2 # via pydantic -pydantic-settings==2.2.1 - # via elia-chat pygments==2.17.2 # via rich pyparsing==3.1.2 # via httplib2 python-dotenv==1.0.1 # via litellm - # via pydantic-settings pyyaml==6.0.1 # via huggingface-hub regex==2023.12.25 @@ -168,7 +163,7 @@ sqlalchemy==2.0.25 # via sqlmodel sqlmodel==0.0.14 # via elia-chat -textual==0.58.1 +textual==0.62.0 # via elia-chat tiktoken==0.5.2 # via litellm From a748f83229bf2a12ad285c983b25cabdcc1276e5 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 21 May 2024 16:00:05 +0100 Subject: [PATCH 02/10] Archiving chats --- elia_chat/chats_manager.py | 10 ++++++++++ elia_chat/database/models.py | 1 + elia_chat/widgets/chat_list.py | 22 +++++++++++++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/elia_chat/chats_manager.py b/elia_chat/chats_manager.py index 2c97652..edc651c 100644 --- a/elia_chat/chats_manager.py +++ b/elia_chat/chats_manager.py @@ -3,6 +3,7 @@ from dataclasses import dataclass import datetime +from sqlmodel import select from textual import log from elia_chat.database.converters import ( @@ -87,6 +88,15 @@ async def create_chat(chat_data: ChatData) -> int: return chat.id + @staticmethod + async def archive_chat(chat_id: int) -> None: + async with get_session() as session: + statement = select(ChatDao).where(ChatDao.id == chat_id) + result = await session.exec(statement) + chat_dao = result.one() + chat_dao.archived = True + await session.commit() + @staticmethod async def add_message_to_chat(chat_id: int, message: ChatMessage) -> None: async with get_session() as session: diff --git a/elia_chat/database/models.py b/elia_chat/database/models.py index 897e130..194f412 100644 --- a/elia_chat/database/models.py +++ b/elia_chat/database/models.py @@ -75,6 +75,7 @@ async def all() -> list["ChatDao"]: statement = ( select(ChatDao) .join(subquery, subquery.c.chat_id == ChatDao.id) + .where(ChatDao.archived == False) .order_by(desc(subquery.c.max_timestamp)) .options(selectinload(ChatDao.messages)) ) diff --git a/elia_chat/widgets/chat_list.py b/elia_chat/widgets/chat_list.py index 9e2b372..d666b6d 100644 --- a/elia_chat/widgets/chat_list.py +++ b/elia_chat/widgets/chat_list.py @@ -2,6 +2,7 @@ import datetime from dataclasses import dataclass +from typing import cast import humanize from rich.console import RenderResult, Console, ConsoleOptions @@ -59,6 +60,7 @@ class ChatList(OptionList): Binding( "escape", "app.focus('home-prompt')", "Focus prompt", key_display="esc" ), + Binding("a", "archive_chat", "Archive chat", key_display="a"), Binding("j,down", "cursor_down", "Down", show=False), Binding("k,up", "cursor_up", "Up", show=False), Binding("l,right,enter", "select", "Select", show=False), @@ -110,7 +112,7 @@ async def reload_and_refresh(self, new_highlighted: int = -1) -> None: old_highlighted = self.highlighted self.clear_options() self.add_options(self.options) - self.border_title = f"History ({len(self.options)})" + self.border_title = self.get_border_title() if new_highlighted > -1: self.highlighted = new_highlighted else: @@ -124,6 +126,24 @@ async def load_chats(self) -> list[ChatData]: all_chats = await ChatsManager.all_chats() return all_chats + async def action_archive_chat(self) -> None: + if self.highlighted is None: + return + + item = cast(ChatListItem, self.get_option_at_index(self.highlighted)) + self.options.pop(self.highlighted) + self.remove_option_at_index(self.highlighted) + + chat_id = item.chat.id + await ChatsManager.archive_chat(chat_id) + + self.border_title = self.get_border_title() + self.refresh() + self.app.notify(f"Chat [b]{chat_id!r}[/] archived") + + def get_border_title(self) -> str: + return f"History ({len(self.options)})" + def create_chat(self, chat_data: ChatData) -> None: new_chat_list_item = ChatListItem(chat_data, self.app.launch_config) log.debug(f"Creating new chat {new_chat_list_item!r}") From 9b475f9a123f23158249218ed097df84da1fb3fd Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 21 May 2024 16:14:04 +0100 Subject: [PATCH 03/10] Change default code theme --- elia_chat/widgets/chatbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elia_chat/widgets/chatbox.py b/elia_chat/widgets/chatbox.py index c1265dd..198ee69 100644 --- a/elia_chat/widgets/chatbox.py +++ b/elia_chat/widgets/chatbox.py @@ -260,7 +260,7 @@ def markdown(self) -> Markdown: content = self.message.message.get("content") if not isinstance(content, str): content = "" - return Markdown(content) + return Markdown(content, code_theme="dracula") def render(self) -> RenderableType: if self.selection_mode: From dd880421ad3c3a24ce3ed8254452d44413ed5a68 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 21 May 2024 16:28:23 +0100 Subject: [PATCH 04/10] Allow customising the code theme used in messages via configuration --- README.md | 3 +++ elia_chat/config.py | 2 ++ elia_chat/widgets/chatbox.py | 5 ++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index acd900d..6fa3753 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,9 @@ The example file below shows the available options, as well as examples of how t default_model = "elia-gpt-3.5-turbo" # the system prompt on launch system_prompt = "You are a helpful assistant who talks like a pirate." +# change the syntax highlighting theme of code in messages +# choose from https://pygments.org/styles/ +message_code_theme = "dracula" # example of adding local llama3 support # only the `name` field is required here. diff --git a/elia_chat/config.py b/elia_chat/config.py index bfd91df..c4028f9 100644 --- a/elia_chat/config.py +++ b/elia_chat/config.py @@ -153,6 +153,8 @@ class LaunchConfig(BaseModel): "ELIA_SYSTEM_PROMPT", "You are a helpful assistant named Elia." ) ) + message_code_theme: str = Field(default="dracula") + """The default Pygments syntax highlighting theme to be used in chatboxes.""" models: list[EliaChatModel] = Field(default_factory=list) builtin_models: list[EliaChatModel] = Field( default_factory=get_builtin_models, init=False diff --git a/elia_chat/widgets/chatbox.py b/elia_chat/widgets/chatbox.py index 198ee69..a9f92e4 100644 --- a/elia_chat/widgets/chatbox.py +++ b/elia_chat/widgets/chatbox.py @@ -18,6 +18,7 @@ from elia_chat.config import EliaChatModel from elia_chat.models import ChatMessage +from elia_chat.config import launch_config class SelectionTextArea(TextArea): @@ -260,7 +261,9 @@ def markdown(self) -> Markdown: content = self.message.message.get("content") if not isinstance(content, str): content = "" - return Markdown(content, code_theme="dracula") + + config = launch_config.get() + return Markdown(content, code_theme=config.message_code_theme) def render(self) -> RenderableType: if self.selection_mode: From eaecc5983051540a4cef0d7303010330edc454c0 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 21 May 2024 16:40:45 +0100 Subject: [PATCH 05/10] Default to Monokai --- README.md | 5 ++--- elia_chat/config.py | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6fa3753..6676fa5 100644 --- a/README.md +++ b/README.md @@ -53,14 +53,13 @@ the options window (`ctrl+o`). The example file below shows the available options, as well as examples of how to add new models. ```toml -# the *ID* for the model that is selected by default on launch -# to use one of the default builtin OpenAI/anthropic models, prefix -# the model name with `elia-`. +# the ID or name of the model that is selected by default on launch default_model = "elia-gpt-3.5-turbo" # the system prompt on launch system_prompt = "You are a helpful assistant who talks like a pirate." # change the syntax highlighting theme of code in messages # choose from https://pygments.org/styles/ +# defaults to "monokai" message_code_theme = "dracula" # example of adding local llama3 support diff --git a/elia_chat/config.py b/elia_chat/config.py index c4028f9..598500e 100644 --- a/elia_chat/config.py +++ b/elia_chat/config.py @@ -153,7 +153,7 @@ class LaunchConfig(BaseModel): "ELIA_SYSTEM_PROMPT", "You are a helpful assistant named Elia." ) ) - message_code_theme: str = Field(default="dracula") + message_code_theme: str = Field(default="monokai") """The default Pygments syntax highlighting theme to be used in chatboxes.""" models: list[EliaChatModel] = Field(default_factory=list) builtin_models: list[EliaChatModel] = Field( From b7d6965e845a53a55661f322436cca1d4ee54ed9 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 21 May 2024 16:46:00 +0100 Subject: [PATCH 06/10] Using Pyperclip to copy instead of the terminal emulator --- elia_chat/widgets/chatbox.py | 8 ++++++-- pyproject.toml | 1 + requirements-dev.lock | 2 ++ requirements.lock | 2 ++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/elia_chat/widgets/chatbox.py b/elia_chat/widgets/chatbox.py index a9f92e4..7ff93fa 100644 --- a/elia_chat/widgets/chatbox.py +++ b/elia_chat/widgets/chatbox.py @@ -98,7 +98,9 @@ def action_copy_to_clipboard(self) -> None: message = f"Copied message ({len(text_to_copy)} characters)." self.notify(message, title="Message copied") - self.app.copy_to_clipboard(text_to_copy) + import pyperclip + + pyperclip.copy(text_to_copy) self.visual_mode = False def action_next_code_block(self) -> None: @@ -204,7 +206,9 @@ def action_copy_to_clipboard(self) -> None: if not self.selection_mode: text_to_copy = self.message.message.get("content") if isinstance(text_to_copy, str): - self.app.copy_to_clipboard(text_to_copy) + import pyperclip + + pyperclip.copy(text_to_copy) message = f"Copied message ({len(text_to_copy)} characters)." self.notify(message, title="Message copied") else: diff --git a/pyproject.toml b/pyproject.toml index 392a98f..8b461cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ dependencies = [ "litellm==1.35.38", "greenlet>=3.0.3", "google-generativeai>=0.5.3", + "pyperclip>=1.8.2", ] readme = "README.md" requires-python = ">= 3.11" diff --git a/requirements-dev.lock b/requirements-dev.lock index 687c7d5..f6ddd28 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -167,6 +167,8 @@ pygments==2.17.2 pyinstrument==4.6.2 pyparsing==3.1.2 # via httplib2 +pyperclip==1.8.2 + # via elia-chat python-dotenv==1.0.1 # via litellm pyyaml==6.0.1 diff --git a/requirements.lock b/requirements.lock index c756492..68a175c 100644 --- a/requirements.lock +++ b/requirements.lock @@ -140,6 +140,8 @@ pygments==2.17.2 # via rich pyparsing==3.1.2 # via httplib2 +pyperclip==1.8.2 + # via elia-chat python-dotenv==1.0.1 # via litellm pyyaml==6.0.1 From aa47800a9edb41555bd8b672581ae539551b2e20 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 21 May 2024 16:59:13 +0100 Subject: [PATCH 07/10] Change default model to gpt-4o --- README.md | 18 +++++++++++++++--- elia_chat/config.py | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6676fa5..7b28042 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,22 @@ Launch Elia from the command line: elia ``` -Launch directly a new chat from the command line: +Launch a new chat inline (under your prompt) with `-i`/`--inline`: ```bash -elia "What is the Zen of Python?" +elia -i "What is the Zen of Python?" +``` + +Launch a new chat in full-screen mode: + +```bash +elia "Tell me a cool fact about lizards!" +``` + +Specify a model via the command line using `-m`/`--model`: + +```bash +elia -m gpt-4o ``` ## Running local models @@ -54,7 +66,7 @@ The example file below shows the available options, as well as examples of how t ```toml # the ID or name of the model that is selected by default on launch -default_model = "elia-gpt-3.5-turbo" +default_model = "gpt-4o" # the system prompt on launch system_prompt = "You are a helpful assistant who talks like a pirate." # change the syntax highlighting theme of code in messages diff --git a/elia_chat/config.py b/elia_chat/config.py index 598500e..50360e1 100644 --- a/elia_chat/config.py +++ b/elia_chat/config.py @@ -146,7 +146,7 @@ class LaunchConfig(BaseModel): model_config = ConfigDict(frozen=True) - default_model: str = Field(default="elia-gpt-3.5-turbo") + default_model: str = Field(default="elia-gpt-4o") """The ID or name of the default model.""" system_prompt: str = Field( default=os.getenv( From d53fc93be273682404d58c0ff9fffabdc62f0e4e Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 21 May 2024 17:11:15 +0100 Subject: [PATCH 08/10] Fix modal screens in inline mode --- elia_chat/elia.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/elia_chat/elia.scss b/elia_chat/elia.scss index fcfd1f6..85e1473 100644 --- a/elia_chat/elia.scss +++ b/elia_chat/elia.scss @@ -39,7 +39,10 @@ Screen { ModalScreen { background: black 50%; padding: 0; - + &:inline { + padding: 0; + border: none; + } & Footer { margin: 0 2 1 2; } From 268e8fb62d44dbf94c892f4d12225948e57c27e8 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 21 May 2024 17:16:15 +0100 Subject: [PATCH 09/10] Small changes --- elia_chat/app.py | 2 +- elia_chat/elia.scss | 2 +- elia_chat/screens/help_screen.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/elia_chat/app.py b/elia_chat/app.py index de8ab9a..a57d8dc 100644 --- a/elia_chat/app.py +++ b/elia_chat/app.py @@ -28,7 +28,7 @@ class Elia(App[None]): CSS_PATH = Path(__file__).parent / "elia.scss" BINDINGS = [ Binding("q", "app.quit", "Quit", show=False), - Binding("?", "help", "Help"), + Binding("f1,?", "help", "Help"), ] def __init__(self, config: LaunchConfig, startup_prompt: str = ""): diff --git a/elia_chat/elia.scss b/elia_chat/elia.scss index 85e1473..fa2b08a 100644 --- a/elia_chat/elia.scss +++ b/elia_chat/elia.scss @@ -31,7 +31,7 @@ Screen { background: $background; padding: 0 2 1 2; &:inline { - height: 50vh; + height: 80vh; padding: 0 2; } } diff --git a/elia_chat/screens/help_screen.py b/elia_chat/screens/help_screen.py index 77638af..4231bdf 100644 --- a/elia_chat/screens/help_screen.py +++ b/elia_chat/screens/help_screen.py @@ -8,7 +8,7 @@ class HelpScreen(ModalScreen[None]): BINDINGS = [ Binding("q", "app.quit", "Quit", show=False), - Binding("escape,?", "app.pop_screen()", "Close help", key_display="esc"), + Binding("escape,f1,?", "app.pop_screen()", "Close help", key_display="esc"), ] HELP_MARKDOWN = """\ From 1b51948c111bcb1243c1b0c7244ce036ca41e512 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 21 May 2024 17:17:44 +0100 Subject: [PATCH 10/10] 1.6.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8b461cf..b82881d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "elia_chat" -version = "1.5.0" +version = "1.6.0" description = "A powerful terminal user interface for interacting with large language models." authors = [ { name = "Darren Burns", email = "darrenb900@gmail.com" }