add zeroclaw hardware preflight and orchestration docs (#19)
This commit was merged in pull request #19.
This commit is contained in:
@@ -218,6 +218,11 @@ _pkginfo.txt
|
||||
|
||||
# Visual Studio cache files
|
||||
*.[Cc]ache
|
||||
|
||||
# ZeroClaw local runtime (generated locally, never committed)
|
||||
/.zeroclaw/
|
||||
/config.toml
|
||||
/workspace/
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
|
||||
@@ -79,6 +79,14 @@ _Agent Repo & GitHub – README généré automatiquement._
|
||||
5. Ouvrir le moniteur série à 115200 bauds.
|
||||
6. Connecter puis piloter les appels via commandes série.
|
||||
|
||||
## Orchestration ZeroClaw (préflight + agent)
|
||||
|
||||
- Guide: `docs/zeroclaw_orchestration.md`
|
||||
- Préflight hardware avant upload:
|
||||
- `python3 scripts/zeroclaw_hw_preflight.py --require-port`
|
||||
- Conversation agent ciblée RTC (depuis `Kill_LIFE`):
|
||||
- `tools/ai/zeroclaw_dual_chat.sh rtc -m "fais un état hardware et propose 3 actions"`
|
||||
|
||||
## Commandes série
|
||||
- `h` : aide
|
||||
- `s` : statut runtime (hook, HFP, audio, call)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# Orchestration ZeroClaw (RTC)
|
||||
|
||||
Dernière mise à jour: 2026-02-21.
|
||||
|
||||
## Objectif
|
||||
|
||||
Rendre les boucles hardware RTC plus robustes:
|
||||
|
||||
- préflight USB obligatoire avant upload/flash,
|
||||
- session agent ZeroClaw ciblée sur le repo RTC,
|
||||
- exécution coordonnée avec `Kill_LIFE` (orchestrateur dual-repo).
|
||||
|
||||
## 1) Préflight hardware local
|
||||
|
||||
Lancer avant `autoflash.py`, `hw_validation.py` ou tout upload PlatformIO:
|
||||
|
||||
```bash
|
||||
python3 scripts/zeroclaw_hw_preflight.py --zeroclaw-bin /Users/cils/Documents/Lelectron_rare/Kill_LIFE/zeroclaw/target/release/zeroclaw --require-port
|
||||
```
|
||||
|
||||
Variantes:
|
||||
|
||||
```bash
|
||||
python3 scripts/zeroclaw_hw_preflight.py --port /dev/tty.SLAB_USBtoUART
|
||||
python3 scripts/zeroclaw_hw_preflight.py --port /dev/tty.usbserial-0001 --port /dev/tty.usbmodem5AB90753301
|
||||
```
|
||||
|
||||
## 2) Conversation agent ciblée RTC
|
||||
|
||||
Depuis `Kill_LIFE`:
|
||||
|
||||
```bash
|
||||
tools/ai/zeroclaw_dual_chat.sh rtc -m "fais un état hardware et propose 3 actions"
|
||||
```
|
||||
|
||||
Si credentials manquants, choisir un provider:
|
||||
|
||||
- `zeroclaw auth login --provider openai-codex --device-code`
|
||||
- ou `export OPENROUTER_API_KEY=... && export ZEROCLAW_PROVIDER=openrouter`
|
||||
|
||||
## 3) Boucle recommandée (issue -> PR)
|
||||
|
||||
1. Préflight USB (`zeroclaw_hw_preflight.py`).
|
||||
2. Prompt court RTC.
|
||||
3. Patch minimal RTC.
|
||||
4. Tests locaux ciblés.
|
||||
5. PR dédiée RTC avec logs/artefacts.
|
||||
Executable
+102
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run ZeroClaw USB discovery/introspection before hardware actions."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import glob
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def resolve_bin(requested: str) -> str:
|
||||
if os.path.sep in requested:
|
||||
if not Path(requested).exists():
|
||||
raise FileNotFoundError(f"ZeroClaw binary not found: {requested}")
|
||||
return requested
|
||||
resolved = shutil.which(requested)
|
||||
if not resolved:
|
||||
raise FileNotFoundError(
|
||||
"ZeroClaw binary not found in PATH. Set --zeroclaw-bin explicitly."
|
||||
)
|
||||
return resolved
|
||||
|
||||
|
||||
def default_ports() -> list[str]:
|
||||
patterns = [
|
||||
"/dev/tty.SLAB_USBtoUART",
|
||||
"/dev/tty.usbserial-*",
|
||||
"/dev/tty.usbmodem*",
|
||||
]
|
||||
ports: list[str] = []
|
||||
for pattern in patterns:
|
||||
ports.extend(glob.glob(pattern))
|
||||
return sorted(set(ports))
|
||||
|
||||
|
||||
def run_command(cmd: list[str]) -> int:
|
||||
print(f"$ {' '.join(cmd)}")
|
||||
proc = subprocess.run(cmd, check=False)
|
||||
return proc.returncode
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="ZeroClaw preflight for RTC hardware sessions."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--zeroclaw-bin",
|
||||
default=os.environ.get("ZEROCLAW_BIN", "zeroclaw"),
|
||||
help="Path/name of zeroclaw binary (default: zeroclaw in PATH).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--port",
|
||||
action="append",
|
||||
default=[],
|
||||
help="Explicit serial port to introspect (repeatable).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--require-port",
|
||||
action="store_true",
|
||||
help="Fail if no serial port candidate is detected.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
zc_bin = resolve_bin(args.zeroclaw_bin)
|
||||
except FileNotFoundError as exc:
|
||||
print(f"[fail] {exc}", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
if run_command([zc_bin, "hardware", "discover"]) != 0:
|
||||
print("[fail] zeroclaw hardware discover failed", file=sys.stderr)
|
||||
return 3
|
||||
|
||||
ports = args.port if args.port else default_ports()
|
||||
if not ports:
|
||||
message = "[warn] no candidate serial ports detected."
|
||||
if args.require_port:
|
||||
print(message, file=sys.stderr)
|
||||
return 4
|
||||
print(message)
|
||||
return 0
|
||||
|
||||
failures = 0
|
||||
for port in ports:
|
||||
rc = run_command([zc_bin, "hardware", "introspect", port])
|
||||
if rc != 0:
|
||||
failures += 1
|
||||
|
||||
if failures:
|
||||
print(f"[fail] introspection failed on {failures} port(s).", file=sys.stderr)
|
||||
return 5
|
||||
|
||||
print("[ok] zeroclaw hardware preflight passed.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user