Skip to content

feat: boost windows & fix SSL in desktop#1282

Merged
xieyxclack merged 6 commits intoagentscope-ai:mainfrom
rayrayraykk:weirui/dev/startup-boost
Mar 11, 2026
Merged

feat: boost windows & fix SSL in desktop#1282
xieyxclack merged 6 commits intoagentscope-ai:mainfrom
rayrayraykk:weirui/dev/startup-boost

Conversation

@rayrayraykk
Copy link
Copy Markdown
Member

Description

[Describe what this PR does and why]

Related Issue: Fixes #(issue_number) or Relates to #(issue_number)

Security Considerations: [If applicable, e.g. channel auth, env/config handling]

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Refactoring

Component(s) Affected

  • Core / Backend (app, agents, config, providers, utils, local_models)
  • Console (frontend web UI)
  • Channels (DingTalk, Feishu, QQ, Discord, iMessage, etc.)
  • Skills
  • CLI
  • Documentation (website)
  • Tests
  • CI/CD
  • Scripts / Deploy

Checklist

  • I ran pre-commit run --all-files locally and it passes
  • If pre-commit auto-fixed files, I committed those changes and reran checks
  • I ran tests locally (pytest or as relevant) and they pass
  • Documentation updated (if needed)
  • Ready for review

Testing

[How to test these changes]

Local Verification Evidence

pre-commit run --all-files
# paste summary result

pytest
# paste summary result

Additional Notes

[Optional: any other context]

Copilot AI review requested due to automatic review settings March 11, 2026 13:43
@rayrayraykk rayrayraykk temporarily deployed to maintainer-approved March 11, 2026 13:43 — with GitHub Actions Inactive
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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 enhances the robustness and debuggability of the desktop application across Windows and macOS. It tackles critical issues such as subprocess communication deadlocks on Windows, improves the reliability of SSL certificate discovery, and introduces more flexible logging configurations. These changes collectively aim to provide a more stable user experience and streamline troubleshooting for developers.

Highlights

  • Enhanced Windows Desktop Application Stability: Addressed subprocess buffer blocking issues on Windows by implementing a dedicated _stream_reader function and utilizing threading to continuously drain stdout and stderr of child processes, preventing deadlocks.
  • Improved SSL Certificate Handling: Refined the detection and logging of the SSL_CERT_FILE path across both Windows and macOS desktop builds, including a new temporary file approach on Windows to reliably query certifi paths and logging warnings if the specified certificate file is not found.
  • Flexible Logging Level Configuration: Introduced support for the COPAW_LOG_LEVEL environment variable, allowing users to control the application's logging verbosity. Default log levels are now info for standard launches and debug for debug mode, enhancing diagnostic capabilities.
  • Platform-Specific File Logging: Modified the file logging mechanism to use a simple FileHandler on Windows and Linux to prevent file locking issues, while retaining the RotatingFileHandler for macOS to manage log file sizes.
  • Standardized PATH Environment Variable Management: Ensured that the system PATH is preserved and the packaged environment's bin directory is prepended to it in both Windows and macOS build scripts, allowing desktop applications to correctly access system commands and packaged Python executables.
  • Application Startup Performance Logging: Added debug logging for the application's startup duration, providing insights into performance and helping identify potential bottlenecks during initialization.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • scripts/pack/build_macos.sh
    • Preserved system PATH and prepended packaged environment's bin directory to ensure correct command execution.
    • Added logging for the PATH and LOG_LEVEL environment variables at startup for improved debugging.
    • Integrated COPAW_LOG_LEVEL to control the log verbosity of the copaw desktop command.
  • scripts/pack/build_win.ps1
    • Preserved system PATH and prepended packaged environment's bin directory for consistent command access.
    • Implemented COPAW_LOG_LEVEL for the copaw desktop command, defaulting to info for normal and debug for debug mode.
    • Revised SSL certifi path detection to use a temporary file, resolving for /f blocking issues in batch scripts.
    • Expanded debug mode logging to include PATH, Log Level, SSL_CERT_FILE, REQUESTS_CA_BUNDLE, and CURL_CA_BUNDLE.
  • src/copaw/app/_app.py
    • Imported the time module.
    • Implemented logging for the application's startup duration to monitor performance.
  • src/copaw/cli/desktop_cmd.py
    • Imported the threading module.
    • Introduced a _stream_reader function to handle non-blocking output from subprocesses on Windows.
    • Added checks and logging for the SSL_CERT_FILE environment variable, including warnings if the file is not found.
    • Modified the subprocess.Popen call to launch the application using copaw app instead of directly invoking uvicorn.
    • Configured subprocess.Popen to use piped stdout and stderr with dedicated reader threads for Windows to prevent buffer deadlocks.
  • src/copaw/utils/logging.py
    • Updated the docstring for add_copaw_file_handler to clarify platform-specific behavior.
    • Implemented conditional file handlers: FileHandler for Windows/Linux to avoid file locking, and RotatingFileHandler for macOS.
    • Set the default log level for the Windows file handler to INFO.
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 Generative AI Prohibited Use Policy, 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
Copy Markdown
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 updates desktop startup behavior and packaging scripts to improve Windows reliability and ensure SSL certificate environment variables are set correctly in packaged apps.

Changes:

  • Adjust daemon log file handling to use non-rotating logging on Windows/Linux and rotating logs on macOS.
  • Update copaw desktop to start the server via python -m copaw app, add SSL cert diagnostics, and drain subprocess output on Windows to avoid blocking.
  • Update Windows/macOS pack launchers to preserve PATH, set SSL cert env vars, and pass through a configurable log level.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/copaw/utils/logging.py Switches daemon file logging to platform-specific handlers (FileHandler vs RotatingFileHandler).
src/copaw/cli/desktop_cmd.py Improves Windows subprocess output handling and starts the app via the CLI app command; adds SSL_CERT_FILE diagnostics.
src/copaw/app/_app.py Adds startup elapsed-time debug logging during FastAPI lifespan startup.
scripts/pack/build_win.ps1 Updates generated .bat launchers to preserve PATH, improve certifi lookup, and pass --log-level.
scripts/pack/build_macos.sh Updates the .app launcher to preserve PATH and pass --log-level.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +157 to +170
is_windows_or_linux = platform.system() in ("Windows", "Linux")
if is_windows_or_linux:
file_handler = logging.FileHandler(
log_path,
encoding="utf-8",
mode="a",
)
else:
file_handler = logging.handlers.RotatingFileHandler(
log_path,
encoding="utf-8",
maxBytes=_COPAW_LOG_MAX_BYTES,
backupCount=_COPAW_LOG_BACKUP_COUNT,
)
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

add_copaw_file_handler() now uses a plain FileHandler on Linux, which disables log rotation entirely and can let copaw.log grow without bound. If the file-locking issue is Windows-specific, consider limiting the non-rotating handler to Windows and keeping RotatingFileHandler for Linux (or implement rotation another way on Linux).

Copilot uses AI. Check for mistakes.
Comment on lines +172 to +174
if platform.system() == "Windows":
file_handler.setLevel(logging.INFO)

Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

On Windows the file handler level is forced to INFO, which will drop DEBUG logs even when COPAW_LOG_LEVEL=debug (or --log-level debug) is requested. If this isn’t intentional, prefer leaving the handler at NOTSET (default) or aligning it with the copaw logger’s configured level so file output matches the selected verbosity.

Suggested change
if platform.system() == "Windows":
file_handler.setLevel(logging.INFO)

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +146
set /p CERT_FILE=<"%CERT_TMP%"
del "%CERT_TMP%" 2>nul
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

This set /p CERT_FILE=<"%CERT_TMP%" will print an error (and may behave unexpectedly) if the preceding Python command fails to create the temp file. Consider guarding with if exist "%CERT_TMP%" (...) (and/or clearing CERT_FILE) to avoid noisy startup failures when certifi isn’t importable.

Suggested change
set /p CERT_FILE=<"%CERT_TMP%"
del "%CERT_TMP%" 2>nul
if exist "%CERT_TMP%" (
set /p CERT_FILE=<"%CERT_TMP%"
del "%CERT_TMP%" 2>nul
) else (
set "CERT_FILE="
)

Copilot uses AI. Check for mistakes.
Comment thread src/copaw/app/_app.py

startup_elapsed = time.time() - startup_start_time
logger.debug(
f"Application startup completed in {startup_elapsed:.3f} seconds",
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

This debug log uses an f-string, which formats the message even when debug logging is disabled. Prefer parameterized logging (e.g., logger.debug("... %.3f ...", startup_elapsed)) to avoid unnecessary work on non-debug runs.

Suggested change
f"Application startup completed in {startup_elapsed:.3f} seconds",
"Application startup completed in %.3f seconds",
startup_elapsed,

Copilot uses AI. Check for mistakes.
Comment on lines +194 to +206
echo Log Level: %COPAW_LOG_LEVEL%
echo SSL_CERT_FILE: %SSL_CERT_FILE%
echo REQUESTS_CA_BUNDLE: %REQUESTS_CA_BUNDLE%
echo CURL_CA_BUNDLE: %CURL_CA_BUNDLE%
echo.
if not exist "%USERPROFILE%\.copaw\config.json" (
echo [Init] Creating config...
"%~dp0python.exe" -m copaw init --defaults --accept-security
"%~dp0python.exe" -u -m copaw init --defaults --accept-security
)
echo [Launch] Starting CoPaw Desktop...
echo [Launch] Starting CoPaw Desktop with log-level=%COPAW_LOG_LEVEL%...
echo Press Ctrl+C to stop
echo.
"%~dp0python.exe" -m copaw desktop
"%~dp0python.exe" -u -m copaw desktop --log-level %COPAW_LOG_LEVEL%
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

In the debug launcher, COPAW_LOG_LEVEL is expanded unquoted in multiple places (echo Log Level: %COPAW_LOG_LEVEL%, the [Launch] message, and the python.exe invocation), so a value containing metacharacters like & or | will be parsed by cmd.exe and can inject additional commands. If an attacker can set COPAW_LOG_LEVEL in the environment, they can execute arbitrary commands whenever this debug launcher runs, both during the echo diagnostics and when starting Python. Quote the COPAW_LOG_LEVEL expansions in these lines (including the --log-level argument) so that they are treated as a single literal argument/value rather than command syntax.

Copilot uses AI. Check for mistakes.
"%~dp0python.exe" -u -m copaw init --defaults --accept-security
)
"%~dp0python.exe" -m copaw desktop
"%~dp0python.exe" -u -m copaw desktop --log-level %COPAW_LOG_LEVEL%
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

The value of COPAW_LOG_LEVEL is interpolated unquoted into the python.exe command line, so a crafted value containing characters like &, | or > will be interpreted by cmd.exe and can inject additional commands. An attacker who can influence the environment (e.g., set COPAW_LOG_LEVEL) could cause arbitrary commands to execute when the launcher runs instead of just passing a log-level argument to Python. Quote the log-level argument (for example, by passing it as a single quoted token to --log-level) so that cmd.exe treats the entire value as data rather than part of the command syntax.

Suggested change
"%~dp0python.exe" -u -m copaw desktop --log-level %COPAW_LOG_LEVEL%
"%~dp0python.exe" -u -m copaw desktop --log-level "%COPAW_LOG_LEVEL%"

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
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 several enhancements, primarily focused on improving the build process and runtime behavior on Windows, as well as fixing SSL certificate handling for the desktop application. Key changes include updating the build scripts for both macOS and Windows to correctly set the PATH, handle log levels, and more robustly determine the SSL certificate path. The Windows build script now uses a temporary file to capture Python script output, avoiding potential hangs. In the Python code, the desktop command now uses threaded stream readers to prevent subprocess output buffers from blocking on Windows, and the logging utility has been updated to use FileHandler on Windows and Linux to prevent file locking issues. My review includes a couple of suggestions to improve code clarity and error handling for better maintainability.

Note: Security Review is unavailable for this PR.

Comment on lines +73 to +74
except Exception:
pass
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Silently passing on all exceptions with except Exception: pass can hide bugs and make debugging difficult. It's better to at least log the exception to be aware of potential issues, especially during development. Consider logging the exception using the _log_desktop function.

Suggested change
except Exception:
pass
except Exception as e:
_log_desktop(f'[_stream_reader] Error reading from subprocess stream: {e!r}')

Comment on lines +157 to +173
is_windows_or_linux = platform.system() in ("Windows", "Linux")
if is_windows_or_linux:
file_handler = logging.FileHandler(
log_path,
encoding="utf-8",
mode="a",
)
else:
file_handler = logging.handlers.RotatingFileHandler(
log_path,
encoding="utf-8",
maxBytes=_COPAW_LOG_MAX_BYTES,
backupCount=_COPAW_LOG_BACKUP_COUNT,
)

if platform.system() == "Windows":
file_handler.setLevel(logging.INFO)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The call to platform.system() is made twice. It's more efficient and readable to call it once and store the result in a variable for later use. This avoids redundant system calls and simplifies the logic.

Suggested change
is_windows_or_linux = platform.system() in ("Windows", "Linux")
if is_windows_or_linux:
file_handler = logging.FileHandler(
log_path,
encoding="utf-8",
mode="a",
)
else:
file_handler = logging.handlers.RotatingFileHandler(
log_path,
encoding="utf-8",
maxBytes=_COPAW_LOG_MAX_BYTES,
backupCount=_COPAW_LOG_BACKUP_COUNT,
)
if platform.system() == "Windows":
file_handler.setLevel(logging.INFO)
system = platform.system()
if system in ("Windows", "Linux"):
file_handler = logging.FileHandler(
log_path,
encoding="utf-8",
mode="a",
)
else:
file_handler = logging.handlers.RotatingFileHandler(
log_path,
encoding="utf-8",
maxBytes=_COPAW_LOG_MAX_BYTES,
backupCount=_COPAW_LOG_BACKUP_COUNT,
)
if system == "Windows":
file_handler.setLevel(logging.INFO)

@xieyxclack xieyxclack merged commit 852cc7d into agentscope-ai:main Mar 11, 2026
24 checks passed
hh0592821 pushed a commit to hh0592821/CoPaw that referenced this pull request Mar 12, 2026
tudan110 pushed a commit to tudan110/QwenPaw that referenced this pull request Apr 4, 2026
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.

3 participants