()
| 305 | |
| 306 | |
| 307 | def main() -> int: |
| 308 | ap = argparse.ArgumentParser(description=__doc__) |
| 309 | win = ap.add_mutually_exclusive_group() |
| 310 | win.add_argument("--days", type=int, help="lookback window in days (default: 2)") |
| 311 | win.add_argument("--hours", type=int, help="lookback window in hours") |
| 312 | ap.add_argument( |
| 313 | "--agent", |
| 314 | choices=("codex", "claude"), |
| 315 | default="codex", |
| 316 | help="local coding agent to invoke", |
| 317 | ) |
| 318 | ap.add_argument( |
| 319 | "--dry-run", |
| 320 | action="store_true", |
| 321 | help="print aggregated summary as JSON and exit (no agent call)", |
| 322 | ) |
| 323 | ap.add_argument( |
| 324 | "--out", |
| 325 | default="-", |
| 326 | help="write agent response here (default: stdout)", |
| 327 | ) |
| 328 | ap.add_argument( |
| 329 | "-v", "--verbose", action="store_true", help="log query progress to stderr" |
| 330 | ) |
| 331 | args = ap.parse_args() |
| 332 | |
| 333 | logging.basicConfig( |
| 334 | level=logging.INFO if args.verbose else logging.WARNING, |
| 335 | format="%(message)s", |
| 336 | stream=sys.stderr, |
| 337 | ) |
| 338 | |
| 339 | token = os.environ.get("BETTER_STACK_TOKEN", "").strip() |
| 340 | if not token: |
| 341 | raise SystemExit( |
| 342 | "BETTER_STACK_TOKEN not set. Run `set -a; . .env; set +a` first." |
| 343 | ) |
| 344 | if ":" not in token: |
| 345 | log.warning( |
| 346 | "BETTER_STACK_TOKEN does not look like 'user:pass'; " |
| 347 | "Basic auth may fail. See betterstack.txt." |
| 348 | ) |
| 349 | |
| 350 | if args.hours is not None: |
| 351 | n, unit, window = args.hours, "HOUR", f"{args.hours} hour(s)" |
| 352 | else: |
| 353 | days = args.days if args.days is not None else 2 |
| 354 | n, unit, window = days, "DAY", f"{days} day(s)" |
| 355 | |
| 356 | summary = collect(token, n, unit) |
| 357 | |
| 358 | if args.dry_run: |
| 359 | json.dump(summary, sys.stdout, indent=2, ensure_ascii=False) |
| 360 | sys.stdout.write("\n") |
| 361 | return 0 |
| 362 | |
| 363 | prompt = build_prompt(window, summary) |
| 364 | response = run_agent(args.agent, prompt) |
no test coverage detected