This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

1#!/usr/bin/env python3 2"""Cloud Run Job entrypoint: generate AI-solve questionnaire for one issue.""" 3 4from __future__ import annotations 5 6import argparse 7import json 8import os 9import sys 10 11from dotenv import load_dotenv 12 13from agent.agent import generate_and_save_questionnaire 14from agent.load_issue import resolve_issue_uri 15 16 17def load_env() -> None: 18 load_dotenv() 19 20 21def require_env(name: str) -> str: 22 value = os.getenv(name, "").strip() 23 if not value: 24 print(f"ERROR: {name} is not set", file=sys.stderr) 25 raise SystemExit(1) 26 return value 27 28 29def main(argv: list[str] | None = None) -> None: 30 parser = argparse.ArgumentParser( 31 description="Generate and cache an AI-solve questionnaire for a Tangled issue." 32 ) 33 parser.add_argument( 34 "issue_id", 35 nargs="?", 36 help="Issue at:// URI or rkey (rkey requires DB lookup)", 37 ) 38 parser.add_argument( 39 "--issue-uri", 40 metavar="URI", 41 help="Full at:// issue URI (overrides positional issue_id)", 42 ) 43 parser.add_argument( 44 "--issue-id", 45 metavar="ID", 46 dest="issue_id_flag", 47 help="Same as positional: at:// URI or rkey", 48 ) 49 parser.add_argument( 50 "--no-file-tree", 51 action="store_true", 52 help="Skip knot file-tree walk before generation", 53 ) 54 parser.add_argument( 55 "--list-tool", 56 action="store_true", 57 help="Expose list_repo_files in addition to read_repo_file", 58 ) 59 parser.add_argument( 60 "--no-save", 61 action="store_true", 62 help="Print questionnaire JSON only; do not write to Postgres", 63 ) 64 args = parser.parse_args(argv) 65 66 load_env() 67 require_env("DB_CONNECTION_STRING") 68 require_env("ANTHROPIC_API_KEY") 69 70 raw = ( 71 args.issue_uri 72 or args.issue_id_flag 73 or args.issue_id 74 or os.getenv("ISSUE_URI", "").strip() 75 or os.getenv("ISSUE_ID", "").strip() 76 ) 77 if not raw: 78 print( 79 "ERROR: provide issue id via arg, --issue-uri, ISSUE_URI, or ISSUE_ID", 80 file=sys.stderr, 81 ) 82 raise SystemExit(1) 83 84 issue_uri = resolve_issue_uri(raw) 85 print(f"[job] generating questionnaire for {issue_uri}", file=sys.stderr) 86 87 result = generate_and_save_questionnaire( 88 issue_uri, 89 fetch_file_tree=not args.no_file_tree, 90 include_list_tool=args.list_tool, 91 thread_id=f"job-{issue_uri.rsplit('/', 1)[-1]}", 92 save=not args.no_save, 93 ) 94 95 if args.no_save and "payload" in result: 96 print(json.dumps(result["payload"], indent=2, ensure_ascii=False)) 97 else: 98 print(json.dumps(result, indent=2)) 99 if args.no_save: 100 print( 101 f"[job] done (no-save) version={result.get('version')} " 102 f"questions={result.get('question_count')}", 103 file=sys.stderr, 104 ) 105 else: 106 print( 107 f"[job] saved version={result.get('version')} " 108 f"questions={result.get('question_count')} " 109 f"updated_at={result.get('updated_at')}", 110 file=sys.stderr, 111 ) 112 113 114if __name__ == "__main__": 115 try: 116 main() 117 except KeyboardInterrupt: 118 print("\nInterrupted.", file=sys.stderr) 119 raise SystemExit(130) from None