Skip to content

feat: add Windows UI Automation support and adb-mcp#16

Open
3338682145 wants to merge 2 commits intoEinsia:mainfrom
3338682145:feat/windows-uia-support
Open

feat: add Windows UI Automation support and adb-mcp#16
3338682145 wants to merge 2 commits intoEinsia:mainfrom
3338682145:feat/windows-uia-support

Conversation

@3338682145
Copy link
Copy Markdown

Summary

This PR adds Windows support to OpenChronicle by replacing only the OS
capture layer and keeping the existing memory pipeline intact.

What changed

  • Added a Windows UI Automation capture adapter that emits JSON compatible
    with the existing capture buffer format.
  • Added polling-based Windows capture flow, without low-level hooks.
  • Kept macOS capture path intact and unchanged in behavior.
  • Added Windows process / path compatibility for start, status, and
    stop.
  • Default data root on Windows is %LOCALAPPDATA%\OpenChronicle.
  • Added install.ps1 for Windows 11 install and startup.
  • Added UTF-8 file I/O fixes and a short os.replace retry for Windows
    file writes.
  • Updated docs for Windows 11, UIA polling, and data directory behavior.
  • Added Windows support tests.

Verification

  • uv run pytest --basetemp pytest-temp-pr
  • uv run ruff check src/openchronicle/capture/windows_uia.py tests/ test_windows_support.py
  • python -m compileall src

Results:

  • 105 passed, 1 skipped
  • targeted ruff passed
  • compileall passed

Notes

  • Full ruff check still has 7 pre-existing lint issues in unrelated test
    files.
  • This PR intentionally does not remove macOS support.
  • Windows capture is polling-based for now, not hook-based.
    Title: Add Android ADB Control MCP server with OpenChronicle memory logging

Summary:

  • Adds a separate openchronicle adb-mcp stdio MCP server for safe Android ADB control.
  • Exposes device listing, screenshot, UI dump, tap, swipe, text input, keyevent, current app,
    app launch, and logcat tools.
  • Records every ADB tool attempt into OpenChronicle daily event memory using existing store
    APIs.
  • Adds safety.py denylist for destructive, privileged, and system-mutating ADB commands.
  • Documents Windows 11/WSL2 setup and Codex/Claude MCP configuration in README_ADB_AGENT.md.

Validation:

  • uv run pytest --basetemp .pytest_cache\full-test-tmp-2
  • uv run python -m compileall src\openchronicle\adb src\openchronicle\mcp\adb_server.py
  • E:\ai\product.tooling\platform-tools\adb.exe devices -l
  • MCP stdio smoke test: list_tools + adb_list_devices successful.

Copy link
Copy Markdown

@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 comprehensive support for Windows 11, enabling cross-platform capture via Windows UI Automation polling alongside the existing macOS event-driven system. Key additions include a new Windows-specific capture provider, a PowerShell installation script, and platform-aware path and process management. Documentation and configuration have been updated to reflect these changes, and file operations now consistently specify UTF-8 encoding. Feedback focuses on improving the robustness of JSON parsing by using read_bytes() instead of read_text() to prevent potential UnicodeDecodeError exceptions.

"""Rewrite a capture JSON without its ``screenshot`` field. Returns True if stripped."""
try:
raw = path.read_text()
raw = path.read_text(encoding="utf-8")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

When parsing JSON files, it is recommended to use read_bytes() instead of read_text(). This allows the json library to handle encoding detection automatically and prevents potential UnicodeDecodeError exceptions, which are a type of ValueError and might not be caught by OSError handlers.

Suggested change
raw = path.read_text(encoding="utf-8")
raw = path.read_bytes()
References
  1. When parsing JSON files, use read_bytes() and pass the result to json.loads() to let the JSON library handle encoding detection and prevent unhandled UnicodeDecodeError exceptions.

Comment thread src/openchronicle/cli.py
return {}
try:
data = json.loads(path.read_text())
data = json.loads(path.read_text(encoding="utf-8"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

When parsing JSON files, it is recommended to use read_bytes() instead of read_text(). This allows the json library to handle encoding detection automatically and prevents potential UnicodeDecodeError exceptions, which are a type of ValueError and may not be caught by OSError handlers.

Suggested change
data = json.loads(path.read_text(encoding="utf-8"))
data = json.loads(path.read_bytes())
References
  1. When parsing JSON files, use read_bytes() and pass the result to json.loads() to let the JSON library handle encoding detection and prevent unhandled UnicodeDecodeError exceptions.

Comment thread src/openchronicle/cli.py
return {}
try:
data = json.loads(path.read_text())
data = json.loads(path.read_text(encoding="utf-8"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

When parsing JSON files, it is recommended to use read_bytes() instead of read_text(). This allows the json library to handle encoding detection automatically and prevents potential UnicodeDecodeError exceptions, which are a type of ValueError and may not be caught by OSError handlers.

Suggested change
data = json.loads(path.read_text(encoding="utf-8"))
data = json.loads(path.read_bytes())
References
  1. When parsing JSON files, use read_bytes() and pass the result to json.loads() to let the JSON library handle encoding detection and prevent unhandled UnicodeDecodeError exceptions.

Comment thread src/openchronicle/cli.py
for p in files:
try:
data = json.loads(p.read_text())
data = json.loads(p.read_text(encoding="utf-8"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

When parsing JSON files, it is recommended to use read_bytes() instead of read_text(). This allows the json library to handle encoding detection automatically and prevents potential UnicodeDecodeError exceptions, which are not caught by the current OSError handler.

Suggested change
data = json.loads(p.read_text(encoding="utf-8"))
data = json.loads(p.read_bytes())
References
  1. When parsing JSON files, use read_bytes() and pass the result to json.loads() to let the JSON library handle encoding detection and prevent unhandled UnicodeDecodeError exceptions.

def _load_capture(path: Path) -> dict[str, Any] | None:
try:
return json.loads(path.read_text())
return json.loads(path.read_text(encoding="utf-8"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

When parsing JSON files, it is recommended to use read_bytes() instead of read_text(). This allows the json library to handle encoding detection automatically and prevents potential UnicodeDecodeError exceptions, which are a type of ValueError and may not be caught by OSError handlers.

Suggested change
return json.loads(path.read_text(encoding="utf-8"))
return json.loads(path.read_bytes())
References
  1. When parsing JSON files, use read_bytes() and pass the result to json.loads() to let the JSON library handle encoding detection and prevent unhandled UnicodeDecodeError exceptions.

@3338682145
Copy link
Copy Markdown
Author

Please feel free to contact us with any questions.

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.

1 participant