-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
154 lines (117 loc) · 4.07 KB
/
main.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import sys
import os
import subprocess
import json
import re
import argparse
from pathlib import Path
from llm import LiteLLMClient
def create_next_app(app_name: str):
"""creates a fresh NextJS app"""
print(f"Creating Next.js app: {app_name}")
process = subprocess.Popen(
f"npx create-next-app@latest {app_name} --yes",
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
stdout, stderr = process.communicate()
if process.returncode != 0:
print(f"Error creating Next.js app: {stderr}")
sys.exit(1)
print(f"Next.js app created successfully at ./{app_name}")
return os.path.abspath(app_name)
def get_file_content(app_path, relative_path):
"""get content of a file in the Next.js app"""
file_path = os.path.join(app_path, relative_path)
if os.path.exists(file_path):
with open(file_path, 'r') as f:
return f.read()
return ""
def build_prompt(app_path: str, user_query: str):
"""build the prompt for the LLM with current file contents"""
files = {
"app/page.tsx": get_file_content(app_path, "app/page.tsx"),
"app/layout.tsx": get_file_content(app_path, "app/layout.tsx"),
"app/globals.css": get_file_content(app_path, "app/globals.css"),
}
prompt = f"""You are an expert web-application developer. Please build a Next.js web application according to the following user query:
"{user_query}"
The current directory structure is:
app/
— globals.css
— layout.tsx
— page.tsx
public/
... etc...
Here is the current page.tsx which you can overwrite.
###
{files["app/page.tsx"]}
###
Here is the current page.tsx which you can overwrite.
###
{files["app/layout.tsx"]}
###
Here is the current page.tsx which you can overwrite.
###
{files["app/globals.css"]}
###
Important Notes:
- Please return the full completed files- you may also create new files if needed.
- For each file, specify the file path using ###path/to/file### followed by the code for that file wrapped in triple backticks (```).
For example:
###app/page.tsx###
```tsx
// your code here
```
###app/api/submit.ts###
```ts
// Your code here
```
The code you return will be immediately written to the app and then deployed so ensure that the app will compile and run as intended.
"""
return prompt
def parse_response(response):
"""parse the LLM response to extract file paths/contents into files dict"""
file_pattern = r"###(.*?)###\s*```(?:.*?)\n(.*?)```"
matches = re.findall(file_pattern, response, re.DOTALL)
files = {}
for file_path, content in matches:
file_path = file_path.strip()
files[file_path] = content
return files
def write_files(app_path, files):
"""write the files to app dir"""
for file_path, content in files.items():
full_path = os.path.join(app_path, file_path)
os.makedirs(os.path.dirname(full_path), exist_ok=True)
with open(full_path, 'w') as f:
f.write(content)
print(f"Wrote file: {file_path}")
def main():
parser = argparse.ArgumentParser(description="Generate a Next.js app using an LLM")
parser.add_argument("app_name", help="Name of the Next.js app to create")
parser.add_argument("query", help="User query describing app to create")
parser.add_argument("--model", default="claude-3-7-sonnet-20250219", help="LLM model to use")
args = parser.parse_args()
app_path = create_next_app(args.app_name)
prompt = build_prompt(app_path, args.query)
# print(f"\Prompt:\n{prompt}")
print(f"Querying LLM ({args.model})...")
lm = LiteLLMClient(model=args.model)
messages = [
{
"role": "user",
"content": prompt
}
]
response = lm(messages)
# print(f"\LM Response:\n{prompt}")
files = parse_response(response)
write_files(app_path, files)
print(f"\nApp generation complete! your app is ready to be deployed at: {app_path}")
print("you can deploy it with: cd path/to/app && npx vercel")
if __name__ == "__main__":
main()