From 89f2499c2191f1574075f977611736608325e2fa Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 8 May 2026 19:42:20 -0700 Subject: [PATCH 1/6] fix: Hide PowerShell window when sending notifications Co-authored-by: cecli (openai/gemini_cli_local/gemini-2.5-pro) --- cecli/io.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cecli/io.py b/cecli/io.py index 230b87f0745..c3ebac99f6b 100644 --- a/cecli/io.py +++ b/cecli/io.py @@ -1724,7 +1724,7 @@ def get_default_notification_command(self): "[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('cecli')" '.Show($toast)"' ) - return "powershell -command" + ps_command + return "powershell -WindowStyle Hidden -Command" + ps_command return None # Unknown system From 2e89564add20e4a2313907d5542f1a86406793a3 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 10 May 2026 14:03:16 -0700 Subject: [PATCH 2/6] fix: Use MessageBox for Windows notifications to hide terminal Co-authored-by: cecli (openai/nvidia_nim/deepseek-ai/deepseek-v4-pro) --- cecli/io.py | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/cecli/io.py b/cecli/io.py index c3ebac99f6b..455e37acfe4 100644 --- a/cecli/io.py +++ b/cecli/io.py @@ -1707,24 +1707,13 @@ def get_default_notification_command(self): return f"zenity --notification --text='{NOTIFICATION_MESSAGE}'" return None # No known notification tool found elif system == "Windows": - # PowerShell toast notification - ps_command = ( - ' "try {{ Add-Type -AssemblyName System.Runtime.WindowsRuntime; $null =' - " [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications," - " ContentType = WindowsRuntime] }} catch {{}}; " - "$template =" - " [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent" - "([Windows.UI.Notifications.ToastTemplateType]::ToastText02); " - "$toastXml = $template.GetXml(); " - "$toastXml.GetElementsByTagName('text')[0].AppendChild" - "($template.CreateTextNode('cecli')) > $null; " - f"$toastXml.GetElementsByTagName('text')[1].AppendChild" - f"($template.CreateTextNode('{NOTIFICATION_MESSAGE}')) > $null; " - "$toast = [Windows.UI.Notifications.ToastNotification]::new($toastXml); " - "[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('cecli')" - '.Show($toast)"' + # PowerShell MessageBox notification (no terminal window shown) + return ( + "powershell -Command" + " \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');" + f" [System.Windows.Forms.MessageBox]::Show('{NOTIFICATION_MESSAGE}'," + " 'cecli')\"" ) - return "powershell -WindowStyle Hidden -Command" + ps_command return None # Unknown system From c9f8771cc04871d636f26776b33d68f95f7ef6c9 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 10 May 2026 14:20:39 -0700 Subject: [PATCH 3/6] fix: Remove DETACHED_PROCESS flag for Windows notifications Co-authored-by: cecli (openai/nvidia_nim/deepseek-ai/deepseek-v4-pro) --- cecli/io.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cecli/io.py b/cecli/io.py index 455e37acfe4..cd7994a64e0 100644 --- a/cecli/io.py +++ b/cecli/io.py @@ -1728,9 +1728,7 @@ def _send_notification(self): "stderr": subprocess.DEVNULL, } if platform.system() == "Windows": - kwargs["creationflags"] = ( - subprocess.CREATE_NO_WINDOW | subprocess.DETACHED_PROCESS - ) + kwargs["creationflags"] = subprocess.CREATE_NO_WINDOW else: # For non-Windows systems, start a new session to detach kwargs["start_new_session"] = True From 40a8f2390c0bfffa48424deee4299f65dbb33b72 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 10 May 2026 14:24:07 -0700 Subject: [PATCH 4/6] cli-12: fixed formatting --- cecli/coders/agent_coder.py | 25 +++++++++++++-------- cecli/coders/base_coder.py | 5 ++--- cecli/sessions.py | 15 ++++++------- cecli/tools/context_manager.py | 3 +-- cecli/tools/read_range.py | 41 +++++++++++++++++++++------------- 5 files changed, 51 insertions(+), 38 deletions(-) diff --git a/cecli/coders/agent_coder.py b/cecli/coders/agent_coder.py index 77db195c201..8524d707185 100644 --- a/cecli/coders/agent_coder.py +++ b/cecli/coders/agent_coder.py @@ -282,9 +282,7 @@ async def _exec_async(): content_parts.append(item.text) return "".join(content_parts) except Exception as e: - self.io.tool_warning( - (f"Executing {tool_name} on {server.name} failed:\nError: {e}") - ) + self.io.tool_warning(f"Executing {tool_name} on {server.name} failed:\nError: {e}") return f"Error executing tool call {tool_name}: {e}" result, interrupted = await interruptible(_exec_async(), self.interrupt_event) @@ -381,7 +379,10 @@ def get_context_symbol_outline(self): try: result = '\n' result += "## Symbol Outline (Current Context)\n\n" - result += "Code definitions (classes, functions, methods, etc.) found in files currently in chat context." + result += ( + "Code definitions (classes, functions, methods, etc.) found in files currently in" + " chat context." + ) result += "\n\n" files_to_outline = list(self.abs_fnames) + list(self.abs_read_only_fnames) if not files_to_outline: @@ -522,7 +523,10 @@ def get_context_summary(self): ) if editable_files: result += "\n".join(editable_files) + "\n\n" - result += f"**Total editable: {len(editable_files)} files, {editable_tokens:,} tokens**\n\n" + result += ( + f"**Total editable: {len(editable_files)} files," + f" {editable_tokens:,} tokens**\n\n" + ) else: result += "No editable files in context\n\n" if self.abs_read_only_fnames: @@ -542,7 +546,10 @@ def get_context_summary(self): ) if readonly_files: result += "\n".join(readonly_files) + "\n\n" - result += f"**Total read-only: {len(readonly_files)} files, {readonly_tokens:,} tokens**\n\n" + result += ( + f"**Total read-only: {len(readonly_files)} files," + f" {readonly_tokens:,} tokens**\n\n" + ) else: result += "No read-only files in context\n\n" extra_tokens = sum(self.context_block_tokens.values()) @@ -730,7 +737,7 @@ async def gather_and_await(): self.model_kwargs = {} result_message = f"Error executing {tool_name}: {e}" self.io.tool_error( - (f"Error during {tool_name} execution: {e}\n{traceback.format_exc()}") + f"Error during {tool_name} execution: {e}\n{traceback.format_exc()}" ) tool_responses.append( {"role": "tool", "tool_call_id": tool_call.id, "content": result_message} @@ -1020,8 +1027,8 @@ def _generate_tool_context(self, repetitive_tools): context_parts.append("## File Editing Tools Disabled") context_parts.append( "File editing tools are currently disabled. Use `ReadRange` to determine the" - " current content hash prefixes needed to perform an edit and activate them when you" - " are ready to edit a file." + " current content hash prefixes needed to perform an edit and activate them when" + " you are ready to edit a file." ) context_parts.append("\n\n") diff --git a/cecli/coders/base_coder.py b/cecli/coders/base_coder.py index 922d5328671..afcae12a9d7 100755 --- a/cecli/coders/base_coder.py +++ b/cecli/coders/base_coder.py @@ -1142,9 +1142,8 @@ def _include_in_map(abs_path): "other_files": other_files, "mentioned_fnames": mentioned_fnames, "all_abs_files": all_abs_files, - "read_only_count": ( - len(set(self.abs_read_only_fnames)) - + len(set(self.abs_read_only_stubs_fnames)) + "read_only_count": len(set(self.abs_read_only_fnames)) + len( + set(self.abs_read_only_stubs_fnames) ), } ) diff --git a/cecli/sessions.py b/cecli/sessions.py index 5ff6a5cd4e9..6d6be87bc8c 100644 --- a/cecli/sessions.py +++ b/cecli/sessions.py @@ -71,10 +71,9 @@ def list_sessions(self) -> List[Dict]: "file": session_file, "model": session_data.get("model", "unknown"), "edit_format": session_data.get("edit_format", "unknown"), - "num_messages": ( - len(session_data.get("chat_history", {}).get("done_messages", [])) - + len(session_data.get("chat_history", {}).get("cur_messages", [])) - ), + "num_messages": len( + session_data.get("chat_history", {}).get("done_messages", []) + ) + len(session_data.get("chat_history", {}).get("cur_messages", [])), "num_files": ( len(session_data.get("files", {}).get("editable", [])) + len(session_data.get("files", {}).get("read_only", [])) @@ -198,11 +197,11 @@ def _build_session_data(self, session_name) -> Dict: "editor_edit_format": self.coder.main_model.editor_edit_format, "edit_format": self.coder.edit_format, "chat_history": { - "done_messages": ( - ConversationService.get_manager(self.coder).get_messages_dict(MessageTag.DONE) + "done_messages": ConversationService.get_manager(self.coder).get_messages_dict( + MessageTag.DONE ), - "cur_messages": ( - ConversationService.get_manager(self.coder).get_messages_dict(MessageTag.CUR) + "cur_messages": ConversationService.get_manager(self.coder).get_messages_dict( + MessageTag.CUR ), }, "files": { diff --git a/cecli/tools/context_manager.py b/cecli/tools/context_manager.py index f969f48edcc..de565573f15 100644 --- a/cecli/tools/context_manager.py +++ b/cecli/tools/context_manager.py @@ -32,8 +32,7 @@ class Tool(BaseTool): "type": "array", "items": {"type": "string"}, "description": ( - "List of file paths to add as read-only. " - "Limit to at most 2 at a time." + "List of file paths to add as read-only. Limit to at most 2 at a time." ), }, "create": { diff --git a/cecli/tools/read_range.py b/cecli/tools/read_range.py index 0b0310ab997..66cafedd73b 100644 --- a/cecli/tools/read_range.py +++ b/cecli/tools/read_range.py @@ -22,17 +22,16 @@ class Tool(BaseTool): "name": "ReadRange", "description": ( "Get content hash prefixes of content between start and end patterns in files." - " Accepts an array of `show` objects, each with file_path, start_text," - " end_text. These values must be lines from the content of the file." - " They can contain up to 3 lines but newlines should generally be avoided." - " Avoid using generic keywords and symbols." - "Special markers @000 and 000@ represent the file boundaries and can be" - " used for start_text and end_text for the first and last lines of" - " the file respectively. Avoid using both of the special markers together on non-empty files." - " Never use content hashes as the start_text and end_text values." - " Do not use the same pattern for the start_text and end_text." - " It is best to use function names, variable declarations and other block identifiers as " - " start_texts and end_texts." + " Accepts an array of `show` objects, each with file_path, start_text, end_text." + " These values must be lines from the content of the file. They can contain up to 3" + " lines but newlines should generally be avoided. Avoid using generic keywords and" + " symbols.Special markers @000 and 000@ represent the file boundaries and can be" + " used for start_text and end_text for the first and last lines of the file" + " respectively. Avoid using both of the special markers together on non-empty" + " files. Never use content hashes as the start_text and end_text values. Do not use" + " the same pattern for the start_text and end_text. It is best to use function" + " names, variable declarations and other block identifiers as start_texts and" + " end_texts." ), "parameters": { "type": "object", @@ -127,7 +126,10 @@ def execute(cls, coder, show, **kwargs): error_outputs.append( cls.format_error( coder, - f"Show operation {show_index + 1}: Provide both 'start_text' and 'end_text'.", + ( + f"Show operation {show_index + 1}: Provide both 'start_text' and" + " 'end_text'." + ), file_path, start_text, end_text, @@ -284,7 +286,10 @@ def execute(cls, coder, show, **kwargs): error_outputs.append( cls.format_error( coder, - f"End pattern '{end_text}' not found in {file_path}. Do not search for it again.", + ( + f"End pattern '{end_text}' not found in {file_path}. Do not" + " search for it again." + ), file_path, start_text, end_text, @@ -297,7 +302,10 @@ def execute(cls, coder, show, **kwargs): error_outputs.append( cls.format_error( coder, - f"End pattern '{end_text}' not found after start pattern in {file_path}.", + ( + f"End pattern '{end_text}' not found after start pattern in" + f" {file_path}." + ), file_path, start_text, end_text, @@ -314,7 +322,7 @@ def execute(cls, coder, show, **kwargs): cls.format_error( coder, ( - f"Special markers cannot be used for ranges greater than 200 lines." + "Special markers cannot be used for ranges greater than 200 lines." f" The resolved range is {e_idx - s_idx + 1} lines." " Pick more refined boundaries." ), @@ -466,7 +474,8 @@ def execute(cls, coder, show, **kwargs): ) if already_up_to_details: coder.io.tool_output( - f"Lines already up to date in context for {len(already_up_to_details)} operation(s)" + "Lines already up to date in context for" + f" {len(already_up_to_details)} operation(s)" ) detail_str = "\n".join(already_up_to_details) From d4f892c82e8747a150c867c779386a524c9978d1 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 10 May 2026 15:02:13 -0700 Subject: [PATCH 5/6] cli-12: fixed formatting --- cecli/coders/base_coder.py | 5 +++-- cecli/sessions.py | 15 ++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/cecli/coders/base_coder.py b/cecli/coders/base_coder.py index afcae12a9d7..922d5328671 100755 --- a/cecli/coders/base_coder.py +++ b/cecli/coders/base_coder.py @@ -1142,8 +1142,9 @@ def _include_in_map(abs_path): "other_files": other_files, "mentioned_fnames": mentioned_fnames, "all_abs_files": all_abs_files, - "read_only_count": len(set(self.abs_read_only_fnames)) + len( - set(self.abs_read_only_stubs_fnames) + "read_only_count": ( + len(set(self.abs_read_only_fnames)) + + len(set(self.abs_read_only_stubs_fnames)) ), } ) diff --git a/cecli/sessions.py b/cecli/sessions.py index 6d6be87bc8c..5ff6a5cd4e9 100644 --- a/cecli/sessions.py +++ b/cecli/sessions.py @@ -71,9 +71,10 @@ def list_sessions(self) -> List[Dict]: "file": session_file, "model": session_data.get("model", "unknown"), "edit_format": session_data.get("edit_format", "unknown"), - "num_messages": len( - session_data.get("chat_history", {}).get("done_messages", []) - ) + len(session_data.get("chat_history", {}).get("cur_messages", [])), + "num_messages": ( + len(session_data.get("chat_history", {}).get("done_messages", [])) + + len(session_data.get("chat_history", {}).get("cur_messages", [])) + ), "num_files": ( len(session_data.get("files", {}).get("editable", [])) + len(session_data.get("files", {}).get("read_only", [])) @@ -197,11 +198,11 @@ def _build_session_data(self, session_name) -> Dict: "editor_edit_format": self.coder.main_model.editor_edit_format, "edit_format": self.coder.edit_format, "chat_history": { - "done_messages": ConversationService.get_manager(self.coder).get_messages_dict( - MessageTag.DONE + "done_messages": ( + ConversationService.get_manager(self.coder).get_messages_dict(MessageTag.DONE) ), - "cur_messages": ConversationService.get_manager(self.coder).get_messages_dict( - MessageTag.CUR + "cur_messages": ( + ConversationService.get_manager(self.coder).get_messages_dict(MessageTag.CUR) ), }, "files": { From bceb0b5b5716ff4f3a35141b2d73a81fafc36513 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 10 May 2026 19:13:29 -0700 Subject: [PATCH 6/6] cli-12: fix --- cecli/io.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/cecli/io.py b/cecli/io.py index cd7994a64e0..cbea56e2109 100644 --- a/cecli/io.py +++ b/cecli/io.py @@ -1707,13 +1707,24 @@ def get_default_notification_command(self): return f"zenity --notification --text='{NOTIFICATION_MESSAGE}'" return None # No known notification tool found elif system == "Windows": - # PowerShell MessageBox notification (no terminal window shown) - return ( - "powershell -Command" - " \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');" - f" [System.Windows.Forms.MessageBox]::Show('{NOTIFICATION_MESSAGE}'," - " 'cecli')\"" + # PowerShell toast notification + ps_command = ( + ' "try {{ Add-Type -AssemblyName System.Runtime.WindowsRuntime; $null =' + " [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications," + " ContentType = WindowsRuntime] }} catch {{}}; " + "$template =" + " [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent" + "([Windows.UI.Notifications.ToastTemplateType]::ToastText02); " + "$toastXml = $template.GetXml(); " + "$toastXml.GetElementsByTagName('text')[0].AppendChild" + "($template.CreateTextNode('cecli')) > $null; " + f"$toastXml.GetElementsByTagName('text')[1].AppendChild" + f"($template.CreateTextNode('{NOTIFICATION_MESSAGE}')) > $null; " + "$toast = [Windows.UI.Notifications.ToastNotification]::new($toastXml); " + "[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('cecli')" + '.Show($toast)"' ) + return "powershell -WindowStyle Hidden -Command" + ps_command return None # Unknown system