qwen_agent/skills/competitor-news-intel/scripts/intel_cli.py
2026-04-16 10:23:54 +08:00

205 lines
7.2 KiB
Python

#!/usr/bin/env python3
import argparse
import json
import sys
from datetime import datetime, UTC
from intel_core import (
analyze_events,
validate_analyze_payload,
validate_collect_payload,
validate_run_payload,
)
from search_provider import (
InvalidSearchInputError,
MissingAPIKeyError,
SearchProviderError,
UnsupportedProviderError,
UpstreamHTTPError,
collect_events,
)
ERROR_TEMPLATE = {
"success": False,
"code": "invalid_input",
"message": "",
"data": {},
"meta": {},
"errors": [],
}
def _now_iso() -> str:
return datetime.now(UTC).isoformat()
def _emit(data: dict, pretty: bool, stream=None):
print(json.dumps(data, ensure_ascii=False, indent=2 if pretty else None), file=stream or sys.stdout)
def _error_response(code: str, message: str, errors: list[str] | None = None) -> dict:
return {
**ERROR_TEMPLATE,
"code": code,
"message": message,
"meta": {"generated_at": _now_iso()},
"errors": errors or [],
}
def _load_payload(raw: str) -> dict:
return json.loads(raw)
def _override_search(payload: dict, args: argparse.Namespace) -> dict:
payload.setdefault("data", {})
payload["data"].setdefault("search", {})
if getattr(args, "provider", None):
payload["data"]["search"]["provider"] = args.provider
if getattr(args, "freshness", None):
payload["data"]["search"]["freshness"] = args.freshness
if getattr(args, "count", None) is not None:
payload["data"]["search"]["count"] = args.count
if getattr(args, "max_events", None) is not None:
payload["max_events"] = args.max_events
return payload
def cmd_collect(args: argparse.Namespace):
payload = _override_search(_load_payload(args.input_json), args)
errors = validate_collect_payload(payload)
if errors:
_emit(_error_response("invalid_input", "payload invalid", errors), args.pretty, sys.stderr)
raise SystemExit(1)
events = collect_events(payload)
result = {
"success": True,
"code": "ok",
"message": "events collected",
"data": {"developments": events},
"meta": {"generated_at": _now_iso(), "source_count": len(events)},
"errors": [],
}
_emit(result, args.pretty)
def cmd_analyze(args: argparse.Namespace):
payload = _override_search(_load_payload(args.input_json), args)
errors = validate_analyze_payload(payload)
if errors:
_emit(_error_response("invalid_input", "payload invalid", errors), args.pretty, sys.stderr)
raise SystemExit(1)
events = payload.get("data", {}).get("developments", [])
data = analyze_events(payload, events)
result = {
"success": True,
"code": "ok",
"message": "intelligence analyzed",
"data": data,
"meta": {
"generated_at": _now_iso(),
"raw_count": data.get("stats", {}).get("raw_count", len(events)),
"dedup_count": data.get("stats", {}).get("dedup_count", len(events)),
"returned_count": data.get("stats", {}).get("returned_count", len(data.get("developments", []))),
},
"errors": [],
}
if args.output == "markdown":
print(data["markdown"])
return
_emit(result, args.pretty)
def cmd_run(args: argparse.Namespace):
payload = _override_search(_load_payload(args.input_json), args)
errors = validate_run_payload(payload)
if errors:
_emit(_error_response("invalid_input", "payload invalid", errors), args.pretty, sys.stderr)
raise SystemExit(1)
events = collect_events(payload)
data = analyze_events(payload, events)
result = {
"success": True,
"code": "ok",
"message": "intelligence brief generated",
"data": data,
"meta": {
"generated_at": _now_iso(),
"raw_count": data.get("stats", {}).get("raw_count", len(events)),
"dedup_count": data.get("stats", {}).get("dedup_count", len(events)),
"returned_count": data.get("stats", {}).get("returned_count", len(data.get("developments", []))),
},
"errors": [],
}
if args.output == "markdown":
print(data["markdown"])
return
_emit(result, args.pretty)
def cmd_plan_recurring(args: argparse.Namespace):
payload = _override_search(_load_payload(args.input_json), args)
errors = validate_run_payload(payload)
if errors:
_emit(_error_response("invalid_input", "payload invalid", errors), args.pretty, sys.stderr)
raise SystemExit(1)
data = analyze_events(payload, [])
result = {
"success": True,
"code": "ok",
"message": "recurring plan generated",
"data": {"schedule_payload": data["schedule_payload"]},
"meta": {"generated_at": _now_iso()},
"errors": [],
}
_emit(result, args.pretty)
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="Generate competitor intelligence")
subparsers = parser.add_subparsers(dest="command", required=True)
for name in ["collect", "analyze", "run", "plan-recurring"]:
sub = subparsers.add_parser(name)
sub.add_argument("--input-json", required=True)
sub.add_argument("--provider")
sub.add_argument("--freshness")
sub.add_argument("--count", type=int)
sub.add_argument("--max-events", type=int)
sub.add_argument("--pretty", action="store_true")
if name in {"analyze", "run"}:
sub.add_argument("--output", choices=["json", "markdown"], default="json")
subparsers.choices["collect"].set_defaults(func=cmd_collect)
subparsers.choices["analyze"].set_defaults(func=cmd_analyze)
subparsers.choices["run"].set_defaults(func=cmd_run)
subparsers.choices["plan-recurring"].set_defaults(func=cmd_plan_recurring)
return parser
if __name__ == "__main__":
parser = build_parser()
args = parser.parse_args()
try:
args.func(args)
except json.JSONDecodeError as exc:
_emit(_error_response("invalid_input", f"invalid json: {exc}", [str(exc)]), getattr(args, "pretty", False), sys.stderr)
raise SystemExit(1)
except MissingAPIKeyError as exc:
_emit(_error_response("missing_api_key", str(exc), [str(exc)]), getattr(args, "pretty", False), sys.stderr)
raise SystemExit(1)
except UnsupportedProviderError as exc:
_emit(_error_response("unsupported_provider", str(exc), [str(exc)]), getattr(args, "pretty", False), sys.stderr)
raise SystemExit(1)
except InvalidSearchInputError as exc:
_emit(_error_response("invalid_input", str(exc), [str(exc)]), getattr(args, "pretty", False), sys.stderr)
raise SystemExit(1)
except UpstreamHTTPError as exc:
_emit(_error_response("upstream_http_error", str(exc), [str(exc)]), getattr(args, "pretty", False), sys.stderr)
raise SystemExit(1)
except SearchProviderError as exc:
_emit(_error_response("provider_error", str(exc), [str(exc)]), getattr(args, "pretty", False), sys.stderr)
raise SystemExit(1)
except Exception as exc:
_emit(_error_response("internal_error", "unexpected error", [str(exc)]), getattr(args, "pretty", False), sys.stderr)
raise SystemExit(1)