feat: add TTLCache for get_cache_version and TEMPLATE_AUTO_RELOAD config with Makefile worker count variables

This commit is contained in:
2026-06-14 14:46:36 +00:00
parent c151325916
commit d75d5dc6a8
149 changed files with 9811 additions and 262 deletions
@@ -1160,6 +1160,19 @@ ACTIONS: tuple[Action, ...] = (
params=(path("uid", "Audit event uid."),),
requires_admin=True,
),
Action(
name="bot_monitor",
method="GET",
path="/admin/bots/data",
summary="Live screenshot monitor of every running bot persona (admin only)",
description=(
"Returns JSON: one entry per running bot slot with its username, persona, current "
"action and status text, last page url, frame age in seconds, whether it is active, "
"and a frame_url to the latest low-quality screenshot. Use this to see what the bot "
"fleet is doing right now. Frames live only in the worker running the Bots service."
),
requires_admin=True,
),
Action(
name="admin_list_users",
method="GET",
@@ -45,6 +45,22 @@ CONTAINER_ACTIONS: tuple[Action, ...] = (
arg(
"boot_command", "Optional command to run on boot, e.g. 'python app.py'."
),
arg(
"boot_language",
"Optional boot source language: 'none', 'python', or 'bash'. When set with boot_script, the script is materialized into /app and run on launch (takes precedence over boot_command).",
),
arg(
"boot_script",
"Optional boot source code (the body of the python or bash script) run on launch when boot_language is python or bash.",
),
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).",
),
arg(
"start_on_boot",
"Force this instance to running whenever the container service starts ('true' or 'false', default false).",
),
arg("restart_policy", "never, always, on-failure, or unless-stopped."),
arg("env", "Optional env vars as KEY=VALUE lines."),
arg(
@@ -90,6 +106,32 @@ CONTAINER_ACTIONS: tuple[Action, ...] = (
),
),
),
Action(
name="container_configure_instance",
method="LOCAL",
path="",
handler="container",
requires_admin=True,
summary="Update an instance's run-as user, boot language/script/command, restart policy, start-on-boot flag, and resource limits",
params=(
SLUG,
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).",
),
arg("boot_language", "Boot source language: 'none', 'python', or 'bash'."),
arg("boot_script", "Boot source code body run on launch."),
arg("boot_command", "Fallback boot command used when no boot_script is set."),
arg("restart_policy", "never, always, on-failure, or unless-stopped."),
arg(
"start_on_boot",
"Force running on container-service start ('true' or 'false').",
),
arg("cpu_limit", "CPU limit, e.g. 1 or 1.5."),
arg("mem_limit", "Memory limit, e.g. 512m or 1g."),
),
),
Action(
name="container_logs",
method="LOCAL",
@@ -103,6 +103,7 @@ _DEVII_MECHANIC_EVENTS = {
_DEVII_CONTAINER_EVENTS = {
"container_create_instance": "container.instance.create",
"container_configure_instance": "container.instance.configure",
"container_exec": "container.instance.exec",
"container_schedule": "container.schedule.create",
}
@@ -42,6 +42,10 @@ class Action:
"chunks",
"rsearch",
"container",
"customization",
"notification",
"behavior",
"virtual_tool",
] = "http"
freeform_body: bool = False
ajax: bool = False
@@ -79,10 +79,20 @@ class ContainerController:
"no",
"off",
)
start_on_boot = str(arguments.get("start_on_boot", "false")).lower() in (
"true",
"1",
"yes",
"on",
)
inst = await api.create_instance(
project,
name=str(arguments.get("name", "")),
boot_command=str(arguments.get("boot_command", "")),
boot_language=str(arguments.get("boot_language", "none")),
boot_script=str(arguments.get("boot_script", "")),
run_as_uid=str(arguments.get("run_as_uid", "")),
start_on_boot=start_on_boot,
env=arguments.get("env", ""),
cpu_limit=str(arguments.get("cpu_limit", "")),
mem_limit=str(arguments.get("mem_limit", "")),
@@ -105,8 +115,8 @@ class ContainerController:
if action == "delete":
api.mark_for_removal(inst, actor=actor)
elif action == "sync":
count = await api.sync_workspace(inst, self._actor_user())
return json.dumps({"status": "synced", "imported": count})
counts = await api.sync_workspace(inst, self._actor_user())
return json.dumps({"status": "synced", **counts})
elif action == "restart":
api.request_restart(inst, actor=actor)
elif action in ("start", "resume"):
@@ -119,6 +129,32 @@ class ContainerController:
raise ToolInputError(f"unknown action: {action}")
return json.dumps({"status": "ok", "action": action, "instance": inst["uid"]})
async def _configure_instance(self, arguments) -> str:
project = self._project(arguments)
inst = self._instance(project, str(arguments.get("instance", "")))
actor = ("user", self._actor_user()["uid"])
kwargs: dict = {}
for key in (
"run_as_uid",
"boot_language",
"boot_script",
"boot_command",
"restart_policy",
"cpu_limit",
"mem_limit",
):
if key in arguments and arguments.get(key) is not None:
kwargs[key] = str(arguments.get(key))
if "start_on_boot" in arguments and arguments.get("start_on_boot") is not None:
kwargs["start_on_boot"] = str(arguments.get("start_on_boot")).lower() in (
"true",
"1",
"yes",
"on",
)
updated = api.update_instance_config(inst, actor=actor, **kwargs)
return json.dumps({"status": "configured", "instance": updated}, default=str)
async def _logs(self, arguments) -> str:
project = self._project(arguments)
inst = self._instance(project, str(arguments.get("instance", "")))