Mayank2027 commited on
Commit
5de89f6
·
verified ·
1 Parent(s): fdacbc7

Create main.py

Browse files
Files changed (1) hide show
  1. main.py +179 -0
main.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, json, asyncio, shutil, subprocess
2
+ from fastapi import FastAPI, HTTPException, WebSocket, WebSocketDisconnect, BackgroundTasks
3
+ from fastapi.staticfiles import StaticFiles
4
+ from fastapi.responses import FileResponse, StreamingResponse
5
+ from pydantic import BaseModel
6
+ from typing import List, Optional, Dict, Any
7
+ from pathlib import Path
8
+ import git
9
+
10
+ from model_router import route_chat, route_autocomplete, get_available_models
11
+ from agent import CodingAgent
12
+ from codebase_index import CodebaseIndex
13
+ from autocomplete import generate_autocomplete
14
+
15
+ app = FastAPI(title="Codeki API")
16
+
17
+ # Global codebase indexer (lazy load per project)
18
+ indexers = {}
19
+
20
+ # Agent instances for cloud tasks
21
+ agents = {}
22
+
23
+ # Mount static frontend
24
+ if os.path.exists("static"):
25
+ app.mount("/static", StaticFiles(directory="static", html=True), name="static")
26
+
27
+ # ---- Models ----
28
+ class ChatRequest(BaseModel):
29
+ model: str = "groq-mixtral-8x7b-32768"
30
+ messages: List[Dict[str, str]]
31
+ context_files: Optional[List[str]] = None
32
+ project_path: str = "/app/sandbox" # default
33
+
34
+ class AgentTaskRequest(BaseModel):
35
+ prompt: str
36
+ model: str = "openrouter-anthropic/claude-3-opus"
37
+ project_path: str
38
+ auto_approve: bool = False
39
+ background: bool = False
40
+
41
+ class AutocompleteRequest(BaseModel):
42
+ prefix: str
43
+ suffix: str = ""
44
+ filepath: str
45
+ language: str
46
+ max_tokens: int = 64
47
+ model: str = "groq-llama3-8b-8192"
48
+
49
+ class IndexRequest(BaseModel):
50
+ project_path: str
51
+
52
+ class BugFixRequest(BaseModel):
53
+ file_path: str
54
+ error_output: str
55
+ project_path: str
56
+
57
+ class ReviewRequest(BaseModel):
58
+ pr_diff: str
59
+ project_path: str
60
+
61
+ # ---- API Routes ----
62
+
63
+ @app.get("/")
64
+ async def root():
65
+ return FileResponse("static/index.html")
66
+
67
+ @app.get("/api/models")
68
+ async def get_models():
69
+ return get_available_models()
70
+
71
+ @app.post("/api/chat")
72
+ async def chat(req: ChatRequest):
73
+ # Context retrieval if files referenced
74
+ context = ""
75
+ if req.context_files:
76
+ for f in req.context_files:
77
+ p = Path(req.project_path) / f
78
+ if p.exists():
79
+ context += f"\n--- {f} ---\n{p.read_text()}\n"
80
+ req.messages.insert(0, {"role": "system", "content": f"Relevant codebase context:\n{context}"})
81
+
82
+ async def event_stream():
83
+ async for token in route_chat(req.model, req.messages):
84
+ yield f"data: {json.dumps({'token': token})}\n\n"
85
+ yield "data: [DONE]\n\n"
86
+ return StreamingResponse(event_stream(), media_type="text/event-stream")
87
+
88
+ @app.post("/api/agent/run")
89
+ async def run_agent(req: AgentTaskRequest, background_tasks: BackgroundTasks):
90
+ agent = CodingAgent(project_path=req.project_path, model=req.model)
91
+ if req.background:
92
+ # Cloud agent - run in background task queue
93
+ task_id = str(uuid.uuid4())
94
+ agents[task_id] = agent
95
+ background_tasks.add_task(agent.execute_task, req.prompt, auto_approve=req.auto_approve)
96
+ return {"task_id": task_id, "status": "started"}
97
+ else:
98
+ # Synchronous execution with streaming
99
+ async def event_stream():
100
+ async for event in agent.execute_task_stream(req.prompt, auto_approve=req.auto_approve):
101
+ yield f"data: {json.dumps(event)}\n\n"
102
+ yield "data: [DONE]\n\n"
103
+ return StreamingResponse(event_stream(), media_type="text/event-stream")
104
+
105
+ @app.post("/api/autocomplete")
106
+ async def autocomplete(req: AutocompleteRequest):
107
+ suggestions = await generate_autocomplete(req)
108
+ return {"completions": suggestions}
109
+
110
+ @app.post("/api/index")
111
+ async def index_project(req: IndexRequest):
112
+ idx = CodebaseIndex(req.project_path)
113
+ idx.build_index()
114
+ indexers[req.project_path] = idx
115
+ return {"status": "indexed", "files": len(idx.file_list)}
116
+
117
+ @app.post("/api/bugfix")
118
+ async def bugfix(req: BugFixRequest):
119
+ # Agent that fixes the given error
120
+ agent = CodingAgent(project_path=req.project_path, model="openrouter-anthropic/claude-3-opus")
121
+ result = await agent.fix_error(req.file_path, req.error_output)
122
+ return result
123
+
124
+ @app.post("/api/review")
125
+ async def review_code(req: ReviewRequest):
126
+ agent = CodingAgent(project_path=req.project_path, model="openrouter-anthropic/claude-3-opus")
127
+ review = await agent.review_pr(req.pr_diff)
128
+ return {"review": review}
129
+
130
+ @app.post("/api/git")
131
+ async def git_operation(action: str, project_path: str, args: Optional[dict] = None):
132
+ try:
133
+ repo = git.Repo(project_path)
134
+ if action == "commit":
135
+ repo.git.add(A=True)
136
+ repo.git.commit(m=args.get("message", "auto commit"))
137
+ elif action == "log":
138
+ logs = list(repo.iter_commits(max_count=10))
139
+ return {"log": [{"message": c.message, "hash": c.hexsha} for c in logs]}
140
+ elif action == "branch":
141
+ branches = [b.name for b in repo.branches]
142
+ return {"branches": branches}
143
+ # ... other git actions
144
+ except Exception as e:
145
+ raise HTTPException(400, str(e))
146
+
147
+ @app.websocket("/ws/terminal")
148
+ async def terminal_ws(websocket: WebSocket):
149
+ await websocket.accept()
150
+ proc = None
151
+ try:
152
+ while True:
153
+ cmd = await websocket.receive_text()
154
+ if cmd.startswith("exec:"):
155
+ command = cmd[5:]
156
+ proc = await asyncio.create_subprocess_shell(
157
+ command,
158
+ stdout=asyncio.subprocess.PIPE,
159
+ stderr=asyncio.subprocess.PIPE,
160
+ cwd="/app/sandbox"
161
+ )
162
+ stdout, stderr = await proc.communicate()
163
+ output = stdout.decode() + stderr.decode()
164
+ await websocket.send_text(output)
165
+ elif cmd == "ctrl-c" and proc:
166
+ proc.terminate()
167
+ except WebSocketDisconnect:
168
+ pass
169
+
170
+ @app.post("/api/agent/task/{task_id}")
171
+ async def get_agent_status(task_id: str):
172
+ agent = agents.get(task_id)
173
+ if not agent:
174
+ raise HTTPException(404, "Task not found")
175
+ return {"status": agent.status, "logs": agent.logs}
176
+
177
+ if __name__ == "__main__":
178
+ import uvicorn
179
+ uvicorn.run(app, host="0.0.0.0", port=7860)