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
- try:
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