feat: add api key auth, devii agent, openai gateway, and admin service management

This commit introduces a comprehensive set of new features including API key authentication with CLI management commands (get, reset, backfill), a Devii agentic assistant with WebSocket terminal and session bootstrap, an OpenAI-compatible LLM gateway service, and an admin service management panel. It also adds Playwright browser automation for bot support, configures internal gateway URLs, refactors content editing/deletion to support JSON API responses, and updates documentation across AGENTS.md, README.md, and the developer docs site.
This commit is contained in:
2026-06-08 15:38:33 +00:00
parent 921e382cbc
commit e0535bb7c5
270 changed files with 54408 additions and 541 deletions
+10 -7
View File
@@ -8,6 +8,8 @@ from devplacepy.content import load_detail, edit_content_item, delete_content_it
from devplacepy.templating import templates
from devplacepy.utils import get_current_user, require_user, not_found, XP_GIST
from devplacepy.seo import base_seo_context, site_url, website_schema, software_source_code_schema, list_page_seo, next_page_url
from devplacepy.responses import respond, action_result
from devplacepy.schemas import GistsOut, GistDetailOut
logger = logging.getLogger(__name__)
router = APIRouter()
@@ -55,7 +57,7 @@ async def gists_page(request: Request, language: str = None, user_uid: str = Non
],
next_url=next_page_url(request, next_cursor),
)
return templates.TemplateResponse(request, "gists.html", {
return respond(request, "gists.html", {
**seo_ctx,
"request": request,
"user": user,
@@ -65,7 +67,7 @@ async def gists_page(request: Request, language: str = None, user_uid: str = Non
"current_language": language,
"languages": LANGUAGES,
"gist_language_codes": get_gist_languages(),
})
}, model=GistsOut)
@router.get("/{gist_slug}", response_class=HTMLResponse)
@@ -93,9 +95,9 @@ async def gist_detail(request: Request, gist_slug: str):
],
schemas=[website_schema(base), software_source_code_schema(gist, base)],
)
return templates.TemplateResponse(request, "gist_detail.html", detail_context(request, user, detail, "gist", seo_ctx, {
return respond(request, "gist_detail.html", detail_context(request, user, detail, "gist", seo_ctx, {
"languages": LANGUAGES,
}))
}), model=GistDetailOut)
@router.post("/create")
@@ -116,7 +118,8 @@ async def create_gist(request: Request, data: Annotated[GistForm, Form()]):
"source_code": source_code,
"language": language,
}, title, XP_GIST, "First Gist", description or "", data.attachment_uids)
return RedirectResponse(url=f"/gists/{gist_slug}", status_code=302)
url = f"/gists/{gist_slug}"
return action_result(request, url, data={"uid": uid, "slug": gist_slug, "url": url})
@router.post("/edit/{gist_slug}")
@@ -125,7 +128,7 @@ async def edit_gist(request: Request, gist_slug: str, data: Annotated[GistEditFo
language = data.language
if language not in {l[0] for l in LANGUAGES}:
language = "plaintext"
return edit_content_item("gists", user, gist_slug, {
return edit_content_item(request, "gists", user, gist_slug, {
"title": data.title.strip(),
"description": data.description.strip() or None,
"source_code": data.source_code.strip(),
@@ -136,4 +139,4 @@ async def edit_gist(request: Request, gist_slug: str, data: Annotated[GistEditFo
@router.post("/delete/{gist_slug}")
async def delete_gist(request: Request, gist_slug: str):
user = require_user(request)
return delete_content_item("gists", "gist", user, gist_slug, "/gists")
return delete_content_item(request, "gists", "gist", user, gist_slug, "/gists")