lybic-guiagents 0.3.0__py3-none-any.whl → 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lybic-guiagents might be problematic. Click here for more details.
- gui_agents/__init__.py +1 -1
- gui_agents/agents/agent_s.py +73 -25
- gui_agents/agents/global_state.py +13 -1
- gui_agents/agents/grounding.py +19 -4
- gui_agents/agents/manager.py +13 -1
- gui_agents/agents/worker.py +20 -4
- gui_agents/cli_app.py +242 -217
- gui_agents/grpc_app.py +265 -90
- gui_agents/service/agent_service.py +51 -34
- gui_agents/store/registry.py +114 -6
- {lybic_guiagents-0.3.0.dist-info → lybic_guiagents-0.5.0.dist-info}/METADATA +6 -6
- {lybic_guiagents-0.3.0.dist-info → lybic_guiagents-0.5.0.dist-info}/RECORD +16 -16
- {lybic_guiagents-0.3.0.dist-info → lybic_guiagents-0.5.0.dist-info}/WHEEL +0 -0
- {lybic_guiagents-0.3.0.dist-info → lybic_guiagents-0.5.0.dist-info}/entry_points.txt +0 -0
- {lybic_guiagents-0.3.0.dist-info → lybic_guiagents-0.5.0.dist-info}/licenses/LICENSE +0 -0
- {lybic_guiagents-0.3.0.dist-info → lybic_guiagents-0.5.0.dist-info}/top_level.txt +0 -0
gui_agents/__init__.py
CHANGED
|
@@ -37,7 +37,7 @@ from .agents.hardware_interface import HardwareInterface
|
|
|
37
37
|
from .store.registry import Registry
|
|
38
38
|
from .agents.global_state import GlobalState
|
|
39
39
|
|
|
40
|
-
__version__ = "0.
|
|
40
|
+
__version__ = "0.5.0"
|
|
41
41
|
|
|
42
42
|
# Primary exports (what users should typically use)
|
|
43
43
|
__all__ = [
|
gui_agents/agents/agent_s.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import json
|
|
3
2
|
import logging
|
|
4
3
|
import os
|
|
@@ -13,7 +12,6 @@ from gui_agents.utils.common_utils import Node
|
|
|
13
12
|
from gui_agents.agents.global_state import GlobalState
|
|
14
13
|
from gui_agents.store.registry import Registry
|
|
15
14
|
from gui_agents.utils.common_utils import (
|
|
16
|
-
# call_llm_safe,
|
|
17
15
|
parse_single_code_from_string,
|
|
18
16
|
sanitize_code,
|
|
19
17
|
extract_first_agent_function,
|
|
@@ -172,8 +170,6 @@ class AgentS2(UIAgent):
|
|
|
172
170
|
else:
|
|
173
171
|
print(f"Found local knowledge base path: {kb_platform_path}")
|
|
174
172
|
|
|
175
|
-
self.reset()
|
|
176
|
-
|
|
177
173
|
def reset(self) -> None:
|
|
178
174
|
"""
|
|
179
175
|
Reinitialize core components and reset the agent's runtime state.
|
|
@@ -219,12 +215,18 @@ class AgentS2(UIAgent):
|
|
|
219
215
|
self.subtasks: List[Node] = []
|
|
220
216
|
self.search_query: str = ""
|
|
221
217
|
self.subtask_status: str = "Start"
|
|
222
|
-
|
|
218
|
+
# Use task-specific registry if task_id is available, otherwise fall back to global registry
|
|
219
|
+
if self.task_id:
|
|
220
|
+
self.global_state: GlobalState = Registry.get_from_context("GlobalStateStore", self.task_id) # type: ignore
|
|
221
|
+
else:
|
|
222
|
+
self.global_state: GlobalState = Registry.get("GlobalStateStore") # type: ignore
|
|
223
223
|
|
|
224
224
|
# Pass task_id to components
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
self.manager.set_task_id(self.task_id)
|
|
226
|
+
self.worker.set_task_id(self.task_id)
|
|
227
|
+
# Grounding doesn't have task_id in normal mode, but we set it if available
|
|
228
|
+
if hasattr(self, 'grounding') and hasattr(self.grounding, 'set_task_id'):
|
|
229
|
+
self.grounding.set_task_id(self.task_id)
|
|
228
230
|
|
|
229
231
|
def set_task_id(self, task_id: str) -> None:
|
|
230
232
|
"""
|
|
@@ -236,9 +238,9 @@ class AgentS2(UIAgent):
|
|
|
236
238
|
self.task_id = task_id
|
|
237
239
|
# Also set task_id for components if they exist
|
|
238
240
|
if hasattr(self, 'manager') and self.manager:
|
|
239
|
-
self.manager.task_id
|
|
241
|
+
self.manager.set_task_id(task_id)
|
|
240
242
|
if hasattr(self, 'worker') and self.worker:
|
|
241
|
-
self.worker.task_id
|
|
243
|
+
self.worker.set_task_id(task_id)
|
|
242
244
|
|
|
243
245
|
def reset_executor_state(self) -> None:
|
|
244
246
|
"""Reset executor and step counter"""
|
|
@@ -249,17 +251,28 @@ class AgentS2(UIAgent):
|
|
|
249
251
|
# Initialize the three info dictionaries
|
|
250
252
|
"""
|
|
251
253
|
Produce the next executor actions and diagnostic information for the current task step.
|
|
252
|
-
|
|
254
|
+
|
|
253
255
|
This method coordinates planning, subtask selection, action generation, grounding (code extraction and execution), and status updates. It may trigger replanning, advance to the next subtask, mark subtasks as completed or failed, and emit stream messages and logs. The returned info merges planner, executor, and evaluator metadata and includes current subtask details.
|
|
254
|
-
|
|
256
|
+
|
|
255
257
|
Parameters:
|
|
256
258
|
instruction (str): The user or system instruction describing the task to accomplish; forwarded to the manager/worker as the task utterance.
|
|
257
259
|
observation (Dict): Current environment observation/state used for grounding and coordinate assignment.
|
|
258
|
-
|
|
260
|
+
|
|
259
261
|
Returns:
|
|
260
262
|
info (Dict): A merged dictionary containing planner_info, executor_info, evaluator_info and the keys `subtask`, `subtask_info`, and `subtask_status`.
|
|
261
263
|
actions (List[Dict]): List of action dictionaries produced for execution (may include actions with type "DONE", failure indicators, or other executor-generated actions).
|
|
262
264
|
"""
|
|
265
|
+
# Check for cancellation before starting prediction
|
|
266
|
+
if self.global_state.is_cancelled():
|
|
267
|
+
logger.info("AgentS2 prediction cancelled by user request")
|
|
268
|
+
return {
|
|
269
|
+
"subtask": "cancelled",
|
|
270
|
+
"subtask_info": "",
|
|
271
|
+
"subtask_status": "cancelled",
|
|
272
|
+
"reflection": "Task was cancelled",
|
|
273
|
+
"executor_plan": "agent.done()"
|
|
274
|
+
}, ["done"]
|
|
275
|
+
|
|
263
276
|
planner_info = {}
|
|
264
277
|
executor_info = {}
|
|
265
278
|
evaluator_info = {
|
|
@@ -276,6 +289,16 @@ class AgentS2(UIAgent):
|
|
|
276
289
|
|
|
277
290
|
# If the DONE response by the executor is for a subtask, then the agent should continue with the next subtask without sending the action to the environment
|
|
278
291
|
while not self.should_send_action:
|
|
292
|
+
# Check for cancellation in each iteration
|
|
293
|
+
if self.global_state.is_cancelled():
|
|
294
|
+
logger.info("AgentS2 prediction loop cancelled by user request")
|
|
295
|
+
return {
|
|
296
|
+
"subtask": "cancelled",
|
|
297
|
+
"subtask_info": "",
|
|
298
|
+
"subtask_status": "cancelled",
|
|
299
|
+
"reflection": "Task was cancelled",
|
|
300
|
+
"executor_plan": "agent.done()"
|
|
301
|
+
}, [{"type": "DONE"}]
|
|
279
302
|
time.sleep(5.0)
|
|
280
303
|
self.subtask_status = "In"
|
|
281
304
|
# Always time get_action_queue, even if not called
|
|
@@ -430,6 +453,15 @@ class AgentS2(UIAgent):
|
|
|
430
453
|
}
|
|
431
454
|
)
|
|
432
455
|
except Exception as e:
|
|
456
|
+
if self.global_state.is_cancelled():
|
|
457
|
+
logger.info("Cancelled during grounding; stopping without action")
|
|
458
|
+
return {
|
|
459
|
+
"subtask": "cancelled",
|
|
460
|
+
"subtask_info": "",
|
|
461
|
+
"subtask_status": "cancelled",
|
|
462
|
+
"reflection": "Task was cancelled",
|
|
463
|
+
"executor_plan": "agent.done()"
|
|
464
|
+
}, [{"type": "DONE"}]
|
|
433
465
|
logger.error("Error in parsing plan code: %s", e)
|
|
434
466
|
plan_code = "agent.wait(1.0)"
|
|
435
467
|
agent: Grounding = self.grounding # this agent will be used in next code
|
|
@@ -733,8 +765,6 @@ class AgentSFast(UIAgent):
|
|
|
733
765
|
else:
|
|
734
766
|
print(f"Found local knowledge base path: {kb_platform_path}")
|
|
735
767
|
|
|
736
|
-
self.reset()
|
|
737
|
-
|
|
738
768
|
def reset(self) -> None:
|
|
739
769
|
"""
|
|
740
770
|
Reinitialize the fast-agent components and reset internal runtime state.
|
|
@@ -816,19 +846,25 @@ class AgentSFast(UIAgent):
|
|
|
816
846
|
# Reset state variables
|
|
817
847
|
self.step_count: int = 0
|
|
818
848
|
self.turn_count: int = 0
|
|
819
|
-
|
|
849
|
+
# Use task-specific registry if task_id is available, otherwise fall back to global registry
|
|
850
|
+
if self.task_id:
|
|
851
|
+
self.global_state: GlobalState = Registry.get_from_context("GlobalStateStore", self.task_id) # type: ignore
|
|
852
|
+
else:
|
|
853
|
+
self.global_state: GlobalState = Registry.get("GlobalStateStore") # type: ignore
|
|
820
854
|
self.latest_action = None
|
|
821
855
|
|
|
822
|
-
# Pass task_id to tools if available
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
856
|
+
# Pass task_id to tools and components if available
|
|
857
|
+
self.fast_action_generator.task_id = self.task_id
|
|
858
|
+
if self.enable_reflection and hasattr(self, 'reflection_agent'):
|
|
859
|
+
self.reflection_agent.task_id = self.task_id
|
|
860
|
+
# Set task_id for grounding component
|
|
861
|
+
if hasattr(self, 'grounding') and hasattr(self.grounding, 'set_task_id'):
|
|
862
|
+
self.grounding.set_task_id(self.task_id)
|
|
827
863
|
|
|
828
864
|
def set_task_id(self, task_id: str) -> None:
|
|
829
865
|
"""
|
|
830
866
|
Store the task identifier on the agent and propagate it to subcomponents that use it.
|
|
831
|
-
|
|
867
|
+
|
|
832
868
|
Parameters:
|
|
833
869
|
task_id (str): Identifier for the active task; assigned to this agent and, if present, to
|
|
834
870
|
`fast_action_generator` and `reflection_agent`.
|
|
@@ -839,22 +875,34 @@ class AgentSFast(UIAgent):
|
|
|
839
875
|
self.fast_action_generator.task_id = task_id
|
|
840
876
|
if hasattr(self, 'reflection_agent') and self.reflection_agent:
|
|
841
877
|
self.reflection_agent.task_id = task_id
|
|
878
|
+
# Set task_id for grounding component
|
|
879
|
+
if hasattr(self, 'grounding') and hasattr(self.grounding, 'set_task_id'):
|
|
880
|
+
self.grounding.set_task_id(task_id)
|
|
842
881
|
|
|
843
882
|
def predict(self, instruction: str, observation: Dict) -> Tuple[Dict, List[str]]:
|
|
844
883
|
"""
|
|
845
884
|
Generate the next executor plan and corresponding actions using the configured fast action generator.
|
|
846
|
-
|
|
885
|
+
|
|
847
886
|
Parameters:
|
|
848
887
|
instruction (str): Natural language task description.
|
|
849
888
|
observation (Dict): Current UI state; must include a "screenshot" entry with the screen image.
|
|
850
|
-
|
|
889
|
+
|
|
851
890
|
Returns:
|
|
852
891
|
executor_info (dict): Contains at least the keys `executor_plan` (raw plan text), `reflection` (reflection text or empty string), and `plan_code` (the latest extracted/used action code).
|
|
853
892
|
actions (List[dict]): List of action dictionaries produced by grounding execution; typically a single action dict describing the operation to perform.
|
|
854
893
|
"""
|
|
894
|
+
# Check for cancellation before starting prediction
|
|
895
|
+
if self.global_state.is_cancelled():
|
|
896
|
+
logger.info("AgentSFast prediction cancelled by user request")
|
|
897
|
+
return {
|
|
898
|
+
"executor_plan": "agent.done()",
|
|
899
|
+
"reflection": "Task was cancelled",
|
|
900
|
+
"plan_code": "agent.done()"
|
|
901
|
+
}, [{"type": "DONE"}]
|
|
902
|
+
|
|
855
903
|
import time
|
|
856
904
|
predict_start_time = time.time()
|
|
857
|
-
|
|
905
|
+
|
|
858
906
|
fast_action_start_time = time.time()
|
|
859
907
|
|
|
860
908
|
reflection = None
|
|
@@ -467,7 +467,9 @@ class GlobalState:
|
|
|
467
467
|
return "stopped"
|
|
468
468
|
|
|
469
469
|
def set_running_state(self, state: str) -> None:
|
|
470
|
-
|
|
470
|
+
if state not in {"running", "stopped", "cancelled"}:
|
|
471
|
+
raise ValueError(f"Invalid running state: {state}")
|
|
472
|
+
|
|
471
473
|
tmp = self.running_state_path.with_suffix(".tmp")
|
|
472
474
|
try:
|
|
473
475
|
with locked(tmp, "w") as f:
|
|
@@ -486,6 +488,16 @@ class GlobalState:
|
|
|
486
488
|
pass
|
|
487
489
|
raise
|
|
488
490
|
|
|
491
|
+
def is_cancelled(self) -> bool:
|
|
492
|
+
"""Check if the current execution has been cancelled"""
|
|
493
|
+
try:
|
|
494
|
+
with locked(self.running_state_path, "r") as f:
|
|
495
|
+
data = safe_json_load(f)
|
|
496
|
+
return data == "cancelled"
|
|
497
|
+
except Exception as e:
|
|
498
|
+
logger.warning(f"Failed to check cancellation state: {e}")
|
|
499
|
+
return False
|
|
500
|
+
|
|
489
501
|
# ---------- High-level Wrappers ----------
|
|
490
502
|
def get_obs_for_manager(self):
|
|
491
503
|
return {
|
gui_agents/agents/grounding.py
CHANGED
|
@@ -92,10 +92,20 @@ class Grounding(ACI):
|
|
|
92
92
|
self.text_span_agent = Tools()
|
|
93
93
|
_register(self.text_span_agent, "text_span")
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
# GlobalState will be initialized when task_id is set
|
|
96
|
+
self.global_state: GlobalState = None # type: ignore
|
|
97
|
+
|
|
98
|
+
def set_task_id(self, task_id: str) -> None:
|
|
99
|
+
"""Set the task identifier and update global state reference"""
|
|
100
|
+
# Update global state reference with task-specific registry
|
|
101
|
+
self.global_state = Registry.get_from_context("GlobalStateStore", task_id) # type: ignore
|
|
97
102
|
|
|
98
103
|
def generate_coords(self, ref_expr: str, obs: Dict) -> List[int]:
|
|
104
|
+
# Check for cancellation before starting coordinate generation
|
|
105
|
+
if self.global_state.is_cancelled():
|
|
106
|
+
logger.info("Grounding coordinate generation cancelled by user request")
|
|
107
|
+
raise RuntimeError("cancelled") # Return default coordinates when cancelled
|
|
108
|
+
|
|
99
109
|
grounding_start_time = time.time()
|
|
100
110
|
self.grounding_model.tools["grounding"].llm_agent.reset()
|
|
101
111
|
prompt = (
|
|
@@ -453,8 +463,13 @@ class FastGrounding(ACI):
|
|
|
453
463
|
self.height = height
|
|
454
464
|
self.grounding_width = grounding_width
|
|
455
465
|
self.grounding_height = grounding_height
|
|
456
|
-
|
|
457
|
-
|
|
466
|
+
# GlobalState will be initialized when task_id is set
|
|
467
|
+
self.global_state: GlobalState = None # type: ignore
|
|
468
|
+
|
|
469
|
+
def set_task_id(self, task_id: str) -> None:
|
|
470
|
+
"""Set the task identifier and update global state reference"""
|
|
471
|
+
# Update global state reference with task-specific registry
|
|
472
|
+
self.global_state = Registry.get_from_context("GlobalStateStore", task_id) # type: ignore
|
|
458
473
|
|
|
459
474
|
def reset_screen_size(self, width: int, height: int):
|
|
460
475
|
self.width = width
|
gui_agents/agents/manager.py
CHANGED
|
@@ -102,7 +102,8 @@ class Manager:
|
|
|
102
102
|
Tools_dict=KB_Tools_dict,
|
|
103
103
|
)
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
# GlobalState will be initialized in reset() method when task_id is available
|
|
106
|
+
self.global_state: GlobalState = None # type: ignore
|
|
106
107
|
|
|
107
108
|
self.planner_history = []
|
|
108
109
|
|
|
@@ -118,6 +119,12 @@ class Manager:
|
|
|
118
119
|
|
|
119
120
|
self.multi_round = multi_round
|
|
120
121
|
|
|
122
|
+
def set_task_id(self, task_id: str) -> None:
|
|
123
|
+
"""Set the task identifier and update global state reference"""
|
|
124
|
+
self.task_id = task_id
|
|
125
|
+
# Update global state reference with task-specific registry
|
|
126
|
+
self.global_state = Registry.get_from_context("GlobalStateStore", task_id) # type: ignore
|
|
127
|
+
|
|
121
128
|
def _send_stream_message(self, task_id: str, stage: str, message: str) -> None:
|
|
122
129
|
"""
|
|
123
130
|
Enqueue a stream message for the given task if a task ID is provided.
|
|
@@ -569,6 +576,11 @@ class Manager:
|
|
|
569
576
|
"""Generate the action list based on the instruction
|
|
570
577
|
instruction:str: Instruction for the task
|
|
571
578
|
"""
|
|
579
|
+
# Check for cancellation before starting action queue generation
|
|
580
|
+
if self.global_state.is_cancelled():
|
|
581
|
+
logger.info("Manager action queue generation cancelled by user request")
|
|
582
|
+
return {"cancelled": True}, []
|
|
583
|
+
|
|
572
584
|
import time
|
|
573
585
|
action_queue_start = time.time()
|
|
574
586
|
|
gui_agents/agents/worker.py
CHANGED
|
@@ -67,8 +67,8 @@ class Worker:
|
|
|
67
67
|
|
|
68
68
|
self.enable_reflection = enable_reflection
|
|
69
69
|
self.use_subtask_experience = use_subtask_experience
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
# GlobalState will be initialized in reset() method when task_id is available
|
|
71
|
+
self.global_state: GlobalState = None # type: ignore
|
|
72
72
|
self.reset()
|
|
73
73
|
|
|
74
74
|
def reset(self):
|
|
@@ -159,6 +159,12 @@ class Worker:
|
|
|
159
159
|
self.max_trajector_length = 8
|
|
160
160
|
self.task_id = None # Will be set by agent
|
|
161
161
|
|
|
162
|
+
def set_task_id(self, task_id: str) -> None:
|
|
163
|
+
"""Set the task identifier and update global state reference"""
|
|
164
|
+
self.task_id = task_id
|
|
165
|
+
# Update global state reference with task-specific registry
|
|
166
|
+
self.global_state = Registry.get_from_context("GlobalStateStore", task_id) # type: ignore
|
|
167
|
+
|
|
162
168
|
def generate_next_action(
|
|
163
169
|
self,
|
|
164
170
|
Tu: str,
|
|
@@ -172,7 +178,7 @@ class Worker:
|
|
|
172
178
|
) -> Dict:
|
|
173
179
|
"""
|
|
174
180
|
Generate the next executor action plan and related metadata for the current subtask given the observation and context.
|
|
175
|
-
|
|
181
|
+
|
|
176
182
|
Parameters:
|
|
177
183
|
Tu (str): Full task description or task context.
|
|
178
184
|
search_query (str): Search string used for retrieving episodic/subtask experience.
|
|
@@ -182,7 +188,7 @@ class Worker:
|
|
|
182
188
|
done_task (List[Node]): List of completed task nodes.
|
|
183
189
|
obs (Dict): Current observation dictionary; must include a "screenshot" key with the current screen image.
|
|
184
190
|
running_state (str): Current executor running state (default "running").
|
|
185
|
-
|
|
191
|
+
|
|
186
192
|
Returns:
|
|
187
193
|
Dict: Executor information containing:
|
|
188
194
|
- "current_subtask" (str): The provided subtask.
|
|
@@ -190,6 +196,16 @@ class Worker:
|
|
|
190
196
|
- "executor_plan" (str): The raw plan produced by the action generator.
|
|
191
197
|
- "reflection" (str|None): Reflection text produced by the trajectory reflector, or None if reflection is disabled.
|
|
192
198
|
"""
|
|
199
|
+
# Check for cancellation before starting action generation
|
|
200
|
+
if self.global_state.is_cancelled():
|
|
201
|
+
logger.info("Worker action generation cancelled by user request")
|
|
202
|
+
return {
|
|
203
|
+
"current_subtask": subtask,
|
|
204
|
+
"current_subtask_info": subtask_info,
|
|
205
|
+
"executor_plan": "agent.done()",
|
|
206
|
+
"reflection": "Task was cancelled"
|
|
207
|
+
}
|
|
208
|
+
|
|
193
209
|
import time
|
|
194
210
|
action_start = time.time()
|
|
195
211
|
|