-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexplore_program.py
108 lines (85 loc) · 3.25 KB
/
explore_program.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import subprocess
import sys
import json
import logging
# Set up logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
stream=sys.stderr,
)
def run_help_command(command):
logging.info(f"Running command: {' '.join(command)}")
try:
result = subprocess.run(command, capture_output=True, text=True, check=True)
logging.debug(f"Command output: {result.stdout}")
return result.stdout
except subprocess.CalledProcessError as e:
logging.error(f"Error running command {' '.join(command)}: {e}")
return None
def get_subcommands(program, args):
command = [program] + args + ["--help"]
help_output = run_help_command(command)
if help_output is None:
logging.warning(f"No help output for command: {' '.join(command)}")
return []
cody_prompt = (
"Analyze this help output and return a JSON object with two keys: "
"'has_subcommands' (boolean) and 'subcommands' (list of strings). "
"If there are no subcommands, return an empty list for 'subcommands'. "
"Only return the JSON object, no other text. Ignore any `help` subcommands."
)
logging.info("Sending help output to Cody for analysis")
try:
cody_result = subprocess.run(
[
"cody",
"chat",
"--stdin",
cody_prompt,
],
input=help_output,
capture_output=True,
text=True,
check=True,
)
cody_output = cody_result.stdout.strip()
logging.debug(f"Cody output: {cody_output}")
subcommand_data = json.loads(cody_output)
subcommands = subcommand_data.get("subcommands", [])
logging.info(f"Found subcommands: {subcommands}")
return subcommands
except (subprocess.CalledProcessError, json.JSONDecodeError) as e:
logging.error(f"Error processing subcommands: {e}")
if isinstance(e, subprocess.CalledProcessError):
logging.error(f"stderr: {e.stderr}")
logging.error(f"stdout: {e.stdout}")
return []
def explore_command(program, args=None, depth=0):
if args is None:
args = []
logging.info(f"Exploring command: {program} {' '.join(args)}")
command = [program] + args + ["--help"]
help_output = run_help_command(command)
if help_output is None:
logging.warning(f"No help output for command: {' '.join(command)}")
return ""
markdown = f"{'#' * (depth + 2)} {' '.join([program] + args)}\n\n"
markdown += "```\n" + help_output.strip() + "\n```\n\n"
subcommands = get_subcommands(program, args)
for subcommand in subcommands:
markdown += explore_command(program, args + [subcommand], depth + 1)
return markdown
def main():
if len(sys.argv) != 2:
logging.error("Invalid number of arguments")
print("Usage: python explore_program.py <program_name>", file=sys.stderr)
sys.exit(1)
program = sys.argv[1]
logging.info(f"Starting exploration of program: {program}")
markdown = f"# {program} Help\n\n"
markdown += explore_command(program)
print(markdown)
logging.info("Exploration completed")
if __name__ == "__main__":
main()