feat: version display + issues board
Version: CalVer + git hash shown in top-right corner of main page. Built via Docker ARG BUILD_VERSION at build time. Served via /api-version. Issues Board: shared notepad window for tracking issues with plugin, overlord, nav files, macros. Stored in openissues.json on server. - GET/POST/DELETE /issues endpoints - Draggable window matching Chat/Radar pattern - Category tags (plugin, overlord, nav, macro, other) with colors - Add/resolve issues through the UI Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c4856dc701
commit
38ca6ead12
5 changed files with 258 additions and 1 deletions
59
main.py
59
main.py
|
|
@ -10,6 +10,7 @@ from datetime import datetime, timedelta, timezone
|
|||
import json
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
import sys
|
||||
import time
|
||||
from typing import Dict, List, Any
|
||||
|
|
@ -1326,6 +1327,64 @@ async def get_recent_activity():
|
|||
raise HTTPException(status_code=500, detail="Internal server error")
|
||||
|
||||
|
||||
# ─── Version endpoint ────────────────────────────────────────────
|
||||
@app.get("/api-version")
|
||||
async def get_version():
|
||||
"""Return the application version (CalVer + git hash, set at build time)."""
|
||||
return {"version": os.environ.get("APP_VERSION", "dev")}
|
||||
|
||||
|
||||
# ─── Issues board endpoints ──────────────────────────────────────
|
||||
ISSUES_FILE = Path("openissues.json")
|
||||
|
||||
|
||||
def _load_issues():
|
||||
if ISSUES_FILE.exists():
|
||||
try:
|
||||
return json.loads(ISSUES_FILE.read_text())
|
||||
except (json.JSONDecodeError, IOError):
|
||||
pass
|
||||
return []
|
||||
|
||||
|
||||
def _save_issues(issues):
|
||||
ISSUES_FILE.write_text(json.dumps(issues, indent=2))
|
||||
|
||||
|
||||
@app.get("/issues")
|
||||
async def get_issues():
|
||||
"""Return all open issues."""
|
||||
return {"issues": _load_issues()}
|
||||
|
||||
|
||||
@app.post("/issues")
|
||||
async def add_issue(issue: dict):
|
||||
"""Add a new issue."""
|
||||
issues = _load_issues()
|
||||
new_issue = {
|
||||
"id": uuid.uuid4().hex[:8],
|
||||
"title": issue.get("title", "").strip(),
|
||||
"description": issue.get("description", "").strip(),
|
||||
"category": issue.get("category", "other"),
|
||||
"author": issue.get("author", "Anonymous").strip(),
|
||||
"created": datetime.utcnow().isoformat(),
|
||||
}
|
||||
if not new_issue["title"]:
|
||||
raise HTTPException(status_code=400, detail="Title is required")
|
||||
issues.insert(0, new_issue)
|
||||
_save_issues(issues)
|
||||
return new_issue
|
||||
|
||||
|
||||
@app.delete("/issues/{issue_id}")
|
||||
async def delete_issue(issue_id: str):
|
||||
"""Resolve (delete) an issue."""
|
||||
issues = _load_issues()
|
||||
issues = [i for i in issues if i.get("id") != issue_id]
|
||||
_save_issues(issues)
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
@app.get("/server-health")
|
||||
async def get_server_health():
|
||||
"""Return current server health status."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue