chore: C2 DELETE 204+body, C4 cached_tokens, C5 utcnow + LICENSE (T011)
tests / pytest (push) Has been cancelled
tests / pytest (push) Has been cancelled
This commit is contained in:
@@ -8,7 +8,7 @@ from typing import Optional, Dict, Any, List
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI, Depends, HTTPException, Request
|
||||
from fastapi import FastAPI, Depends, HTTPException, Request, Response
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
@@ -198,10 +198,10 @@ async def api_delete_agent(
|
||||
# Code-Agents: nur deaktivieren, damit sie beim nächsten Sync wieder da sind
|
||||
await set_agent_enabled(db, agent_id, False)
|
||||
await log_audit(db, agent_id=agent_id, user_id=user_id, action="agent_disabled_via_delete", target=agent_id)
|
||||
return {"status": "disabled", "note": "Code-Agents werden nicht gelöscht, nur deaktiviert"}
|
||||
return Response(status_code=204)
|
||||
await delete_agent(db, agent_id)
|
||||
await log_audit(db, agent_id=agent_id, user_id=user_id, action="agent_deleted", target=agent_id)
|
||||
return {"status": "deleted"}
|
||||
return Response(status_code=204)
|
||||
|
||||
|
||||
@app.post("/api/agents/{agent_id}/enable")
|
||||
|
||||
@@ -8,7 +8,7 @@ import aiosqlite
|
||||
import json
|
||||
import uuid
|
||||
import secrets
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
from config import settings
|
||||
|
||||
@@ -267,7 +267,7 @@ async def list_audit(db, agent_id=None, limit=100):
|
||||
|
||||
async def create_session(db, user_id="default", ttl_hours=24):
|
||||
token = secrets.token_urlsafe(32)
|
||||
expires = (datetime.utcnow() + timedelta(hours=ttl_hours)).isoformat()
|
||||
expires = (datetime.now(timezone.utc).replace(tzinfo=None) + timedelta(hours=ttl_hours)).isoformat()
|
||||
await db.execute(
|
||||
"INSERT INTO sessions (token, user_id, expires_at) VALUES (?, ?, ?)",
|
||||
(token, user_id, expires)
|
||||
@@ -284,6 +284,6 @@ async def validate_session(db, token):
|
||||
row = await cur.fetchone()
|
||||
if not row:
|
||||
return None
|
||||
if row[1] and datetime.fromisoformat(row[1]) < datetime.utcnow():
|
||||
if row[1] and datetime.fromisoformat(row[1]) < datetime.now(timezone.utc).replace(tzinfo=None):
|
||||
return None
|
||||
return row[0]
|
||||
|
||||
@@ -72,10 +72,20 @@ async def chat(
|
||||
|
||||
usage = {}
|
||||
if hasattr(response, "usage") and response.usage:
|
||||
# LiteLLM exposes cached prompt tokens via prompt_tokens_details.cached_tokens
|
||||
# (see litellm.types.utils.Usage). Providers like Anthropic/OpenAI surface this
|
||||
# when prompt caching is active; surfacing it here flows through LLMResponse.usage
|
||||
# to any audit log that serialises the usage dict.
|
||||
cached_tokens = 0
|
||||
details = getattr(response.usage, "prompt_tokens_details", None)
|
||||
if details is not None:
|
||||
cached_tokens = getattr(details, "cached_tokens", None) or 0
|
||||
|
||||
usage = {
|
||||
"prompt_tokens": response.usage.prompt_tokens or 0,
|
||||
"completion_tokens": response.usage.completion_tokens or 0,
|
||||
"total_tokens": response.usage.total_tokens or 0,
|
||||
"cached_tokens": cached_tokens,
|
||||
"finish_reason": response.choices[0].finish_reason or "stop",
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user