Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ jobs:
- name: Run installation test
run: |
python test_installation.py

- name: Upload audit reports
if: always()
uses: actions/upload-artifact@v3
with:
name: audit-reports
path: audit_reports/

- name: Generate coverage report
run: |
Expand Down Expand Up @@ -167,4 +174,32 @@ jobs:

- name: Notify on failure
if: ${{ needs.test.result == 'failure' }}
run: echo "❌ Tests failed. Please check the logs."
run: echo "❌ Tests failed. Please check the logs."

supply-chain:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Generate SBOM
run: |
pip install cyclonedx-bom
cyclonedx-py --format json --output sbom.json

- name: Scan secrets
uses: gitleaks/gitleaks-action@v2
with:
args: '--no-git --path .'

- name: CVE audit
run: |
pip install pip-audit
pip-audit > cve-report.txt || true

- name: Upload supply-chain artifacts
uses: actions/upload-artifact@v3
with:
name: supply-chain
path: |
sbom.json
cve-report.txt
24 changes: 24 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Release

on:
push:
tags: ['v*']

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Build wheel
run: |
pip install build
python -m build
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: wheel
path: dist/*.whl
14 changes: 14 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
repos:
- repo: https://github.com/psf/black
rev: 24.3.0
hooks:
- id: black
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.4
hooks:
- id: ruff
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
5 changes: 5 additions & 0 deletions .secrets.baseline
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"version": "1.0.0",
"plugins_used": [],
"results": {}
}
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog

## 0.1.0 - 2024-06-12
- add config validation with Pydantic
- integrate Windows secret store
- sanitize logs and enforce retention
- GPU auto-detection for STT/TTS with healthcheck
- rate limiting and retry utilities
- PowerShell hardening and CI supply-chain jobs
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Jarvis Windows Agent

![CI](https://github.com/CursorTouch/AI_Agents/actions/workflows/ci.yml/badge.svg)

Jarvis is an autonomous agent for Windows automation, integrating voice, web, and desktop controls.

## Security & Compliance
- Default automation mode is **ASSISTIVE**; other modes are documented in [Security Modes](docs/SECURITY_MODES.md).
- Secrets are stored via Windows Credential Manager; see [SECRETS.md](docs/SECRETS.md).
- Logs are sanitized and rotated every 14 days. Use `scripts/healthcheck.py` to inspect device providers.

## Healthcheck
```bash
python scripts/healthcheck.py
```
4 changes: 4 additions & 0 deletions audit_reports/ACTION_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
- Resolve `jarvis_demo.py` syntax error to restore build.

## P1 – Near Term
codex/conduct-comprehensive-audit-for-jarvis-ai-project-8yncbg
- Implement `obs/device_telemetry.py` and `scripts/healthcheck.py` for CPU/GPU metrics.
=======
- Implement `utils/device_telemetry.py` and `scripts/healthcheck.py` for CPU/GPU metrics.
main
- Add CI workflow running `ruff`, `black --check`, `mypy`, `pytest` (skip Office if unavailable).
- Refactor large modules (`web_form_automation.py`, `hitl.py`).
- Ensure `personality_state.json` and other runtime data are gitignored.
Expand Down
8 changes: 8 additions & 0 deletions audit_reports/CPU_GPU_TELEMETRY_GAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@

## Recommended Patches
```python
codex/conduct-comprehensive-audit-for-jarvis-ai-project-8yncbg
# obs/device_telemetry.py (new)
=======
# utils/device_telemetry.py (new)
main
import psutil, json

def snapshot() -> dict:
Expand All @@ -19,7 +23,11 @@ def snapshot() -> dict:
```
```python
# scripts/healthcheck.py (new)
codex/conduct-comprehensive-audit-for-jarvis-ai-project-8yncbg
from obs.device_telemetry import snapshot
=======
from utils.device_telemetry import snapshot
main

if __name__ == "__main__":
stats = snapshot()
Expand Down
25 changes: 14 additions & 11 deletions config/logging.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,33 @@ handlers:
stream: ext://sys.stdout

file:
class: logging.handlers.RotatingFileHandler
class: logging.handlers.TimedRotatingFileHandler
level: DEBUG
formatter: detailed
filename: logs/jarvis.log
maxBytes: 10485760 # 10MB
backupCount: 5
when: D
interval: 1
backupCount: 14
encoding: utf8

error_file:
class: logging.handlers.RotatingFileHandler
class: logging.handlers.TimedRotatingFileHandler
level: ERROR
formatter: detailed
filename: logs/jarvis_errors.log
maxBytes: 10485760 # 10MB
backupCount: 3
when: D
interval: 1
backupCount: 14
encoding: utf8

performance_file:
class: logging.handlers.RotatingFileHandler
class: logging.handlers.TimedRotatingFileHandler
level: DEBUG
formatter: json
filename: logs/jarvis_performance.log
maxBytes: 10485760 # 10MB
backupCount: 3
when: D
interval: 1
backupCount: 14
encoding: utf8
filters: [performance]

Expand Down
4 changes: 4 additions & 0 deletions config/models.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
planner: gpt-4
judge: gpt-4
offline: small
vision: null
5 changes: 5 additions & 0 deletions config/security.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mode_default: ASSISTIVE
web:
allowlist:
- example.com
require_confirm_on_submit: true
18 changes: 18 additions & 0 deletions docs/SECRETS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Secrets Management

Jarvis uses the Windows Credential Manager via the `secret_store` module to keep API keys and tokens out of source control.

## Storing a Secret
```python
from windows_use.security.secret_store import set_secret
set_secret("OPENAI_API_KEY", "sk-...")
```

## Using a Secret in Config
`security.yaml` values can reference `${OPENAI_API_KEY}`. If the environment variable is not set, the loader resolves it from the secret store.

## Rotation
Update the secret with `set_secret` and restart the agent. Use `delete_secret` to remove old keys.

## Auditing
Secrets are never logged. Review access through Windows Credential Manager's audit logs.
9 changes: 9 additions & 0 deletions docs/SECURITY_MODES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Security Modes

| Mode | Description | Typical Use |
| --- | --- | --- |
| ASSISTIVE | Requires explicit user confirmation before actions that modify state. | Safe default for day-to-day use. |
| SEMI_AUTO | Proceeds with predefined checkpoints; user confirmation needed for critical steps or when OTP/CAPTCHA detected. | Batch tasks with oversight. |
| FULL_AUTO | Executes actions without user intervention. Should only run in controlled environments. | Trusted, sandboxed automation. |

Actions submitted in ASSISTIVE and SEMI_AUTO modes must be confirmed when `require_confirm_on_submit` is enabled.
17 changes: 17 additions & 0 deletions docs/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Troubleshooting

## GPU Not Detected
- Ensure CUDA drivers are installed.
- Set `JARVIS_STT_DEVICE=cuda` to force GPU for Whisper.

## Playwright Failures
- Install browsers with `playwright install`.
- Check allowlist and network access.

## Office COM Crashes
- Verify Microsoft Office is installed and updated.
- Run the agent with administrator privileges if required.

## PowerShell Permission Errors
- Constrained Language Mode may block certain cmdlets.
- Ensure commands are in the whitelist and do not require elevated rights.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "windows-use"
version = "0.1.31"
version = "0.1.0"
description = "An AI Agent that interacts with Windows OS at GUI level."
readme = "readme.md"
authors = [
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ termcolor>=2.3.0
sounddevice>=0.4.6
websockets>=11.0.0
webrtcvad>=2.0.10
keyring>=24.3.0

# Optional Dependencies (install only if needed)
# Voice Recognition (uncomment if voice features needed)
Expand Down
49 changes: 48 additions & 1 deletion scripts/healthcheck.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,49 @@
codex/conduct-comprehensive-audit-for-jarvis-ai-project-8yncbg
from __future__ import annotations

import json
import os
import time

try:
import torch
except Exception: # pragma: no cover
torch = None

try:
import onnxruntime as ort
except Exception: # pragma: no cover
ort = None


def main() -> None:
providers = []
if ort:
providers = ort.get_available_providers()
gpu = "CPU"
if torch and torch.cuda.is_available():
gpu = torch.cuda.get_device_name(0)
stt_device = os.getenv("JARVIS_STT_DEVICE", "auto")

info = {"providers": providers, "gpu": gpu, "stt_device": stt_device}
print(json.dumps(info, indent=2))

try:
import ollama # type: ignore

start = time.time()
ollama.generate(
model="llama2", prompt="healthcheck", options={"num_predict": 10}
)
latency = time.time() - start
print(f"Ollama generated 10 tokens in {latency:.2f}s")
except Exception as e: # pragma: no cover - ollama optional
print(f"Ollama check skipped: {e}")


if __name__ == "__main__":
main()
=======
#!/usr/bin/env python3
"""Health Check Script for Jarvis AI System

Expand Down Expand Up @@ -544,4 +590,5 @@ def main():


if __name__ == '__main__':
main()
main()
main
55 changes: 55 additions & 0 deletions src/windows_use/config_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from __future__ import annotations

import os
import re
from pathlib import Path
from typing import Any, Dict

import yaml

from .config_schema import ModelsConfig, SecurityConfig
from .security.secret_store import get_secret


_ENV_PATTERN = re.compile(r"\$\{([^}]+)\}")


def _resolve(value: Any) -> Any:
if isinstance(value, str):
match = _ENV_PATTERN.fullmatch(value)
if match:
name = match.group(1)
return os.getenv(name) or get_secret(name)
return value


def _load_yaml(path: Path) -> Dict[str, Any]:
with path.open("r", encoding="utf-8") as f:
data = yaml.safe_load(f) or {}
return _traverse(data)


def _traverse(obj: Any) -> Any:
if isinstance(obj, dict):
return {k: _traverse(v) for k, v in obj.items()}
if isinstance(obj, list):
return [_traverse(v) for v in obj]
return _resolve(obj)


def load_security_config(path: str | Path = "config/security.yaml") -> SecurityConfig:
data = _load_yaml(Path(path))
config = SecurityConfig(**data)
if not config.web.allowlist:
raise ValueError("allowlist must not be empty")
if config.mode_default != config.mode_default.__class__.ASSISTIVE:
raise ValueError("mode_default must be ASSISTIVE")
return config


def load_models_config(path: str | Path = "config/models.yaml") -> ModelsConfig:
data = _load_yaml(Path(path))
config = ModelsConfig(**data)
if not config.offline:
config.offline = "safe"
return config
Loading
Loading