🐛 Bug: Fix the bug where the front-end sheet table can only display one key when there are multiple API keys.
Browse files
main.py
CHANGED
|
@@ -1051,7 +1051,7 @@ from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
|
|
| 1051 |
from fastapi.security import APIKeyHeader
|
| 1052 |
from typing import Optional, List
|
| 1053 |
|
| 1054 |
-
from xue import HTML, Head, Body, Div, xue_initialize, Script
|
| 1055 |
from xue.components.menubar import (
|
| 1056 |
Menubar, MenubarMenu, MenubarTrigger, MenubarContent,
|
| 1057 |
MenubarItem, MenubarSeparator
|
|
@@ -1069,7 +1069,6 @@ yaml = YAML()
|
|
| 1069 |
yaml.preserve_quotes = True
|
| 1070 |
yaml.indent(mapping=2, sequence=4, offset=2)
|
| 1071 |
|
| 1072 |
-
|
| 1073 |
frontend_router = APIRouter()
|
| 1074 |
|
| 1075 |
API_KEY_NAME = "X-API-Key"
|
|
@@ -1262,7 +1261,7 @@ async def get_columns_menu(menu_id: str, row_id: str):
|
|
| 1262 |
"hx-delete": f"/delete/{row_id}",
|
| 1263 |
"hx-target": "body",
|
| 1264 |
"hx-swap": "outerHTML",
|
| 1265 |
-
"hx-confirm": "
|
| 1266 |
},
|
| 1267 |
]
|
| 1268 |
result = dropdown.dropdown_menu_content(menu_id, columns).render()
|
|
@@ -1291,6 +1290,36 @@ async def add_model():
|
|
| 1291 |
new_model = model_config_row(new_model_id).render()
|
| 1292 |
return new_model
|
| 1293 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1294 |
@frontend_router.get("/edit-sheet/{row_id}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
| 1295 |
async def get_edit_sheet(row_id: str, x_api_key: str = Depends(get_api_key)):
|
| 1296 |
row_data = get_row_data(row_id)
|
|
@@ -1305,6 +1334,10 @@ async def get_edit_sheet(row_id: str, x_api_key: str = Depends(get_api_key)):
|
|
| 1305 |
key, value = list(model.items())[0]
|
| 1306 |
model_list.append(model_config_row(f"model{index}", key, value, True))
|
| 1307 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1308 |
sheet_id = "edit-sheet"
|
| 1309 |
edit_sheet_content = sheet.SheetContent(
|
| 1310 |
sheet.SheetHeader(
|
|
@@ -1316,7 +1349,19 @@ async def get_edit_sheet(row_id: str, x_api_key: str = Depends(get_api_key)):
|
|
| 1316 |
form.Form(
|
| 1317 |
form.FormField("Provider", "provider", value=row_data["provider"], placeholder="Enter provider name", required=True),
|
| 1318 |
form.FormField("Base URL", "base_url", value=row_data["base_url"], placeholder="Enter base URL", required=True),
|
| 1319 |
-
form.FormField("API Key", "api_key", value=row_data["api"], type="text", placeholder="Enter API key"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1320 |
Div(
|
| 1321 |
Div("Models", class_="text-lg font-semibold mb-2"),
|
| 1322 |
Div(
|
|
@@ -1363,6 +1408,27 @@ async def get_edit_sheet(row_id: str, x_api_key: str = Depends(get_api_key)):
|
|
| 1363 |
).render()
|
| 1364 |
return result
|
| 1365 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1366 |
@frontend_router.get("/add-provider-sheet", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
| 1367 |
async def get_add_provider_sheet():
|
| 1368 |
sheet_id = "add-provider-sheet"
|
|
@@ -1427,11 +1493,10 @@ def update_row_data(row_id, updated_data):
|
|
| 1427 |
print(row_id, updated_data)
|
| 1428 |
index = int(row_id)
|
| 1429 |
app.state.config["providers"][index] = updated_data
|
| 1430 |
-
save_api_yaml()
|
| 1431 |
|
| 1432 |
def save_api_yaml():
|
| 1433 |
with open(API_YAML_PATH, "w", encoding="utf-8") as f:
|
| 1434 |
-
yaml.
|
| 1435 |
|
| 1436 |
@frontend_router.post("/submit/{row_id}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
| 1437 |
async def submit_form(
|
|
@@ -1439,13 +1504,15 @@ async def submit_form(
|
|
| 1439 |
request: Request,
|
| 1440 |
provider: str = FastapiForm(...),
|
| 1441 |
base_url: str = FastapiForm(...),
|
| 1442 |
-
api_key: Optional[str] = FastapiForm(None),
|
| 1443 |
tools: Optional[str] = FastapiForm(None),
|
| 1444 |
notes: Optional[str] = FastapiForm(None),
|
| 1445 |
x_api_key: str = Depends(get_api_key)
|
| 1446 |
):
|
| 1447 |
form_data = await request.form()
|
| 1448 |
|
|
|
|
|
|
|
| 1449 |
# 收集模型数据
|
| 1450 |
models = []
|
| 1451 |
for key, value in form_data.items():
|
|
@@ -1462,7 +1529,7 @@ async def submit_form(
|
|
| 1462 |
updated_data = {
|
| 1463 |
"provider": provider,
|
| 1464 |
"base_url": base_url,
|
| 1465 |
-
"api":
|
| 1466 |
"model": models,
|
| 1467 |
"tools": tools == "on",
|
| 1468 |
"notes": notes,
|
|
|
|
| 1051 |
from fastapi.security import APIKeyHeader
|
| 1052 |
from typing import Optional, List
|
| 1053 |
|
| 1054 |
+
from xue import HTML, Head, Body, Div, xue_initialize, Script, Ul, Li
|
| 1055 |
from xue.components.menubar import (
|
| 1056 |
Menubar, MenubarMenu, MenubarTrigger, MenubarContent,
|
| 1057 |
MenubarItem, MenubarSeparator
|
|
|
|
| 1069 |
yaml.preserve_quotes = True
|
| 1070 |
yaml.indent(mapping=2, sequence=4, offset=2)
|
| 1071 |
|
|
|
|
| 1072 |
frontend_router = APIRouter()
|
| 1073 |
|
| 1074 |
API_KEY_NAME = "X-API-Key"
|
|
|
|
| 1261 |
"hx-delete": f"/delete/{row_id}",
|
| 1262 |
"hx-target": "body",
|
| 1263 |
"hx-swap": "outerHTML",
|
| 1264 |
+
"hx-confirm": "Are you sure you want to delete this configuration?"
|
| 1265 |
},
|
| 1266 |
]
|
| 1267 |
result = dropdown.dropdown_menu_content(menu_id, columns).render()
|
|
|
|
| 1290 |
new_model = model_config_row(new_model_id).render()
|
| 1291 |
return new_model
|
| 1292 |
|
| 1293 |
+
def render_api_keys(row_id, api_keys):
|
| 1294 |
+
return Ul(
|
| 1295 |
+
*[Li(
|
| 1296 |
+
Div(
|
| 1297 |
+
Div(
|
| 1298 |
+
input.input(
|
| 1299 |
+
type="text",
|
| 1300 |
+
placeholder="Enter API key",
|
| 1301 |
+
value=api_key,
|
| 1302 |
+
name=f"api_key_{i}",
|
| 1303 |
+
class_="flex-grow w-full"
|
| 1304 |
+
),
|
| 1305 |
+
class_="flex-grow"
|
| 1306 |
+
),
|
| 1307 |
+
button.button(
|
| 1308 |
+
"Delete",
|
| 1309 |
+
variant="outline",
|
| 1310 |
+
type="button",
|
| 1311 |
+
class_="ml-2",
|
| 1312 |
+
hx_delete=f"/delete-api-key/{row_id}/{i}",
|
| 1313 |
+
hx_target="#api-keys-container",
|
| 1314 |
+
hx_swap="outerHTML"
|
| 1315 |
+
),
|
| 1316 |
+
class_="flex items-center mb-2 w-full"
|
| 1317 |
+
)
|
| 1318 |
+
) for i, api_key in enumerate(api_keys)],
|
| 1319 |
+
id="api-keys-container",
|
| 1320 |
+
class_="space-y-2 w-full"
|
| 1321 |
+
)
|
| 1322 |
+
|
| 1323 |
@frontend_router.get("/edit-sheet/{row_id}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
| 1324 |
async def get_edit_sheet(row_id: str, x_api_key: str = Depends(get_api_key)):
|
| 1325 |
row_data = get_row_data(row_id)
|
|
|
|
| 1334 |
key, value = list(model.items())[0]
|
| 1335 |
model_list.append(model_config_row(f"model{index}", key, value, True))
|
| 1336 |
|
| 1337 |
+
# 处理多个 API keys
|
| 1338 |
+
api_keys = row_data["api"] if isinstance(row_data["api"], list) else [row_data["api"]]
|
| 1339 |
+
api_key_inputs = render_api_keys(row_id, api_keys)
|
| 1340 |
+
|
| 1341 |
sheet_id = "edit-sheet"
|
| 1342 |
edit_sheet_content = sheet.SheetContent(
|
| 1343 |
sheet.SheetHeader(
|
|
|
|
| 1349 |
form.Form(
|
| 1350 |
form.FormField("Provider", "provider", value=row_data["provider"], placeholder="Enter provider name", required=True),
|
| 1351 |
form.FormField("Base URL", "base_url", value=row_data["base_url"], placeholder="Enter base URL", required=True),
|
| 1352 |
+
# form.FormField("API Key", "api_key", value=row_data["api"], type="text", placeholder="Enter API key"),
|
| 1353 |
+
Div(
|
| 1354 |
+
Div("API Keys", class_="text-lg font-semibold mb-2"),
|
| 1355 |
+
api_key_inputs,
|
| 1356 |
+
button.button(
|
| 1357 |
+
"Add API Key",
|
| 1358 |
+
class_="mt-2",
|
| 1359 |
+
hx_post=f"/add-api-key/{row_id}",
|
| 1360 |
+
hx_target="#api-keys-container",
|
| 1361 |
+
hx_swap="outerHTML"
|
| 1362 |
+
),
|
| 1363 |
+
class_="mb-4"
|
| 1364 |
+
),
|
| 1365 |
Div(
|
| 1366 |
Div("Models", class_="text-lg font-semibold mb-2"),
|
| 1367 |
Div(
|
|
|
|
| 1408 |
).render()
|
| 1409 |
return result
|
| 1410 |
|
| 1411 |
+
@frontend_router.post("/add-api-key/{row_id}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
| 1412 |
+
async def add_api_key(row_id: str):
|
| 1413 |
+
row_data = get_row_data(row_id)
|
| 1414 |
+
api_keys = row_data["api"] if isinstance(row_data["api"], list) else [row_data["api"]]
|
| 1415 |
+
api_keys.append("") # 添加一个空的API key
|
| 1416 |
+
|
| 1417 |
+
api_key_inputs = render_api_keys(row_id, api_keys)
|
| 1418 |
+
|
| 1419 |
+
return api_key_inputs.render()
|
| 1420 |
+
|
| 1421 |
+
@frontend_router.delete("/delete-api-key/{row_id}/{index}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
| 1422 |
+
async def delete_api_key(row_id: str, index: int):
|
| 1423 |
+
row_data = get_row_data(row_id)
|
| 1424 |
+
api_keys = row_data["api"] if isinstance(row_data["api"], list) else [row_data["api"]]
|
| 1425 |
+
if len(api_keys) > 1:
|
| 1426 |
+
del api_keys[index]
|
| 1427 |
+
|
| 1428 |
+
api_key_inputs = render_api_keys(row_id, api_keys)
|
| 1429 |
+
|
| 1430 |
+
return api_key_inputs.render()
|
| 1431 |
+
|
| 1432 |
@frontend_router.get("/add-provider-sheet", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
| 1433 |
async def get_add_provider_sheet():
|
| 1434 |
sheet_id = "add-provider-sheet"
|
|
|
|
| 1493 |
print(row_id, updated_data)
|
| 1494 |
index = int(row_id)
|
| 1495 |
app.state.config["providers"][index] = updated_data
|
|
|
|
| 1496 |
|
| 1497 |
def save_api_yaml():
|
| 1498 |
with open(API_YAML_PATH, "w", encoding="utf-8") as f:
|
| 1499 |
+
yaml.dump(app.state.config, f)
|
| 1500 |
|
| 1501 |
@frontend_router.post("/submit/{row_id}", response_class=HTMLResponse, dependencies=[Depends(frontend_rate_limit_dependency)])
|
| 1502 |
async def submit_form(
|
|
|
|
| 1504 |
request: Request,
|
| 1505 |
provider: str = FastapiForm(...),
|
| 1506 |
base_url: str = FastapiForm(...),
|
| 1507 |
+
# api_key: Optional[str] = FastapiForm(None),
|
| 1508 |
tools: Optional[str] = FastapiForm(None),
|
| 1509 |
notes: Optional[str] = FastapiForm(None),
|
| 1510 |
x_api_key: str = Depends(get_api_key)
|
| 1511 |
):
|
| 1512 |
form_data = await request.form()
|
| 1513 |
|
| 1514 |
+
api_keys = [value for key, value in form_data.items() if key.startswith("api_key_") and value]
|
| 1515 |
+
|
| 1516 |
# 收集模型数据
|
| 1517 |
models = []
|
| 1518 |
for key, value in form_data.items():
|
|
|
|
| 1529 |
updated_data = {
|
| 1530 |
"provider": provider,
|
| 1531 |
"base_url": base_url,
|
| 1532 |
+
"api": api_keys[0] if len(api_keys) == 1 else api_keys, # 如果只有一个 API key,就不使用列表
|
| 1533 |
"model": models,
|
| 1534 |
"tools": tools == "on",
|
| 1535 |
"notes": notes,
|