ciyidogan commited on
Commit
b2396e7
·
verified ·
1 Parent(s): db3b193

Update project_controller.py

Browse files
Files changed (1) hide show
  1. project_controller.py +60 -241
project_controller.py CHANGED
@@ -1,256 +1,75 @@
1
- from fastapi import APIRouter, HTTPException, Request, Depends
2
- from config_provider import get_config, service_config
3
- from service_config import ServiceConfig
4
  from utils import save_service_config, log
5
- import datetime
6
- import json
7
  import copy
8
 
9
  router = APIRouter()
10
 
11
- def get_utc_now():
12
- return datetime.datetime.utcnow().isoformat()
13
-
14
- @router.get("/list")
15
- def list_projects(config: ServiceConfig = Depends(get_config)):
16
- return config.projects
17
-
18
- @router.get("/{project_name}/latest")
19
- def get_latest_project_version(project_name: str, config: ServiceConfig = Depends(get_config)):
20
- project = config.projects.get(project_name)
21
- if not project:
22
- raise HTTPException(status_code=404, detail="Project not found")
23
-
24
- if not project.get("versions"):
25
- raise HTTPException(status_code=404, detail="No versions found")
26
-
27
- latest = max(project["versions"], key=lambda v: v["version_number"])
28
-
29
- return {
30
- "version_number": latest["version_number"],
31
- "published": latest.get("published", False),
32
- "intents": latest.get("intents", []),
33
- "llm": latest.get("llm", {}),
34
- "last_updated": project.get("last_updated", get_utc_now())
35
  }
36
-
37
- @router.post("/update")
38
- async def update_project(request: Request, config: ServiceConfig = Depends(get_config)):
39
- data = await request.json()
40
- project_name = data.get("project_name")
41
- client_last_updated = data.get("client_last_updated")
42
- new_data = data.get("new_data")
43
-
44
- project = config.projects.get(project_name)
45
  if not project:
46
  raise HTTPException(status_code=404, detail="Project not found")
 
 
 
 
47
 
48
- if project.get("last_updated") != client_last_updated:
49
- raise HTTPException(status_code=409, detail="Record updated by another user. Please reload.")
50
-
51
- latest = max(project["versions"], key=lambda v: v["version_number"])
52
- if latest.get("published"):
53
- raise HTTPException(status_code=400, detail="Cannot edit a published version.")
54
-
55
- latest.update(new_data)
56
- project["last_updated"] = get_utc_now()
57
-
58
- with open(config.config_path, "w", encoding="utf-8") as f:
59
- json.dump(config, f, indent=2)
60
-
61
- return {"message": f"Project {project_name} updated"}
62
-
63
- @router.post("/publish")
64
- async def publish_project(request: Request, config: ServiceConfig = Depends(get_config)):
65
- data = await request.json()
66
- project_name = data.get("project_name")
67
- client_last_updated = data.get("client_last_updated")
68
-
69
- project = config.projects.get(project_name)
70
- if not project:
71
- raise HTTPException(status_code=404, detail="Project not found")
72
-
73
- if project.get("last_updated") != client_last_updated:
74
- raise HTTPException(status_code=409, detail="Record updated by another user. Please reload.")
75
-
76
- latest = max(project["versions"], key=lambda v: v["version_number"])
77
- if latest.get("published"):
78
- raise HTTPException(status_code=400, detail="Version already published.")
79
-
80
- llm = latest.get("llm", {})
81
- if not llm.get("repo_id"):
82
- raise HTTPException(status_code=400, detail="repo_id is required")
83
- if llm.get("use_fine_tune") and not llm.get("fine_tune_zip"):
84
- raise HTTPException(status_code=400, detail="fine_tune_zip is required when use_fine_tune is true")
85
-
86
- latest["published"] = True
87
- latest["last_updated"] = get_utc_now()
88
-
89
- new_version_number = latest["version_number"] + 1
90
- new_version = copy.deepcopy(latest)
91
- new_version["version_number"] = new_version_number
92
- new_version["published"] = False
93
- new_version["last_updated"] = get_utc_now()
94
- new_version["intents"] = []
95
- new_version["llm"] = copy.deepcopy(llm)
96
-
97
- project["versions"].append(new_version)
98
- project["last_updated"] = get_utc_now()
99
-
100
- with open(config.config_path, "w", encoding="utf-8") as f:
101
- json.dump(config, f, indent=2)
102
-
103
- return {"message": f"Project {project_name} version published and new draft version {new_version_number} created"}
104
-
105
- @router.post("/add_intent")
106
- async def add_intent(request: Request, config: ServiceConfig = Depends(get_config)):
107
- data = await request.json()
108
- project_name = data.get("project_name")
109
- intent_name = data.get("intent_name")
110
-
111
- project = config.projects.get(project_name)
112
  if not project:
113
  raise HTTPException(status_code=404, detail="Project not found")
114
-
115
- latest = max(project["versions"], key=lambda v: v["version_number"])
116
- if any(intent["name"] == intent_name for intent in latest.get("intents", [])):
117
- raise HTTPException(status_code=400, detail="Intent with this name already exists.")
118
-
119
- latest.setdefault("intents", []).append({
120
- "name": intent_name,
121
- "examples": [],
122
- "parameters": [],
123
- "action": "",
124
- "fallback_timeout_message": "",
125
- "fallback_error_message": "",
126
- "humanization_prompt": ""
127
- })
128
- project["last_updated"] = get_utc_now()
129
-
130
- with open(config.config_path, "w", encoding="utf-8") as f:
131
- json.dump(config, f, indent=2)
132
-
133
- return {"message": f"Intent {intent_name} added to project {project_name}"}
134
-
135
- @router.post("/delete_intent")
136
- async def delete_intent(request: Request, config: ServiceConfig = Depends(get_config)):
137
- data = await request.json()
138
- project_name = data.get("project_name")
139
- intent_name = data.get("intent_name")
140
-
141
- project = config.projects.get(project_name)
142
  if not project:
143
  raise HTTPException(status_code=404, detail="Project not found")
144
-
145
- latest = max(project["versions"], key=lambda v: v["version_number"])
146
- intents = latest.get("intents", [])
147
- new_intents = [intent for intent in intents if intent["name"] != intent_name]
148
- if len(new_intents) == len(intents):
149
- raise HTTPException(status_code=404, detail="Intent not found.")
150
-
151
- latest["intents"] = new_intents
152
- project["last_updated"] = get_utc_now()
153
-
154
- with open(config.config_path, "w", encoding="utf-8") as f:
155
- json.dump(config, f, indent=2)
156
-
157
- return {"message": f"Intent {intent_name} deleted from project {project_name}"}
158
-
159
- @router.post("/update_intent")
160
- async def update_intent(request: Request, config: ServiceConfig = Depends(get_config)):
161
- data = await request.json()
162
- project_name = data.get("project_name")
163
- intent_name = data.get("intent_name")
164
- intent_data = data.get("intent_data")
165
-
166
- if not project_name or not intent_name or not intent_data:
167
- raise HTTPException(status_code=400, detail="project_name, intent_name, and intent_data are required")
168
-
169
- project = config.projects.get(project_name)
170
  if not project:
171
  raise HTTPException(status_code=404, detail="Project not found")
172
-
173
- latest = max(project["versions"], key=lambda v: v["version_number"])
174
-
175
- updated = False
176
- for intent in latest.get("intents", []):
177
- if intent.get("name") == intent_name:
178
- intent.update(intent_data)
179
- updated = True
180
- break
181
-
182
- if not updated:
183
- raise HTTPException(status_code=404, detail="Intent not found in project")
184
-
185
- project["last_updated"] = get_utc_now()
186
-
187
- with open(config.config_path, "w", encoding="utf-8") as f:
188
- json.dump(config, f, indent=2)
189
-
190
- return {"message": f"Intent {intent_name} updated in project {project_name}"}
191
-
192
- @router.post("/seed/test_data")
193
- def seed_test_data(config: ServiceConfig = Depends(get_config)):
194
- config.projects = {
195
- "demo-project": {
196
- "enabled": True,
197
- "last_updated": get_utc_now(),
198
- "versions": [
199
- {
200
- "version_number": 1,
201
- "published": True,
202
- "last_updated": get_utc_now(),
203
- "intents": [{"name": "weather-intent"}, {"name": "currency-intent"}],
204
- "llm": {
205
- "repo_id": "demo/repo",
206
- "use_fine_tune": False
207
- }
208
- },
209
- {
210
- "version_number": 2,
211
- "published": False,
212
- "last_updated": get_utc_now(),
213
- "intents": [],
214
- "llm": {
215
- "repo_id": "demo/repo",
216
- "use_fine_tune": False
217
- }
218
- }
219
- ]
220
- }
221
- }
222
- with open(config.config_path, "w", encoding="utf-8") as f:
223
- json.dump(config, f, indent=2)
224
-
225
- return {"message": "Test data seeded"}
226
-
227
- @router.post("/clear/all")
228
- def clear_all(config: ServiceConfig = Depends(get_config)):
229
- config.projects = {}
230
- with open(config.config_path, "w", encoding="utf-8") as f:
231
- json.dump(config, f, indent=2)
232
-
233
- return {"message": "All projects cleared"}
234
-
235
- @router.post("/project/new-version")
236
- def create_new_version(base_version_id: int, config: ServiceConfig = Depends(get_config)):
237
- try:
238
- project = config.get_current_project()
239
- base_version = next((v for v in project['versions'] if v['no'] == base_version_id), None)
240
- if not base_version:
241
- raise HTTPException(status_code=404, detail="Base version not found")
242
-
243
- new_version_no = max(v['no'] for v in project['versions']) + 1
244
- new_version = copy.deepcopy(base_version)
245
- new_version['no'] = new_version_no
246
- new_version['published'] = False
247
- project['versions'].append(new_version)
248
-
249
- save_service_config(config)
250
- log(f"✅ New version {new_version_no} created for project {project['name']}")
251
- return { "status": "success", "new_version": new_version_no }
252
-
253
- except Exception as e:
254
- log(f"❌ Error creating new version: {str(e)}")
255
- raise HTTPException(status_code=500, detail="Failed to create new version")
256
-
 
1
+ from fastapi import APIRouter, Depends, HTTPException
2
+ from config_provider import get_config, ServiceConfig
 
3
  from utils import save_service_config, log
 
 
4
  import copy
5
 
6
  router = APIRouter()
7
 
8
+ @router.post("/project/new")
9
+ def create_project(name: str, config: ServiceConfig = Depends(get_config)):
10
+ if any(p['name'] == name for p in config.data['projects']):
11
+ raise HTTPException(status_code=400, detail="Project already exists")
12
+ new_project = {
13
+ "name": name,
14
+ "versions": []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  }
16
+ config.data['projects'].append(new_project)
17
+ save_service_config(config)
18
+ log(f"✅ New project '{name}' created")
19
+ return { "status": "success" }
20
+
21
+ @router.post("/project/delete")
22
+ def delete_project(name: str, config: ServiceConfig = Depends(get_config)):
23
+ project = next((p for p in config.data['projects'] if p['name'] == name), None)
 
24
  if not project:
25
  raise HTTPException(status_code=404, detail="Project not found")
26
+ config.data['projects'].remove(project)
27
+ save_service_config(config)
28
+ log(f"🗑️ Project '{name}' deleted")
29
+ return { "status": "success" }
30
 
31
+ @router.post("/project/new-version")
32
+ def create_new_version(project_name: str, base_version_no: int, config: ServiceConfig = Depends(get_config)):
33
+ project = next((p for p in config.data['projects'] if p['name'] == project_name), None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  if not project:
35
  raise HTTPException(status_code=404, detail="Project not found")
36
+ base_version = next((v for v in project['versions'] if v['no'] == base_version_no), None)
37
+ if not base_version:
38
+ raise HTTPException(status_code=404, detail="Base version not found")
39
+ new_version_no = max((v['no'] for v in project['versions']), default=0) + 1
40
+ new_version = copy.deepcopy(base_version)
41
+ new_version['no'] = new_version_no
42
+ new_version['published'] = False
43
+ project['versions'].append(new_version)
44
+ save_service_config(config)
45
+ log(f" New version {new_version_no} created for project {project_name}")
46
+ return { "status": "success", "new_version": new_version_no }
47
+
48
+ @router.post("/project/delete-version")
49
+ def delete_version(project_name: str, version_no: int, config: ServiceConfig = Depends(get_config)):
50
+ project = next((p for p in config.data['projects'] if p['name'] == project_name), None)
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  if not project:
52
  raise HTTPException(status_code=404, detail="Project not found")
53
+ version = next((v for v in project['versions'] if v['no'] == version_no), None)
54
+ if not version:
55
+ raise HTTPException(status_code=404, detail="Version not found")
56
+ project['versions'].remove(version)
57
+ save_service_config(config)
58
+ log(f"🗑️ Version {version_no} deleted from project {project_name}")
59
+ return { "status": "success" }
60
+
61
+ @router.post("/project/update-api")
62
+ def update_api(project_name: str, version_no: int, api_data: dict, config: ServiceConfig = Depends(get_config)):
63
+ project = next((p for p in config.data['projects'] if p['name'] == project_name), None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  if not project:
65
  raise HTTPException(status_code=404, detail="Project not found")
66
+ version = next((v for v in project['versions'] if v['no'] == version_no), None)
67
+ if not version:
68
+ raise HTTPException(status_code=404, detail="Version not found")
69
+ existing_api = next((a for a in version['apis'] if a['name'] == api_data['name']), None)
70
+ if existing_api:
71
+ version['apis'].remove(existing_api)
72
+ version['apis'].append(api_data)
73
+ save_service_config(config)
74
+ log(f"🔧 API '{api_data['name']}' updated in project {project_name} version {version_no}")
75
+ return { "status": "success" }