feat: add ISSLOP AI usage analysis CLI commands, game router, and politics topic
- Add `cmd_isslop_prune`, `cmd_isslop_clear`, `cmd_isslop_analyze` CLI commands for AI usage analysis job management - Register `/game` router with `index` and `farm` endpoints for Code Farm idle game - Add `politics` to allowed TOPICS constant replacing `signals` - Introduce `ISSLOP_DIR`, `ISSLOP_WORKSPACES_DIR`, `ISSLOP_RUNS_DIR`, `ISSLOP_MEDIA_DIR` config paths - Add `clear_user_stars` and `clear_user_projects_cache` calls on vote and project create/delete - Update `make prod` to use `nproc` workers via `DEVPLACE_WEB_WORKERS` env var - Convert `database.py` and `utils.py` to packages for modular structure - Add `devplace apikey` and `devplace token` CLI subcommands for API key and access token management
This commit is contained in:
@@ -108,4 +108,58 @@ TOOLS_ACTIONS: tuple[Action, ...] = (
|
||||
params=(path("uid", "DeepSearch job uid returned by deepsearch."),),
|
||||
requires_auth=False,
|
||||
),
|
||||
Action(
|
||||
name="isslop",
|
||||
method="POST",
|
||||
path="/tools/isslop/run",
|
||||
summary="Classify a repository or website as AI slop or human work",
|
||||
description=(
|
||||
"Queues a background AI Usage Analyzer job and returns {uid, status_url, report_url}. "
|
||||
"Poll the status with isslop_status until status is 'completed', then share the "
|
||||
"authenticity grade, category, human/AI split and report_url. Accepts http(s), "
|
||||
"git and ssh source URLs."
|
||||
),
|
||||
params=(
|
||||
body("url", "Repository or website URL to classify.", required=True),
|
||||
),
|
||||
requires_auth=True,
|
||||
),
|
||||
Action(
|
||||
name="isslop_status",
|
||||
method="GET",
|
||||
path="/tools/isslop/{uid}",
|
||||
summary="Check a AI usage analysis and obtain its verdict once finished",
|
||||
description=(
|
||||
"Returns the analysis status. When status is 'completed', grade, category, "
|
||||
"human_percent, ai_percent and report_url are populated; while 'pending' or "
|
||||
"'running', poll again shortly."
|
||||
),
|
||||
params=(path("uid", "Analysis uid returned by isslop."),),
|
||||
requires_auth=True,
|
||||
),
|
||||
Action(
|
||||
name="isslop_report",
|
||||
method="GET",
|
||||
path="/tools/isslop/{uid}/report",
|
||||
summary="Read a finished AI usage analysis report",
|
||||
description=(
|
||||
"Returns the full report for a finished analysis: authenticity grade, human/AI "
|
||||
"split, markdown findings, per-file scores with signals, the image review and the "
|
||||
"embeddable badge snippets. Use it after isslop_status reports status 'completed'."
|
||||
),
|
||||
params=(path("uid", "Analysis uid returned by isslop."),),
|
||||
requires_auth=True,
|
||||
),
|
||||
Action(
|
||||
name="isslop_list",
|
||||
method="GET",
|
||||
path="/tools/isslop/list",
|
||||
summary="List the user's AI usage analyses",
|
||||
description=(
|
||||
"Returns the signed-in user's analysis history, newest first, each with its grade, "
|
||||
"category, status and report_url."
|
||||
),
|
||||
params=(),
|
||||
requires_auth=True,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -55,7 +55,7 @@ CONTAINER_ACTIONS: tuple[Action, ...] = (
|
||||
),
|
||||
arg(
|
||||
"run_as_uid",
|
||||
"Optional DevPlace user uid whose identity and API key are injected (PRAVDA_API_KEY, PRAVDA_USER_UID). Does NOT change the container OS user, which is always pravda (uid 1000).",
|
||||
"Optional DevPlace user uid whose identity and API key are injected (DEVPLACE_API_KEY, DEVPLACE_USER_UID). Does NOT change the container OS user, which is always pravda (uid 1000).",
|
||||
),
|
||||
arg(
|
||||
"start_on_boot",
|
||||
@@ -118,7 +118,7 @@ CONTAINER_ACTIONS: tuple[Action, ...] = (
|
||||
arg("instance", "Instance name, slug, or uid.", required=True),
|
||||
arg(
|
||||
"run_as_uid",
|
||||
"DevPlace user uid whose identity and API key are injected (PRAVDA_API_KEY, PRAVDA_USER_UID); pass empty to clear. Does NOT change the container OS user (always pravda, uid 1000).",
|
||||
"DevPlace user uid whose identity and API key are injected (DEVPLACE_API_KEY, DEVPLACE_USER_UID); pass empty to clear. Does NOT change the container OS user (always pravda, uid 1000).",
|
||||
),
|
||||
arg("boot_language", "Boot source language: 'none', 'python', or 'bash'."),
|
||||
arg("boot_script", "Boot source code body run on launch."),
|
||||
|
||||
@@ -287,7 +287,7 @@ class Dispatcher:
|
||||
self._rsearch = RsearchController(settings, owner_kind, owner_id)
|
||||
from ..container import ContainerController
|
||||
|
||||
self._container = ContainerController(client)
|
||||
self._container = ContainerController(client, owner_id=owner_id)
|
||||
from ..customization import CustomizationController
|
||||
|
||||
self._customization = CustomizationController(owner_kind, owner_id)
|
||||
|
||||
@@ -4,7 +4,7 @@ import json
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from devplacepy.database import get_table, resolve_by_slug
|
||||
from devplacepy.database import get_table, get_users_by_uids, resolve_by_slug
|
||||
from devplacepy.services.containers import api, store
|
||||
from devplacepy.services.containers.api import ContainerError
|
||||
from devplacepy.services.containers.runtime import get_backend
|
||||
@@ -15,8 +15,9 @@ logger = logging.getLogger("devii.container")
|
||||
|
||||
|
||||
class ContainerController:
|
||||
def __init__(self, client: Any = None) -> None:
|
||||
def __init__(self, client: Any = None, owner_id: str = "") -> None:
|
||||
self._client = client
|
||||
self._owner_id = owner_id
|
||||
|
||||
def _ingress_url(self, instance: dict):
|
||||
slug = instance.get("ingress_slug")
|
||||
@@ -29,11 +30,19 @@ class ContainerController:
|
||||
|
||||
def _actor_user(self) -> dict:
|
||||
username = getattr(self._client, "username", None)
|
||||
if username:
|
||||
if username and username != "api-key":
|
||||
user = get_table("users").find_one(username=username)
|
||||
if user:
|
||||
return user
|
||||
return {"uid": "admin", "username": username or "admin"}
|
||||
if self._owner_id:
|
||||
user = get_users_by_uids([self._owner_id]).get(self._owner_id)
|
||||
if user:
|
||||
return user
|
||||
return {
|
||||
"uid": "admin",
|
||||
"username": username or "admin",
|
||||
"role": "Admin",
|
||||
}
|
||||
|
||||
def _project(self, arguments: dict) -> dict:
|
||||
from devplacepy.content import can_view_project
|
||||
|
||||
Reference in New Issue
Block a user