diff --git a/cecli/__init__.py b/cecli/__init__.py index 6ea9f35ef0a..66fb65c8e64 100644 --- a/cecli/__init__.py +++ b/cecli/__init__.py @@ -1,6 +1,6 @@ from packaging import version -__version__ = "0.100.8.dev" +__version__ = "0.100.11.dev" safe_version = __version__ try: diff --git a/cecli/args.py b/cecli/args.py index 83286782492..88fd53d22a7 100644 --- a/cecli/args.py +++ b/cecli/args.py @@ -1115,6 +1115,16 @@ def get_parser(default_config_files, git_root): " specified, a default command for your OS may be used." ), ) + group.add_argument( + "--notification-bell", + action=argparse.BooleanOptionalAction, + default=True, + help=( + "Allow notification commands to produce an audible bell. When enabled, command" + " output is not suppressed so terminal bell escape sequences can ring through" + " (default: True)" + ), + ) group.add_argument( "--command-prefix", default=None, diff --git a/cecli/io.py b/cecli/io.py index a140bd516a9..8578282af9a 100644 --- a/cecli/io.py +++ b/cecli/io.py @@ -367,6 +367,7 @@ def __init__( root=".", notifications=False, notifications_command=None, + notification_bell=True, verbose=False, ): self.console = Console() @@ -384,6 +385,7 @@ def __init__( self.multiline_mode = multiline_mode self.bell_on_next_input = False self.notifications = notifications + self.notification_bell = notification_bell self.verbose = verbose self.profile_start_time = None self.profile_last_time = None @@ -1747,11 +1749,20 @@ def _send_notification(self): try: # Use Popen to run the command in the background without waiting for it # and without capturing its output, detaching it from the current terminal session. + + # Determine if this is a terminal bell command that should not be suppressed + is_bell_cmd = ( + "\\a" in self.notifications_command or "\a" in self.notifications_command + ) and re.search(r"(?:echo|print)", self.notifications_command, re.IGNORECASE) + kwargs = { "shell": True, - "stdout": subprocess.DEVNULL, - "stderr": subprocess.DEVNULL, } + + if not (is_bell_cmd or self.notification_bell): + kwargs["stdout"] = subprocess.DEVNULL + kwargs["stderr"] = subprocess.DEVNULL + if platform.system() == "Windows": kwargs["creationflags"] = subprocess.CREATE_NO_WINDOW else: diff --git a/cecli/main.py b/cecli/main.py index 6cb779e7bca..2cd40d7cc9b 100644 --- a/cecli/main.py +++ b/cecli/main.py @@ -273,10 +273,10 @@ def parse_lint_cmds(lint_cmds, io): def register_models(git_root, model_settings_fname, io, verbose=False): from cecli import models - from cecli.helpers.file_searcher import generate_search_path_list + from cecli.helpers.file_searcher import generate_search_path_list, handle_core_files model_settings_files = generate_search_path_list( - ".cecli.model.settings.yml", git_root, model_settings_fname + handle_core_files(".cecli.model.settings.yml"), git_root, model_settings_fname ) try: files_loaded = models.register_models(model_settings_files) @@ -326,13 +326,13 @@ def load_dotenv_files(git_root, dotenv_fname, encoding="utf-8"): def register_litellm_models(git_root, model_metadata_fname, io, verbose=False): from cecli import models - from cecli.helpers.file_searcher import generate_search_path_list + from cecli.helpers.file_searcher import generate_search_path_list, handle_core_files model_metadata_files = [] resource_metadata = importlib_resources.files("cecli.resources").joinpath("model-metadata.json") model_metadata_files.append(str(resource_metadata)) model_metadata_files += generate_search_path_list( - ".cecli.model.metadata.json", git_root, model_metadata_fname + handle_core_files(".cecli.model.metadata.json"), git_root, model_metadata_fname ) try: model_metadata_files_loaded = models.register_litellm_models(model_metadata_files) @@ -697,6 +697,7 @@ def get_io(pretty): multiline_mode=args.multiline, notifications=args.notifications, notifications_command=args.notifications_command, + notification_bell=args.notification_bell, verbose=args.verbose, ) diff --git a/cecli/resources/model-settings.yml b/cecli/resources/model-settings.yml index 995cc25a2bf..3be10dab32f 100644 --- a/cecli/resources/model-settings.yml +++ b/cecli/resources/model-settings.yml @@ -2115,26 +2115,26 @@ - name: openrouter/anthropic/claude-opus-4.6 edit_format: diff - weak_model_name: openrouter/anthropic/claude-haiku-4-5 + weak_model_name: openrouter/anthropic/claude-haiku-4.5 use_repo_map: true examples_as_sys_msg: false extra_params: max_tokens: 128000 cache_control: true - editor_model_name: openrouter/anthropic/claude-sonnet-4-5 + editor_model_name: openrouter/anthropic/claude-sonnet-4.5 editor_edit_format: editor-diff accepts_settings: ["thinking_tokens"] overeager: true - name: openrouter/anthropic/claude-opus-4.7 edit_format: diff - weak_model_name: openrouter/anthropic/claude-haiku-4-5 + weak_model_name: openrouter/anthropic/claude-haiku-4.5 use_repo_map: true examples_as_sys_msg: false extra_params: max_tokens: 128000 cache_control: true - editor_model_name: openrouter/anthropic/claude-sonnet-4-5 + editor_model_name: openrouter/anthropic/claude-sonnet-4.5 editor_edit_format: editor-diff use_temperature: false overeager: true @@ -2142,20 +2142,20 @@ - name: openrouter/anthropic/claude-sonnet-4.5 edit_format: diff - weak_model_name: openrouter/anthropic/claude-haiku-4-5 + weak_model_name: openrouter/anthropic/claude-haiku-4.5 use_repo_map: true examples_as_sys_msg: false extra_params: max_tokens: 64000 cache_control: true - editor_model_name: openrouter/anthropic/claude-sonnet-4-5 + editor_model_name: openrouter/anthropic/claude-sonnet-4.5 editor_edit_format: editor-diff accepts_settings: ["thinking_tokens"] - name: openrouter/anthropic/claude-haiku-4.5 edit_format: diff - weak_model_name: openrouter/anthropic/claude-haiku-4-5 + weak_model_name: openrouter/anthropic/claude-haiku-4.5 use_repo_map: true examples_as_sys_msg: false extra_params: