Spaces:
Paused
Paused
frdel commited on
Commit ·
bd6c93a
1
Parent(s): d7b185c
update checker
Browse files
python/api/message.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
from agent import AgentContext, UserMessage
|
| 2 |
from python.helpers.api import ApiHandler, Request, Response
|
| 3 |
|
| 4 |
-
from python.helpers import files
|
| 5 |
import os
|
| 6 |
from werkzeug.utils import secure_filename
|
| 7 |
from python.helpers.defer import DeferredTask
|
|
@@ -55,6 +55,12 @@ class Message(ApiHandler):
|
|
| 55 |
# Obtain agent context
|
| 56 |
context = self.use_context(ctxid)
|
| 57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
# Store attachments in agent data
|
| 59 |
# context.agent0.set_data("attachments", attachment_paths)
|
| 60 |
|
|
|
|
| 1 |
from agent import AgentContext, UserMessage
|
| 2 |
from python.helpers.api import ApiHandler, Request, Response
|
| 3 |
|
| 4 |
+
from python.helpers import files, extension
|
| 5 |
import os
|
| 6 |
from werkzeug.utils import secure_filename
|
| 7 |
from python.helpers.defer import DeferredTask
|
|
|
|
| 55 |
# Obtain agent context
|
| 56 |
context = self.use_context(ctxid)
|
| 57 |
|
| 58 |
+
# call extension point, alow it to modify data
|
| 59 |
+
data = { "message": message, "attachment_paths": attachment_paths }
|
| 60 |
+
await extension.call_extensions("user_message_ui", agent=context.get_agent(), data=data)
|
| 61 |
+
message = data.get("message", "")
|
| 62 |
+
attachment_paths = data.get("attachment_paths", [])
|
| 63 |
+
|
| 64 |
# Store attachments in agent data
|
| 65 |
# context.agent0.set_data("attachments", attachment_paths)
|
| 66 |
|
python/extensions/user_message_ui/_10_update_check.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from python.helpers import notification
|
| 2 |
+
from python.helpers.extension import Extension
|
| 3 |
+
from agent import LoopData
|
| 4 |
+
from python.helpers import settings, update_check
|
| 5 |
+
import datetime
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
# check for newer versions of A0 available and send notification
|
| 9 |
+
# check after user message is sent from UI, not API, MCP etc. (user is active and can see the notification)
|
| 10 |
+
# do not check too often, use cooldown
|
| 11 |
+
# do not notify too often unless there's a different notification
|
| 12 |
+
|
| 13 |
+
last_check = datetime.datetime.fromtimestamp(0)
|
| 14 |
+
check_cooldown_seconds = 60
|
| 15 |
+
last_notification_id = ""
|
| 16 |
+
last_notification_time = datetime.datetime.fromtimestamp(0)
|
| 17 |
+
notification_cooldown_seconds = 60 * 60 * 24
|
| 18 |
+
|
| 19 |
+
class UpdateCheck(Extension):
|
| 20 |
+
|
| 21 |
+
async def execute(self, loop_data: LoopData = LoopData(), text: str = "", **kwargs):
|
| 22 |
+
try:
|
| 23 |
+
global last_check, last_notification_id, last_notification_time
|
| 24 |
+
|
| 25 |
+
# first check if update check is enabled
|
| 26 |
+
current_settings = settings.get_settings()
|
| 27 |
+
if not current_settings["update_check_enabled"]:
|
| 28 |
+
return
|
| 29 |
+
|
| 30 |
+
# check if cooldown has passed
|
| 31 |
+
if (datetime.datetime.now() - last_check).total_seconds() < check_cooldown_seconds:
|
| 32 |
+
return
|
| 33 |
+
last_check = datetime.datetime.now()
|
| 34 |
+
|
| 35 |
+
# check for updates
|
| 36 |
+
version = await update_check.check_version()
|
| 37 |
+
|
| 38 |
+
# if the user should update, send notification
|
| 39 |
+
if notif := version.get("notification"):
|
| 40 |
+
if notif.get("id") != last_notification_id or (datetime.datetime.now() - last_notification_time).total_seconds() > notification_cooldown_seconds:
|
| 41 |
+
last_notification_id = notif.get("id")
|
| 42 |
+
last_notification_time = datetime.datetime.now()
|
| 43 |
+
self.send_notification(notif)
|
| 44 |
+
except Exception as e:
|
| 45 |
+
pass # no need to log if the update server is inaccessible
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def send_notification(self, notif):
|
| 49 |
+
notifs = self.agent.context.get_notification_manager()
|
| 50 |
+
notifs.send_notification(
|
| 51 |
+
title=notif.get("title", "Newer version available"),
|
| 52 |
+
message=notif.get("message", "A newer version of Agent Zero is available. Please update to the latest version."),
|
| 53 |
+
type=notif.get("type", "info"),
|
| 54 |
+
detail=notif.get("detail", ""),
|
| 55 |
+
display_time=notif.get("display_time", 10),
|
| 56 |
+
group=notif.get("group", "update_check"),
|
| 57 |
+
priority=notif.get("priority", notification.NotificationPriority.NORMAL),
|
| 58 |
+
)
|
python/helpers/git.py
CHANGED
|
@@ -47,4 +47,11 @@ def get_git_info():
|
|
| 47 |
"version": version
|
| 48 |
}
|
| 49 |
|
| 50 |
-
return git_info
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
"version": version
|
| 48 |
}
|
| 49 |
|
| 50 |
+
return git_info
|
| 51 |
+
|
| 52 |
+
def get_version():
|
| 53 |
+
try:
|
| 54 |
+
git_info = get_git_info()
|
| 55 |
+
return str(git_info.get("short_tag", "")).strip() or "unknown"
|
| 56 |
+
except Exception:
|
| 57 |
+
return "unknown"
|
python/helpers/settings.py
CHANGED
|
@@ -111,6 +111,8 @@ class Settings(TypedDict):
|
|
| 111 |
# LiteLLM global kwargs applied to all model calls
|
| 112 |
litellm_global_kwargs: dict[str, Any]
|
| 113 |
|
|
|
|
|
|
|
| 114 |
class PartialSettings(Settings, total=False):
|
| 115 |
pass
|
| 116 |
|
|
@@ -1217,6 +1219,27 @@ def convert_out(settings: Settings) -> SettingsOutput:
|
|
| 1217 |
"tab": "external",
|
| 1218 |
}
|
| 1219 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1220 |
# Backup & Restore section
|
| 1221 |
backup_fields: list[SettingsField] = []
|
| 1222 |
|
|
@@ -1269,6 +1292,7 @@ def convert_out(settings: Settings) -> SettingsOutput:
|
|
| 1269 |
mcp_server_section,
|
| 1270 |
a2a_section,
|
| 1271 |
external_api_section,
|
|
|
|
| 1272 |
backup_section,
|
| 1273 |
dev_section,
|
| 1274 |
# code_exec_section,
|
|
@@ -1502,6 +1526,7 @@ def get_default_settings() -> Settings:
|
|
| 1502 |
variables="",
|
| 1503 |
secrets="",
|
| 1504 |
litellm_global_kwargs={},
|
|
|
|
| 1505 |
)
|
| 1506 |
|
| 1507 |
|
|
@@ -1706,8 +1731,4 @@ def create_auth_token() -> str:
|
|
| 1706 |
|
| 1707 |
|
| 1708 |
def _get_version():
|
| 1709 |
-
|
| 1710 |
-
git_info = git.get_git_info()
|
| 1711 |
-
return str(git_info.get("short_tag", "")).strip() or "unknown"
|
| 1712 |
-
except Exception:
|
| 1713 |
-
return "unknown"
|
|
|
|
| 111 |
# LiteLLM global kwargs applied to all model calls
|
| 112 |
litellm_global_kwargs: dict[str, Any]
|
| 113 |
|
| 114 |
+
update_check_enabled: bool
|
| 115 |
+
|
| 116 |
class PartialSettings(Settings, total=False):
|
| 117 |
pass
|
| 118 |
|
|
|
|
| 1219 |
"tab": "external",
|
| 1220 |
}
|
| 1221 |
|
| 1222 |
+
# update checker section
|
| 1223 |
+
update_checker_fields: list[SettingsField] = []
|
| 1224 |
+
|
| 1225 |
+
update_checker_fields.append(
|
| 1226 |
+
{
|
| 1227 |
+
"id": "update_check_enabled",
|
| 1228 |
+
"title": "Enable Update Checker",
|
| 1229 |
+
"description": "Enable update checker to notify about newer versions of Agent Zero.",
|
| 1230 |
+
"type": "switch",
|
| 1231 |
+
"value": settings["update_check_enabled"],
|
| 1232 |
+
}
|
| 1233 |
+
)
|
| 1234 |
+
|
| 1235 |
+
update_checker_section: SettingsSection = {
|
| 1236 |
+
"id": "update_checker",
|
| 1237 |
+
"title": "Update Checker",
|
| 1238 |
+
"description": "Update checker periodically checks for new releases of Agent Zero and will notify when an update is recommended.<br>No personal data is sent to the update server, only randomized+anonymized unique ID and current version number, which help us evaluate the importance of the update in case of critical bug fixes etc.",
|
| 1239 |
+
"fields": update_checker_fields,
|
| 1240 |
+
"tab": "external",
|
| 1241 |
+
}
|
| 1242 |
+
|
| 1243 |
# Backup & Restore section
|
| 1244 |
backup_fields: list[SettingsField] = []
|
| 1245 |
|
|
|
|
| 1292 |
mcp_server_section,
|
| 1293 |
a2a_section,
|
| 1294 |
external_api_section,
|
| 1295 |
+
update_checker_section,
|
| 1296 |
backup_section,
|
| 1297 |
dev_section,
|
| 1298 |
# code_exec_section,
|
|
|
|
| 1526 |
variables="",
|
| 1527 |
secrets="",
|
| 1528 |
litellm_global_kwargs={},
|
| 1529 |
+
update_check_enabled=True,
|
| 1530 |
)
|
| 1531 |
|
| 1532 |
|
|
|
|
| 1731 |
|
| 1732 |
|
| 1733 |
def _get_version():
|
| 1734 |
+
return git.get_version()
|
|
|
|
|
|
|
|
|
|
|
|
python/helpers/update_check.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from python.helpers import git, runtime
|
| 2 |
+
import hashlib
|
| 3 |
+
|
| 4 |
+
async def check_version():
|
| 5 |
+
import httpx
|
| 6 |
+
|
| 7 |
+
current_version = git.get_version()
|
| 8 |
+
anonymized_id = hashlib.sha256(runtime.get_persistent_id().encode()).hexdigest()[:20]
|
| 9 |
+
|
| 10 |
+
url = "https://api.agent-zero.ai/a0-update-check"
|
| 11 |
+
payload = {"current_version": current_version, "anonymized_id": anonymized_id}
|
| 12 |
+
async with httpx.AsyncClient() as client:
|
| 13 |
+
response = await client.post(url, json=payload)
|
| 14 |
+
version = response.json()
|
| 15 |
+
return version
|