frdel commited on
Commit
215dbf1
·
1 Parent(s): 6ff9f06

Scheduler polishing 1

Browse files
agent.py CHANGED
@@ -163,10 +163,10 @@ class AgentContext:
163
  tool_name="call_subordinate", tool_result=msg # type: ignore
164
  )
165
  )
166
- response = await agent.monologue()
167
  superior = agent.data.get(Agent.DATA_NAME_SUPERIOR, None)
168
  if superior:
169
- response = await self._process_chain(superior, response, False)
170
  return response
171
  except Exception as e:
172
  agent.handle_critical_exception(e)
@@ -313,7 +313,7 @@ class Agent:
313
 
314
  agent_response = await self.call_chat_model(
315
  prompt, callback=stream_callback
316
- )
317
 
318
  await self.handle_intervention(agent_response)
319
 
@@ -499,13 +499,9 @@ class Agent:
499
  system_message=message.system_message
500
  )
501
 
502
- # remove empty attachments from template
503
- if (
504
- isinstance(content, dict)
505
- and "attachments" in content
506
- and not content["attachments"]
507
- ):
508
- del content["attachments"]
509
 
510
  # add to history
511
  msg = self.hist_add_message(False, content=content) # type: ignore
 
163
  tool_name="call_subordinate", tool_result=msg # type: ignore
164
  )
165
  )
166
+ response = await agent.monologue() # type: ignore
167
  superior = agent.data.get(Agent.DATA_NAME_SUPERIOR, None)
168
  if superior:
169
+ response = await self._process_chain(superior, response, False) # type: ignore
170
  return response
171
  except Exception as e:
172
  agent.handle_critical_exception(e)
 
313
 
314
  agent_response = await self.call_chat_model(
315
  prompt, callback=stream_callback
316
+ ) # type: ignore
317
 
318
  await self.handle_intervention(agent_response)
319
 
 
499
  system_message=message.system_message
500
  )
501
 
502
+ # remove empty parts from template
503
+ if isinstance(content, dict):
504
+ content = {k: v for k, v in content.items() if v}
 
 
 
 
505
 
506
  # add to history
507
  msg = self.hist_add_message(False, content=content) # type: ignore
docker/run/Dockerfile CHANGED
@@ -43,8 +43,5 @@ EXPOSE 22 80
43
 
44
  RUN chmod +x /exe/initialize.sh /exe/run_A0.sh /exe/run_searxng.sh
45
 
46
- # This is important or cron will not execute the file
47
- RUN chmod 0644 /etc/cron.d/scheduler_tick
48
-
49
  # initialize runtime and switch to supervisord
50
  CMD ["/exe/initialize.sh", "$BRANCH"]
 
43
 
44
  RUN chmod +x /exe/initialize.sh /exe/run_A0.sh /exe/run_searxng.sh
45
 
 
 
 
46
  # initialize runtime and switch to supervisord
47
  CMD ["/exe/initialize.sh", "$BRANCH"]
docker/run/DockerfileKali CHANGED
@@ -44,8 +44,5 @@ EXPOSE 22 80
44
 
45
  RUN chmod +x /exe/initialize.sh /exe/run_A0.sh /exe/run_searxng.sh
46
 
47
- # This is important or cron will not execute the file
48
- RUN chmod 0644 /etc/cron.d/scheduler_tick
49
-
50
  # initialize runtime and switch to supervisord
51
  CMD ["/exe/initialize.sh", "$BRANCH"]
 
44
 
45
  RUN chmod +x /exe/initialize.sh /exe/run_A0.sh /exe/run_searxng.sh
46
 
 
 
 
47
  # initialize runtime and switch to supervisord
48
  CMD ["/exe/initialize.sh", "$BRANCH"]
docker/run/fs/etc/cron.d/scheduler_tick DELETED
@@ -1,5 +0,0 @@
1
- # TaskScheduler CronJob
2
-
3
- * * * * * root curl http://127.0.0.1:80/scheduler_tick
4
-
5
- # END
 
 
 
 
 
 
docker/run/fs/ins/pre_install.sh CHANGED
@@ -1,5 +1,8 @@
1
  #!/bin/bash
2
 
 
 
 
3
  # Update and install necessary packages
4
  apt-get update && apt-get install -y \
5
  python3 \
 
1
  #!/bin/bash
2
 
3
+ # fix permissions for cron files
4
+ chmod 0644 /etc/cron.d/*
5
+
6
  # Update and install necessary packages
7
  apt-get update && apt-get install -y \
8
  python3 \
python/api/poll.py CHANGED
@@ -32,7 +32,7 @@ class Poll(ApiHandler):
32
  scheduler = TaskScheduler.get()
33
 
34
  # Always reload the scheduler on each poll to ensure we have the latest task state
35
- await scheduler.reload()
36
 
37
  # loop AgentContext._contexts and divide into contexts and tasks
38
 
 
32
  scheduler = TaskScheduler.get()
33
 
34
  # Always reload the scheduler on each poll to ensure we have the latest task state
35
+ # await scheduler.reload() # TODO:SCHEDULER must optimize this
36
 
37
  # loop AgentContext._contexts and divide into contexts and tasks
38
 
python/extensions/message_loop_prompts/_60_include_current_datetime.py CHANGED
@@ -7,16 +7,17 @@ from python.helpers.localization import Localization
7
  class IncludeCurrentDatetime(Extension):
8
  async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
9
  # get current datetime
10
- current_datetime = Localization.get().utc_dt_to_localtime_str(datetime.now(timezone.utc), sep=" ", timespec="seconds")
 
 
11
  # remove timezone offset
12
- current_datetime = current_datetime.split("+")[0]
13
-
14
- # remove old current datetime from loop data
15
- if "current_datetime" in loop_data.extras_temporary:
16
- del loop_data.extras_temporary["current_datetime"]
17
 
18
  # read prompt
19
- datetime_prompt = self.agent.read_prompt("agent.system.datetime.md", date_time=current_datetime)
 
 
20
 
21
  # add current datetime to the loop data
22
  loop_data.extras_temporary["current_datetime"] = datetime_prompt
 
7
  class IncludeCurrentDatetime(Extension):
8
  async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
9
  # get current datetime
10
+ current_datetime = Localization.get().utc_dt_to_localtime_str(
11
+ datetime.now(timezone.utc), sep=" ", timespec="seconds"
12
+ )
13
  # remove timezone offset
14
+ if current_datetime and "+" in current_datetime:
15
+ current_datetime = current_datetime.split("+")[0]
 
 
 
16
 
17
  # read prompt
18
+ datetime_prompt = self.agent.read_prompt(
19
+ "agent.system.datetime.md", date_time=current_datetime
20
+ )
21
 
22
  # add current datetime to the loop data
23
  loop_data.extras_temporary["current_datetime"] = datetime_prompt
python/extensions/system_prompt/_10_system_prompt.py CHANGED
@@ -15,26 +15,11 @@ class SystemPrompt(Extension):
15
 
16
 
17
  def get_main_prompt(agent: Agent):
18
- return get_prompt("agent.system.main.md", agent)
19
 
20
 
21
  def get_tools_prompt(agent: Agent):
22
- prompt = get_prompt("agent.system.tools.md", agent)
23
  if agent.config.chat_model.vision:
24
- prompt += '\n' + get_prompt("agent.system.tools_vision.md", agent)
25
- return prompt
26
-
27
-
28
- def get_prompt(file: str, agent: Agent):
29
- # variables for system prompts
30
- # TODO: move variables to the end of chain
31
- # variables in system prompt would break prompt caching, better to add them to the last message in conversation
32
- # get current datetime
33
- current_datetime = Localization.get().utc_dt_to_localtime_str(datetime.now(timezone.utc), sep=" ", timespec="seconds")
34
- # remove timezone offset
35
- current_datetime = current_datetime.split("+")[0]
36
- vars = {
37
- "date_time": current_datetime,
38
- "agent_name": agent.agent_name,
39
- }
40
- return agent.read_prompt(file, **vars)
 
15
 
16
 
17
  def get_main_prompt(agent: Agent):
18
+ return agent.read_prompt("agent.system.main.md")
19
 
20
 
21
  def get_tools_prompt(agent: Agent):
22
+ prompt = agent.read_prompt("agent.system.tools.md")
23
  if agent.config.chat_model.vision:
24
+ prompt += '\n' + agent.read_prompt("agent.system.tools_vision.md")
25
+ return prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
python/helpers/job_loop.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ from python.helpers.task_scheduler import TaskScheduler
3
+ from python.helpers.print_style import PrintStyle
4
+ from python.helpers import errors
5
+
6
+
7
+ async def run_loop():
8
+ while True:
9
+ try:
10
+ await scheduler_tick()
11
+ except Exception as e:
12
+ PrintStyle().error(errors.format_error(e))
13
+ await asyncio.sleep(60)
14
+
15
+
16
+ async def scheduler_tick():
17
+ # Get the task scheduler instance and print detailed debug info
18
+ scheduler = TaskScheduler.get()
19
+ # Run the scheduler tick
20
+ await scheduler.tick()
python/tools/input.py CHANGED
@@ -12,7 +12,7 @@ class Input(Tool):
12
 
13
  # forward keyboard input to code execution tool
14
  args = {"runtime": "terminal", "code": keyboard}
15
- cot = CodeExecution(self.agent, "code_execution_tool", args, self.message)
16
  cot.log = self.log
17
  return await cot.execute(**args)
18
 
 
12
 
13
  # forward keyboard input to code execution tool
14
  args = {"runtime": "terminal", "code": keyboard}
15
+ cot = CodeExecution(self.agent, "code_execution_tool", "", args, self.message)
16
  cot.log = self.log
17
  return await cot.execute(**args)
18
 
run_ui.py CHANGED
@@ -15,11 +15,13 @@ from python.helpers import persist_chat, runtime, dotenv, process
15
  from python.helpers.cloudflare_tunnel import CloudflareTunnel
16
  from python.helpers.extract_tools import load_classes_from_folder
17
  from python.helpers.api import ApiHandler
 
18
  from python.helpers.print_style import PrintStyle
19
  from python.helpers.task_scheduler import TaskScheduler
 
20
 
21
  # Set the new timezone to 'UTC'
22
- os.environ['TZ'] = 'UTC'
23
  # Apply the timezone change
24
  time.tzset()
25
 
@@ -35,8 +37,10 @@ basic_auth = BasicAuth(app)
35
 
36
  def is_loopback_address(address):
37
  loopback_checker = {
38
- socket.AF_INET: lambda x: struct.unpack('!I', socket.inet_aton(x))[0] >> (32 - 8) == 127,
39
- socket.AF_INET6: lambda x: x == '::1'
 
 
40
  }
41
  address_type = "hostname"
42
  try:
@@ -79,6 +83,7 @@ def requires_api_key(f):
79
  else:
80
  return Response("API key required", 401)
81
  return await f(*args, **kwargs)
 
82
  return decorated
83
 
84
 
@@ -93,6 +98,7 @@ def requires_loopback(f):
93
  {},
94
  )
95
  return await f(*args, **kwargs)
 
96
  return decorated
97
 
98
 
@@ -142,6 +148,10 @@ def run():
142
  from werkzeug.serving import WSGIRequestHandler
143
  from werkzeug.serving import make_server
144
 
 
 
 
 
145
  class NoRequestLoggingWSGIRequestHandler(WSGIRequestHandler):
146
  def log_request(self, code="-", size="-"):
147
  pass # Override to suppress request logging
@@ -188,17 +198,23 @@ def run():
188
  instance = handler(app, lock)
189
 
190
  if handler.requires_loopback():
 
191
  @requires_loopback
192
  async def handle_request():
193
  return await instance.handle_request(request=request)
 
194
  elif handler.requires_auth():
 
195
  @requires_auth
196
  async def handle_request():
197
  return await instance.handle_request(request=request)
 
198
  elif handler.requires_api_key():
 
199
  @requires_api_key
200
  async def handle_request():
201
  return await instance.handle_request(request=request)
 
202
  else:
203
  # Fallback to requires_auth
204
  @requires_auth
@@ -232,7 +248,8 @@ def run():
232
  nonlocal tunnel, server, printer
233
  with lock:
234
  printer.print("Caught signal, stopping server...")
235
- server.shutdown()
 
236
  process.stop_server()
237
  if tunnel:
238
  tunnel.stop()
 
15
  from python.helpers.cloudflare_tunnel import CloudflareTunnel
16
  from python.helpers.extract_tools import load_classes_from_folder
17
  from python.helpers.api import ApiHandler
18
+ from python.helpers.job_loop import run_loop
19
  from python.helpers.print_style import PrintStyle
20
  from python.helpers.task_scheduler import TaskScheduler
21
+ from python.helpers.defer import DeferredTask
22
 
23
  # Set the new timezone to 'UTC'
24
+ os.environ["TZ"] = "UTC"
25
  # Apply the timezone change
26
  time.tzset()
27
 
 
37
 
38
  def is_loopback_address(address):
39
  loopback_checker = {
40
+ socket.AF_INET: lambda x: struct.unpack("!I", socket.inet_aton(x))[0]
41
+ >> (32 - 8)
42
+ == 127,
43
+ socket.AF_INET6: lambda x: x == "::1",
44
  }
45
  address_type = "hostname"
46
  try:
 
83
  else:
84
  return Response("API key required", 401)
85
  return await f(*args, **kwargs)
86
+
87
  return decorated
88
 
89
 
 
98
  {},
99
  )
100
  return await f(*args, **kwargs)
101
+
102
  return decorated
103
 
104
 
 
148
  from werkzeug.serving import WSGIRequestHandler
149
  from werkzeug.serving import make_server
150
 
151
+ PrintStyle().print("Starting job loop...")
152
+ job_loop = DeferredTask().start_task(run_loop)
153
+
154
+ PrintStyle().print("Starting server...")
155
  class NoRequestLoggingWSGIRequestHandler(WSGIRequestHandler):
156
  def log_request(self, code="-", size="-"):
157
  pass # Override to suppress request logging
 
198
  instance = handler(app, lock)
199
 
200
  if handler.requires_loopback():
201
+
202
  @requires_loopback
203
  async def handle_request():
204
  return await instance.handle_request(request=request)
205
+
206
  elif handler.requires_auth():
207
+
208
  @requires_auth
209
  async def handle_request():
210
  return await instance.handle_request(request=request)
211
+
212
  elif handler.requires_api_key():
213
+
214
  @requires_api_key
215
  async def handle_request():
216
  return await instance.handle_request(request=request)
217
+
218
  else:
219
  # Fallback to requires_auth
220
  @requires_auth
 
248
  nonlocal tunnel, server, printer
249
  with lock:
250
  printer.print("Caught signal, stopping server...")
251
+ if server:
252
+ server.shutdown()
253
  process.stop_server()
254
  if tunnel:
255
  tunnel.stop()
test_scheduler.py DELETED
@@ -1,16 +0,0 @@
1
- from python.helpers.task_scheduler import ScheduledTask, TaskSchedule, SchedulerTaskList, TaskState
2
- import asyncio
3
-
4
- slist = SchedulerTaskList.get()
5
-
6
- print(slist.model_dump_json(indent=4))
7
-
8
- for task in slist.tasks:
9
- t = slist.get_task_by_uuid(task.uuid)
10
- t.update(state=TaskState.DISABLED)
11
- print("-" * 100)
12
- print(t.model_dump_json(indent=4))
13
-
14
- print("-" * 100)
15
-
16
- print(slist.model_dump_json(indent=4))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
webui/css/settings.css CHANGED
@@ -329,21 +329,21 @@ nav ul li a img {
329
 
330
  .settings-tab.active {
331
  border-color: var(--color-border);
332
- box-shadow:
333
  0 -4px 8px -2px var(--color-border),
334
  4px 0 8px -2px var(--color-border),
335
- -4px 0 8px -2px var(--color-border);
336
  font-weight: bold;
337
  background-color: var(--color-panel);
338
  }
339
 
340
  /* Light mode overrides */
341
  .light-mode .settings-tab.active {
342
- color: var(--color-border);
343
- box-shadow:
344
  0 -4px 8px -2px var(--color-border),
345
  4px 0 8px -2px var(--color-border),
346
- -4px 0 8px -2px var(--color-border);
347
  }
348
 
349
  .light-mode .settings-tab:not(.active) {
 
329
 
330
  .settings-tab.active {
331
  border-color: var(--color-border);
332
+ /* box-shadow:
333
  0 -4px 8px -2px var(--color-border),
334
  4px 0 8px -2px var(--color-border),
335
+ -4px 0 8px -2px var(--color-border); */
336
  font-weight: bold;
337
  background-color: var(--color-panel);
338
  }
339
 
340
  /* Light mode overrides */
341
  .light-mode .settings-tab.active {
342
+ /* color: var(--color-border); */
343
+ /* box-shadow:
344
  0 -4px 8px -2px var(--color-border),
345
  4px 0 8px -2px var(--color-border),
346
+ -4px 0 8px -2px var(--color-border); */
347
  }
348
 
349
  .light-mode .settings-tab:not(.active) {
webui/index.css CHANGED
@@ -2259,7 +2259,7 @@ a:active {
2259
 
2260
  .light-mode .tab.active::after {
2261
  background-color: var(--highlight-pink);
2262
- box-shadow: 0 0 8px var(--highlight-pink);
2263
  }
2264
  /* Tabs styling */
2265
  .tabs-container {
@@ -2300,10 +2300,10 @@ a:active {
2300
 
2301
  .tab.active {
2302
  border-color: var(--color-border);
2303
- box-shadow:
2304
  0 -4px 8px -2px var(--color-border),
2305
  4px 0 8px -2px var(--color-border),
2306
- -4px 0 8px -2px var(--color-border);
2307
  font-weight: bold;
2308
  background-color: var(--color-panel);
2309
  }
 
2259
 
2260
  .light-mode .tab.active::after {
2261
  background-color: var(--highlight-pink);
2262
+ /* box-shadow: 0 0 8px var(--highlight-pink); */
2263
  }
2264
  /* Tabs styling */
2265
  .tabs-container {
 
2300
 
2301
  .tab.active {
2302
  border-color: var(--color-border);
2303
+ /* box-shadow:
2304
  0 -4px 8px -2px var(--color-border),
2305
  4px 0 8px -2px var(--color-border),
2306
+ -4px 0 8px -2px var(--color-border); */
2307
  font-weight: bold;
2308
  background-color: var(--color-panel);
2309
  }