oagi-core 0.9.2__py3-none-any.whl → 0.10.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.
- oagi/__init__.py +76 -33
- oagi/agent/__init__.py +2 -0
- oagi/agent/default.py +41 -8
- oagi/agent/factories.py +22 -3
- oagi/agent/observer/__init__.py +38 -0
- oagi/agent/observer/agent_observer.py +99 -0
- oagi/agent/observer/events.py +28 -0
- oagi/agent/observer/exporters.py +445 -0
- oagi/agent/observer/protocol.py +12 -0
- oagi/agent/registry.py +2 -2
- oagi/agent/tasker/models.py +1 -0
- oagi/agent/tasker/planner.py +30 -7
- oagi/agent/tasker/taskee_agent.py +171 -79
- oagi/agent/tasker/tasker_agent.py +20 -9
- oagi/cli/agent.py +42 -3
- oagi/cli/tracking.py +27 -17
- oagi/handler/pyautogui_action_handler.py +7 -0
- oagi/server/agent_wrappers.py +5 -5
- oagi/server/models.py +1 -1
- oagi/server/session_store.py +2 -2
- oagi/task/async_.py +11 -32
- oagi/task/async_short.py +1 -1
- oagi/task/base.py +41 -7
- oagi/task/short.py +1 -1
- oagi/task/sync.py +9 -32
- oagi/types/__init__.py +24 -4
- oagi/types/async_image_provider.py +3 -2
- oagi/types/image_provider.py +3 -2
- oagi/types/step_observer.py +75 -16
- oagi/types/url.py +3 -0
- {oagi_core-0.9.2.dist-info → oagi_core-0.10.0.dist-info}/METADATA +37 -25
- oagi_core-0.10.0.dist-info/RECORD +68 -0
- oagi/types/url_image.py +0 -47
- oagi_core-0.9.2.dist-info/RECORD +0 -63
- {oagi_core-0.9.2.dist-info → oagi_core-0.10.0.dist-info}/WHEEL +0 -0
- {oagi_core-0.9.2.dist-info → oagi_core-0.10.0.dist-info}/entry_points.txt +0 -0
- {oagi_core-0.9.2.dist-info → oagi_core-0.10.0.dist-info}/licenses/LICENSE +0 -0
oagi/task/async_.py
CHANGED
|
@@ -9,14 +9,11 @@
|
|
|
9
9
|
import warnings
|
|
10
10
|
|
|
11
11
|
from ..client import AsyncClient
|
|
12
|
-
from ..
|
|
13
|
-
from
|
|
14
|
-
from .base import BaseTask
|
|
12
|
+
from ..types import URL, Image, Step
|
|
13
|
+
from .base import BaseActor
|
|
15
14
|
|
|
16
|
-
logger = get_logger("async_task")
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
class AsyncActor(BaseTask):
|
|
16
|
+
class AsyncActor(BaseActor):
|
|
20
17
|
"""Async base class for task automation with the OAGI API."""
|
|
21
18
|
|
|
22
19
|
def __init__(
|
|
@@ -34,19 +31,19 @@ class AsyncActor(BaseTask):
|
|
|
34
31
|
async def init_task(
|
|
35
32
|
self,
|
|
36
33
|
task_desc: str,
|
|
37
|
-
max_steps: int =
|
|
34
|
+
max_steps: int = 20,
|
|
38
35
|
):
|
|
39
36
|
"""Initialize a new task with the given description.
|
|
40
37
|
|
|
41
38
|
Args:
|
|
42
39
|
task_desc: Task description
|
|
43
|
-
max_steps: Maximum number of steps
|
|
40
|
+
max_steps: Maximum number of steps allowed
|
|
44
41
|
"""
|
|
45
42
|
self._prepare_init_task(task_desc, max_steps)
|
|
46
43
|
|
|
47
44
|
async def step(
|
|
48
45
|
self,
|
|
49
|
-
screenshot: Image | bytes,
|
|
46
|
+
screenshot: Image | URL | bytes,
|
|
50
47
|
instruction: str | None = None,
|
|
51
48
|
temperature: float | None = None,
|
|
52
49
|
) -> Step:
|
|
@@ -60,33 +57,15 @@ class AsyncActor(BaseTask):
|
|
|
60
57
|
Returns:
|
|
61
58
|
Step: The actions and reasoning for this step
|
|
62
59
|
"""
|
|
63
|
-
self.
|
|
64
|
-
|
|
60
|
+
kwargs = self._prepare_step(
|
|
61
|
+
screenshot, instruction, temperature, prefix="async "
|
|
62
|
+
)
|
|
65
63
|
|
|
66
64
|
try:
|
|
67
|
-
|
|
68
|
-
temp = self._get_temperature(temperature)
|
|
69
|
-
|
|
70
|
-
# Prepare screenshot kwargs (handles URLImage vs bytes/Image)
|
|
71
|
-
screenshot_kwargs = self._prepare_screenshot_kwargs(screenshot)
|
|
72
|
-
|
|
73
|
-
# Call API with dynamically determined screenshot argument
|
|
74
|
-
response = await self.client.create_message(
|
|
75
|
-
model=self.model,
|
|
76
|
-
task_description=self.task_description,
|
|
77
|
-
task_id=self.task_id,
|
|
78
|
-
instruction=instruction,
|
|
79
|
-
messages_history=self.message_history,
|
|
80
|
-
temperature=temp,
|
|
81
|
-
**screenshot_kwargs,
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
# Convert API response to Step (also updates message_history)
|
|
65
|
+
response = await self.client.create_message(**kwargs)
|
|
85
66
|
return self._build_step_response(response, prefix="Async ")
|
|
86
|
-
|
|
87
67
|
except Exception as e:
|
|
88
|
-
|
|
89
|
-
raise
|
|
68
|
+
self._handle_step_error(e, prefix="async ")
|
|
90
69
|
|
|
91
70
|
async def close(self):
|
|
92
71
|
"""Close the underlying HTTP client to free resources."""
|
oagi/task/async_short.py
CHANGED
|
@@ -43,7 +43,7 @@ class AsyncShortTask(AsyncActor, BaseAutoMode):
|
|
|
43
43
|
async def auto_mode(
|
|
44
44
|
self,
|
|
45
45
|
task_desc: str,
|
|
46
|
-
max_steps: int =
|
|
46
|
+
max_steps: int = 20,
|
|
47
47
|
executor: AsyncActionHandler = None,
|
|
48
48
|
image_provider: AsyncImageProvider = None,
|
|
49
49
|
temperature: float | None = None,
|
oagi/task/base.py
CHANGED
|
@@ -9,14 +9,14 @@
|
|
|
9
9
|
from uuid import uuid4
|
|
10
10
|
|
|
11
11
|
from ..logging import get_logger
|
|
12
|
-
from ..types import Image, Step
|
|
12
|
+
from ..types import URL, Image, Step
|
|
13
13
|
from ..types.models import LLMResponse
|
|
14
14
|
|
|
15
15
|
logger = get_logger("task.base")
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
class
|
|
19
|
-
"""Base class with shared task management logic for sync/async
|
|
18
|
+
class BaseActor:
|
|
19
|
+
"""Base class with shared task management logic for sync/async actors."""
|
|
20
20
|
|
|
21
21
|
def __init__(
|
|
22
22
|
self,
|
|
@@ -30,6 +30,8 @@ class BaseTask:
|
|
|
30
30
|
self.model = model
|
|
31
31
|
self.temperature = temperature
|
|
32
32
|
self.message_history: list = [] # OpenAI-compatible message history
|
|
33
|
+
self.max_steps: int = 20 # Maximum steps allowed
|
|
34
|
+
self.current_step: int = 0 # Current step counter
|
|
33
35
|
# Client will be set by subclasses
|
|
34
36
|
self.api_key: str | None = None
|
|
35
37
|
self.base_url: str | None = None
|
|
@@ -48,11 +50,43 @@ class BaseTask:
|
|
|
48
50
|
self.task_id = uuid4().hex
|
|
49
51
|
self.task_description = task_desc
|
|
50
52
|
self.message_history = []
|
|
53
|
+
self.max_steps = max_steps
|
|
54
|
+
self.current_step = 0
|
|
51
55
|
logger.info(f"Task initialized: '{task_desc}' (max_steps: {max_steps})")
|
|
52
56
|
|
|
53
|
-
def
|
|
57
|
+
def _validate_and_increment_step(self):
|
|
54
58
|
if not self.task_description:
|
|
55
59
|
raise ValueError("Task description must be set. Call init_task() first.")
|
|
60
|
+
if self.current_step >= self.max_steps:
|
|
61
|
+
raise ValueError(
|
|
62
|
+
f"Max steps limit ({self.max_steps}) reached. "
|
|
63
|
+
"Call init_task() to start a new task."
|
|
64
|
+
)
|
|
65
|
+
self.current_step += 1
|
|
66
|
+
|
|
67
|
+
def _prepare_step(
|
|
68
|
+
self,
|
|
69
|
+
screenshot: Image | URL | bytes,
|
|
70
|
+
instruction: str | None,
|
|
71
|
+
temperature: float | None,
|
|
72
|
+
prefix: str = "",
|
|
73
|
+
) -> dict:
|
|
74
|
+
self._validate_and_increment_step()
|
|
75
|
+
self._log_step_execution(prefix=prefix)
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
"model": self.model,
|
|
79
|
+
"task_description": self.task_description,
|
|
80
|
+
"task_id": self.task_id,
|
|
81
|
+
"instruction": instruction,
|
|
82
|
+
"messages_history": self.message_history,
|
|
83
|
+
"temperature": self._get_temperature(temperature),
|
|
84
|
+
**self._prepare_screenshot_kwargs(screenshot),
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
def _handle_step_error(self, error: Exception, prefix: str = ""):
|
|
88
|
+
logger.error(f"Error during {prefix}step execution: {error}")
|
|
89
|
+
raise
|
|
56
90
|
|
|
57
91
|
def _prepare_screenshot(self, screenshot: Image | bytes) -> bytes:
|
|
58
92
|
if isinstance(screenshot, Image):
|
|
@@ -62,9 +96,9 @@ class BaseTask:
|
|
|
62
96
|
def _get_temperature(self, temperature: float | None) -> float | None:
|
|
63
97
|
return temperature if temperature is not None else self.temperature
|
|
64
98
|
|
|
65
|
-
def _prepare_screenshot_kwargs(self, screenshot: Image | bytes) -> dict:
|
|
66
|
-
if isinstance(screenshot,
|
|
67
|
-
return {"screenshot_url": screenshot
|
|
99
|
+
def _prepare_screenshot_kwargs(self, screenshot: Image | URL | bytes) -> dict:
|
|
100
|
+
if isinstance(screenshot, str):
|
|
101
|
+
return {"screenshot_url": screenshot}
|
|
68
102
|
return {"screenshot": self._prepare_screenshot(screenshot)}
|
|
69
103
|
|
|
70
104
|
def _handle_response_message_history(self, response: LLMResponse):
|
oagi/task/short.py
CHANGED
oagi/task/sync.py
CHANGED
|
@@ -9,14 +9,11 @@
|
|
|
9
9
|
import warnings
|
|
10
10
|
|
|
11
11
|
from ..client import SyncClient
|
|
12
|
-
from ..
|
|
13
|
-
from
|
|
14
|
-
from .base import BaseTask
|
|
12
|
+
from ..types import URL, Image, Step
|
|
13
|
+
from .base import BaseActor
|
|
15
14
|
|
|
16
|
-
logger = get_logger("task")
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
class Actor(BaseTask):
|
|
16
|
+
class Actor(BaseActor):
|
|
20
17
|
"""Base class for task automation with the OAGI API."""
|
|
21
18
|
|
|
22
19
|
def __init__(
|
|
@@ -34,19 +31,19 @@ class Actor(BaseTask):
|
|
|
34
31
|
def init_task(
|
|
35
32
|
self,
|
|
36
33
|
task_desc: str,
|
|
37
|
-
max_steps: int =
|
|
34
|
+
max_steps: int = 20,
|
|
38
35
|
):
|
|
39
36
|
"""Initialize a new task with the given description.
|
|
40
37
|
|
|
41
38
|
Args:
|
|
42
39
|
task_desc: Task description
|
|
43
|
-
max_steps: Maximum number of steps
|
|
40
|
+
max_steps: Maximum number of steps allowed
|
|
44
41
|
"""
|
|
45
42
|
self._prepare_init_task(task_desc, max_steps)
|
|
46
43
|
|
|
47
44
|
def step(
|
|
48
45
|
self,
|
|
49
|
-
screenshot: Image | bytes,
|
|
46
|
+
screenshot: Image | URL | bytes,
|
|
50
47
|
instruction: str | None = None,
|
|
51
48
|
temperature: float | None = None,
|
|
52
49
|
) -> Step:
|
|
@@ -60,33 +57,13 @@ class Actor(BaseTask):
|
|
|
60
57
|
Returns:
|
|
61
58
|
Step: The actions and reasoning for this step
|
|
62
59
|
"""
|
|
63
|
-
self.
|
|
64
|
-
self._log_step_execution()
|
|
60
|
+
kwargs = self._prepare_step(screenshot, instruction, temperature)
|
|
65
61
|
|
|
66
62
|
try:
|
|
67
|
-
|
|
68
|
-
temp = self._get_temperature(temperature)
|
|
69
|
-
|
|
70
|
-
# Prepare screenshot kwargs (handles URLImage vs bytes/Image)
|
|
71
|
-
screenshot_kwargs = self._prepare_screenshot_kwargs(screenshot)
|
|
72
|
-
|
|
73
|
-
# Call API with dynamically determined screenshot argument
|
|
74
|
-
response = self.client.create_message(
|
|
75
|
-
model=self.model,
|
|
76
|
-
task_description=self.task_description,
|
|
77
|
-
task_id=self.task_id,
|
|
78
|
-
instruction=instruction,
|
|
79
|
-
messages_history=self.message_history,
|
|
80
|
-
temperature=temp,
|
|
81
|
-
**screenshot_kwargs,
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
# Convert API response to Step (also updates message_history)
|
|
63
|
+
response = self.client.create_message(**kwargs)
|
|
85
64
|
return self._build_step_response(response)
|
|
86
|
-
|
|
87
65
|
except Exception as e:
|
|
88
|
-
|
|
89
|
-
raise
|
|
66
|
+
self._handle_step_error(e)
|
|
90
67
|
|
|
91
68
|
def close(self):
|
|
92
69
|
"""Close the underlying HTTP client to free resources."""
|
oagi/types/__init__.py
CHANGED
|
@@ -12,19 +12,39 @@ from .async_image_provider import AsyncImageProvider
|
|
|
12
12
|
from .image import Image
|
|
13
13
|
from .image_provider import ImageProvider
|
|
14
14
|
from .models import Action, ActionType, ImageConfig, Step
|
|
15
|
-
from .step_observer import
|
|
16
|
-
|
|
15
|
+
from .step_observer import (
|
|
16
|
+
ActionEvent,
|
|
17
|
+
AsyncObserver,
|
|
18
|
+
AsyncStepObserver,
|
|
19
|
+
BaseEvent,
|
|
20
|
+
ImageEvent,
|
|
21
|
+
LogEvent,
|
|
22
|
+
ObserverEvent,
|
|
23
|
+
PlanEvent,
|
|
24
|
+
SplitEvent,
|
|
25
|
+
StepEvent,
|
|
26
|
+
)
|
|
27
|
+
from .url import URL
|
|
17
28
|
|
|
18
29
|
__all__ = [
|
|
19
30
|
"Action",
|
|
31
|
+
"ActionEvent",
|
|
20
32
|
"ActionType",
|
|
33
|
+
"AsyncObserver",
|
|
34
|
+
"AsyncStepObserver",
|
|
35
|
+
"BaseEvent",
|
|
21
36
|
"Image",
|
|
22
37
|
"ImageConfig",
|
|
38
|
+
"ImageEvent",
|
|
39
|
+
"LogEvent",
|
|
40
|
+
"ObserverEvent",
|
|
41
|
+
"PlanEvent",
|
|
42
|
+
"SplitEvent",
|
|
23
43
|
"Step",
|
|
44
|
+
"StepEvent",
|
|
24
45
|
"ActionHandler",
|
|
25
46
|
"AsyncActionHandler",
|
|
26
47
|
"ImageProvider",
|
|
27
48
|
"AsyncImageProvider",
|
|
28
|
-
"
|
|
29
|
-
"URLImage",
|
|
49
|
+
"URL",
|
|
30
50
|
]
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
from typing import Protocol
|
|
10
10
|
|
|
11
11
|
from .image import Image
|
|
12
|
+
from .url import URL
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class AsyncImageProvider(Protocol):
|
|
15
|
-
async def __call__(self) -> Image:
|
|
16
|
+
async def __call__(self) -> Image | URL:
|
|
16
17
|
"""
|
|
17
18
|
Asynchronously provides an image.
|
|
18
19
|
|
|
@@ -28,7 +29,7 @@ class AsyncImageProvider(Protocol):
|
|
|
28
29
|
RuntimeError: If an error occurs during image capture or generation.
|
|
29
30
|
"""
|
|
30
31
|
|
|
31
|
-
async def last_image(self) -> Image:
|
|
32
|
+
async def last_image(self) -> Image | URL:
|
|
32
33
|
"""
|
|
33
34
|
Asynchronously returns the last captured image.
|
|
34
35
|
|
oagi/types/image_provider.py
CHANGED
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
from typing import Protocol
|
|
10
10
|
|
|
11
11
|
from .image import Image
|
|
12
|
+
from .url import URL
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class ImageProvider(Protocol):
|
|
15
|
-
def __call__(self) -> Image:
|
|
16
|
+
def __call__(self) -> Image | URL:
|
|
16
17
|
"""
|
|
17
18
|
Represents the functionality to invoke the callable object and produce an Image
|
|
18
19
|
result. Typically used to process or generate images using the defined logic
|
|
@@ -22,7 +23,7 @@ class ImageProvider(Protocol):
|
|
|
22
23
|
Image: The resulting image output from the callable logic.
|
|
23
24
|
"""
|
|
24
25
|
|
|
25
|
-
def last_image(self) -> Image:
|
|
26
|
+
def last_image(self) -> Image | URL:
|
|
26
27
|
"""
|
|
27
28
|
Returns the last captured image.
|
|
28
29
|
|
oagi/types/step_observer.py
CHANGED
|
@@ -6,29 +6,88 @@
|
|
|
6
6
|
# Licensed under the MIT License.
|
|
7
7
|
# -----------------------------------------------------------------------------
|
|
8
8
|
|
|
9
|
-
from
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from typing import Literal, Protocol
|
|
10
11
|
|
|
11
|
-
from
|
|
12
|
+
from pydantic import BaseModel, Field
|
|
12
13
|
|
|
14
|
+
from .models import Action, Step
|
|
13
15
|
|
|
14
|
-
class AsyncStepObserver(Protocol):
|
|
15
|
-
"""Protocol for observing agent step execution.
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
class BaseEvent(BaseModel):
|
|
18
|
+
"""Base class for all observer events with automatic timestamp."""
|
|
19
|
+
|
|
20
|
+
timestamp: datetime = Field(default_factory=datetime.now)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ImageEvent(BaseEvent):
|
|
24
|
+
"""Event emitted when a screenshot is captured."""
|
|
25
|
+
|
|
26
|
+
type: Literal["image"] = "image"
|
|
27
|
+
step_num: int
|
|
28
|
+
image: bytes | str
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class StepEvent(BaseEvent):
|
|
32
|
+
"""Event emitted when LLM returns a step decision."""
|
|
33
|
+
|
|
34
|
+
type: Literal["step"] = "step"
|
|
35
|
+
step_num: int
|
|
36
|
+
image: bytes | str
|
|
37
|
+
step: Step
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ActionEvent(BaseEvent):
|
|
41
|
+
"""Event emitted after actions are executed."""
|
|
42
|
+
|
|
43
|
+
type: Literal["action"] = "action"
|
|
44
|
+
step_num: int
|
|
45
|
+
actions: list[Action]
|
|
46
|
+
error: str | None = None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class LogEvent(BaseEvent):
|
|
50
|
+
"""Event for custom log messages."""
|
|
51
|
+
|
|
52
|
+
type: Literal["log"] = "log"
|
|
53
|
+
message: str
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class SplitEvent(BaseEvent):
|
|
57
|
+
"""Event for visual separators in exported reports."""
|
|
58
|
+
|
|
59
|
+
type: Literal["split"] = "split"
|
|
60
|
+
label: str = ""
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class PlanEvent(BaseEvent):
|
|
64
|
+
"""Event emitted for planner activities (planning, reflection, summary)."""
|
|
65
|
+
|
|
66
|
+
type: Literal["plan"] = "plan"
|
|
67
|
+
phase: Literal["initial", "reflection", "summary"]
|
|
68
|
+
image: bytes | str | None = None
|
|
69
|
+
reasoning: str
|
|
70
|
+
result: str | None = None
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
ObserverEvent = ImageEvent | StepEvent | ActionEvent | LogEvent | SplitEvent | PlanEvent
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class AsyncObserver(Protocol):
|
|
77
|
+
"""Protocol for observing agent execution events.
|
|
78
|
+
|
|
79
|
+
Observers receive events during agent execution, enabling
|
|
80
|
+
recording, tracking, logging, or other side effects.
|
|
19
81
|
"""
|
|
20
82
|
|
|
21
|
-
async def
|
|
22
|
-
|
|
23
|
-
step_num: int,
|
|
24
|
-
reasoning: str | None,
|
|
25
|
-
actions: list[Action],
|
|
26
|
-
) -> None:
|
|
27
|
-
"""Called when an agent executes a step.
|
|
83
|
+
async def on_event(self, event: ObserverEvent) -> None:
|
|
84
|
+
"""Called when an agent execution event occurs.
|
|
28
85
|
|
|
29
86
|
Args:
|
|
30
|
-
|
|
31
|
-
reasoning: The reasoning/thinking for this step (if available)
|
|
32
|
-
actions: The list of actions being executed in this step
|
|
87
|
+
event: The event that occurred during agent execution.
|
|
33
88
|
"""
|
|
34
89
|
...
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# Deprecated: Use AsyncObserver instead
|
|
93
|
+
AsyncStepObserver = AsyncObserver
|
oagi/types/url.py
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: oagi-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: Official API of OpenAGI Foundation
|
|
5
5
|
Project-URL: Homepage, https://github.com/agiopen-org/oagi
|
|
6
6
|
Author-email: OpenAGI Foundation <contact@agiopen.org>
|
|
@@ -73,8 +73,8 @@ pip install oagi-core[server] # Server support
|
|
|
73
73
|
|
|
74
74
|
Set your API credentials:
|
|
75
75
|
```bash
|
|
76
|
-
export OAGI_API_KEY="your-api-key"
|
|
77
|
-
export OAGI_BASE_URL="https://api.
|
|
76
|
+
export OAGI_API_KEY="your-api-key" # get your API key from https://developer.openagi.org/
|
|
77
|
+
# export OAGI_BASE_URL="https://api.agiopen.org/", # optional, defaults to production endpoint
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
### Automated Task Execution
|
|
@@ -82,21 +82,25 @@ export OAGI_BASE_URL="https://api.oagi.com" # or your server URL
|
|
|
82
82
|
Run tasks automatically with screenshot capture and action execution:
|
|
83
83
|
|
|
84
84
|
```python
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
)
|
|
85
|
+
import asyncio
|
|
86
|
+
from oagi import AsyncDefaultAgent, AsyncPyautoguiActionHandler, AsyncScreenshotMaker
|
|
87
|
+
|
|
88
|
+
async def main():
|
|
89
|
+
agent = AsyncDefaultAgent(max_steps=10)
|
|
90
|
+
completed = await agent.execute(
|
|
91
|
+
"Search weather on Google",
|
|
92
|
+
action_handler=AsyncPyautoguiActionHandler(), # Executes mouse/keyboard actions
|
|
93
|
+
image_provider=AsyncScreenshotMaker(), # Captures screenshots
|
|
94
|
+
)
|
|
95
|
+
return completed
|
|
96
|
+
|
|
97
|
+
asyncio.run(main())
|
|
94
98
|
```
|
|
95
99
|
|
|
96
100
|
Configure PyAutoGUI behavior with custom settings:
|
|
97
101
|
|
|
98
102
|
```python
|
|
99
|
-
from oagi import
|
|
103
|
+
from oagi import AsyncPyautoguiActionHandler, PyautoguiConfig
|
|
100
104
|
|
|
101
105
|
# Customize action behavior
|
|
102
106
|
config = PyautoguiConfig(
|
|
@@ -108,8 +112,7 @@ config = PyautoguiConfig(
|
|
|
108
112
|
capslock_mode="session" # Caps lock mode: 'session' or 'system' (default: 'session')
|
|
109
113
|
)
|
|
110
114
|
|
|
111
|
-
|
|
112
|
-
task.auto_mode("Complete form", executor=executor, image_provider=ScreenshotMaker())
|
|
115
|
+
action_handler = AsyncPyautoguiActionHandler(config=config)
|
|
113
116
|
```
|
|
114
117
|
|
|
115
118
|
### Image Processing
|
|
@@ -130,20 +133,28 @@ config = ImageConfig(
|
|
|
130
133
|
compressed = image.transform(config)
|
|
131
134
|
```
|
|
132
135
|
|
|
133
|
-
###
|
|
136
|
+
### Manual Control with Actor
|
|
134
137
|
|
|
135
|
-
|
|
138
|
+
For step-by-step control over task execution:
|
|
136
139
|
|
|
137
140
|
```python
|
|
138
141
|
import asyncio
|
|
139
|
-
from oagi import
|
|
142
|
+
from oagi import AsyncActor, AsyncPyautoguiActionHandler, AsyncScreenshotMaker
|
|
140
143
|
|
|
141
144
|
async def main():
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
async with AsyncActor() as actor:
|
|
146
|
+
await actor.init_task("Complete the form")
|
|
147
|
+
image_provider = AsyncScreenshotMaker()
|
|
148
|
+
action_handler = AsyncPyautoguiActionHandler()
|
|
149
|
+
|
|
150
|
+
for _ in range(10):
|
|
151
|
+
image = await image_provider()
|
|
152
|
+
step = await actor.step(image)
|
|
153
|
+
|
|
154
|
+
if step.stop:
|
|
155
|
+
break
|
|
156
|
+
|
|
157
|
+
await action_handler(step.actions)
|
|
147
158
|
|
|
148
159
|
asyncio.run(main())
|
|
149
160
|
```
|
|
@@ -151,9 +162,10 @@ asyncio.run(main())
|
|
|
151
162
|
## Examples
|
|
152
163
|
|
|
153
164
|
See the [`examples/`](examples/) directory for more usage patterns:
|
|
154
|
-
- `
|
|
165
|
+
- `execute_task_auto.py` - Automated task execution with `AsyncDefaultAgent`
|
|
166
|
+
- `execute_task_manual.py` - Manual step-by-step control with `Actor`
|
|
167
|
+
- `continued_session.py` - Continuing tasks across sessions
|
|
155
168
|
- `screenshot_with_config.py` - Image compression and optimization
|
|
156
|
-
- `execute_task_auto.py` - Automated task execution
|
|
157
169
|
- `socketio_server_basic.py` - Socket.IO server example
|
|
158
170
|
- `socketio_client_example.py` - Socket.IO client implementation
|
|
159
171
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
oagi/__init__.py,sha256=xI--F3inDKuNQ2caI4Xx0rdFuUxO24cEeAX6WoGi170,4836
|
|
2
|
+
oagi/exceptions.py,sha256=Rco37GQTPYUfc2vRO3hozxPF_s8mKFDpFvBg2UKWo3Y,3066
|
|
3
|
+
oagi/logging.py,sha256=YT3KCMFj5fzO98R9xlDDgfSotUuz1xRD6OZeYM2rKoo,1760
|
|
4
|
+
oagi/agent/__init__.py,sha256=KTVLUMhbjgpTJoOWMUZkkiqwhgumvbOZV2tJ9XCLfao,901
|
|
5
|
+
oagi/agent/default.py,sha256=VaDiYISM0Y3l_xhSvWcIZQDiUj_ebHg9tgWLnr-OWuY,4116
|
|
6
|
+
oagi/agent/factories.py,sha256=WP4ONu9JBDaJYmK18OuFihAX7YKCeOKgOh981lYguXo,2113
|
|
7
|
+
oagi/agent/protocol.py,sha256=IQJGiMN4yZIacrh5e9JQsoM9TyHb8wJRQR4LAk8dSA0,1615
|
|
8
|
+
oagi/agent/registry.py,sha256=7bMA2-pH3xQ9ZavrHB_mnc2fOGSMeICPbOGtHoM7It0,4851
|
|
9
|
+
oagi/agent/observer/__init__.py,sha256=YZ4qvR22pFB0mSDMX6iKKLbBA1dB-nqC7HZVvdMIVGw,909
|
|
10
|
+
oagi/agent/observer/agent_observer.py,sha256=fBs4X2_YKhYVThJocjMM-65JAHQSCLJPvzy8OXMt5pY,2864
|
|
11
|
+
oagi/agent/observer/events.py,sha256=xc3Z1UGpX69BqhO9cQiGmnRhDZbMYya1kuXm6bXtjWI,625
|
|
12
|
+
oagi/agent/observer/exporters.py,sha256=im1aK8UkGfWbRnVIYdsoCKVX_JYrcEvzRMDD2CK3gcM,15245
|
|
13
|
+
oagi/agent/observer/protocol.py,sha256=jyRXoCG4CdvaPaDASar1rSbwc7vdpkar39KkGpwf8jw,411
|
|
14
|
+
oagi/agent/tasker/__init__.py,sha256=faOC5ONY8ZKr4CjofC6HYg1WKWc1UiaGB9VHy8W280M,800
|
|
15
|
+
oagi/agent/tasker/memory.py,sha256=JsJjUMpnJoKW4VFzd8FI4M-FhnEihTecL61KVgO_YBI,6051
|
|
16
|
+
oagi/agent/tasker/models.py,sha256=eQ6BrRS9v5ZSmgyK8Ji5iXEyB3OvSIKBvB8Ge1FoGdY,2266
|
|
17
|
+
oagi/agent/tasker/planner.py,sha256=XbaL_O5ENKzeOijqEfRqeO6fzzYMmwfjQQlOTxCoK_Y,14810
|
|
18
|
+
oagi/agent/tasker/taskee_agent.py,sha256=b2oHkHrZak3S5gMVffjht7ra8et8xDAADoDlfZFy_os,16731
|
|
19
|
+
oagi/agent/tasker/tasker_agent.py,sha256=2DM3XEPNTd-SJjW9nNXJHoDCM735Uz_Ya1hr-O87mX8,11303
|
|
20
|
+
oagi/cli/__init__.py,sha256=aDnJViTseShpo5fdGPTj-ELysZhmdvB6Z8mEj2D-_N4,359
|
|
21
|
+
oagi/cli/agent.py,sha256=daHCF06rMp-hIOd6AUT1YOtEGu2yhOZb-uDKJu_WrUU,5933
|
|
22
|
+
oagi/cli/display.py,sha256=rkAxuHa40ZtKdmvwARev1rgyfsNyVvQ-J6RdjOZIPwc,1729
|
|
23
|
+
oagi/cli/main.py,sha256=faHns0HaQCGyylDn2YZLpjQESuEiMYjoQVoMkt8FsH4,2292
|
|
24
|
+
oagi/cli/server.py,sha256=Z1ic8r55yaeQBFRCsMNZStC1jRiJdnDGqe9On9LmFzQ,3031
|
|
25
|
+
oagi/cli/tracking.py,sha256=TdrAcNq_-OjgXltFCoFc8NsO_k6yHbdzHnMn3vAAvKA,1707
|
|
26
|
+
oagi/cli/utils.py,sha256=BI6C7WvC51NBsXEsjDONjSNwqdD4i0nHA_rsfpyLwmA,2986
|
|
27
|
+
oagi/client/__init__.py,sha256=F9DShPUdb6vZYmN1fpM1VYzp4MWqUao_e_R1KYmM4Q4,410
|
|
28
|
+
oagi/client/async_.py,sha256=t-GPHcz6xbHx_RPFv1V_hwZ1_f-O9ONH-Ahr0w-Nz8M,11046
|
|
29
|
+
oagi/client/base.py,sha256=4ZfhouEyIcldStJG5ipxpxpD6iVRGrMUZruQX0WKiXE,16934
|
|
30
|
+
oagi/client/sync.py,sha256=QKd6nTUXtyn1Am8YlFcpsoLh1KuHhQgbMemIkb7r39g,10882
|
|
31
|
+
oagi/handler/__init__.py,sha256=Ha11L42K33K3L9S4lQ10UC0DnD5g6egtQUsJpS_tKgg,835
|
|
32
|
+
oagi/handler/_macos.py,sha256=aHkp-xGzvWL_SBjuS690i9jf93OITFJfGHzHeYCK65I,1957
|
|
33
|
+
oagi/handler/async_pyautogui_action_handler.py,sha256=hQzseR1yBD0QMpgsEVNsUmuApGVAIIyGYD06BXd82Dc,1615
|
|
34
|
+
oagi/handler/async_screenshot_maker.py,sha256=8QCtUV59ozpOpvkqhUMb8QDI2qje2gsoFT1qB60tfJM,1689
|
|
35
|
+
oagi/handler/pil_image.py,sha256=yUcAoGBL-aZ0PCjSaAmQsDwtyzjldXHqXQp_OYRk6e4,4080
|
|
36
|
+
oagi/handler/pyautogui_action_handler.py,sha256=VOD1CwdFHUQsk8nDIZUetdWZTH8Ig3xgKR5ljzaKSJ8,10592
|
|
37
|
+
oagi/handler/screenshot_maker.py,sha256=j1jTW-awx3vAnb1N5_FIMBC0Z-rNVQbiBP-S6Gh5dlE,1284
|
|
38
|
+
oagi/server/__init__.py,sha256=uZx8u3vJUb87kkNzwmmVrgAgbqRu0WxyMIQCLSx56kk,452
|
|
39
|
+
oagi/server/agent_wrappers.py,sha256=j8va0A7u80bzOM82nndAplK1uaO_T3kufHWScK6kfWM,3263
|
|
40
|
+
oagi/server/config.py,sha256=2gJ-pDpYAxNUubwSsGKOieGcOtNX9b5YGuSqtf6g2P0,1607
|
|
41
|
+
oagi/server/main.py,sha256=jnTxk7Prc5CzlsUnkBNJp4MOoYN-7HN_Be_m1d3COa8,4829
|
|
42
|
+
oagi/server/models.py,sha256=7zsmjvnIZ0JUcCpE8F2A1OqX4_kGJydraRkbvPHnvn8,2593
|
|
43
|
+
oagi/server/session_store.py,sha256=922Sz00_Ao-9fA0dhA1lrzs7yd6wo7xpdYJH4hZmEaI,3634
|
|
44
|
+
oagi/server/socketio_server.py,sha256=NFw5Zu7yCFLW-gOu9OX8k6mNFaCN2jtX1Tob_9w5YM0,14344
|
|
45
|
+
oagi/task/__init__.py,sha256=g_8_7ZLDLKuCGzyrB42OzY3gSOjd_SxzkJW3_pf-PXs,662
|
|
46
|
+
oagi/task/async_.py,sha256=ev1jnuOQIYahjjMlSCFwtaeyOliePZCpEVt3ocsZXAI,3124
|
|
47
|
+
oagi/task/async_short.py,sha256=VMIBKcTQMjadWXPHiJXWlYZqr5v4MeGVYnuKOs7dS3Y,2752
|
|
48
|
+
oagi/task/base.py,sha256=D4e4N1cWoObMzaGcXyXGBPKyNbzmxABIjxbHiVrK548,5664
|
|
49
|
+
oagi/task/short.py,sha256=xSR5_9BX35UMfITXtCgKXRLU92f4vnqa06c-HSjUO0A,2561
|
|
50
|
+
oagi/task/sync.py,sha256=ciDkQYJQZkQyp8buNIKXU9Oy6kD7WIezCh2L0trLDDc,2958
|
|
51
|
+
oagi/types/__init__.py,sha256=TCdHA8zPJAzpo-jgkfcWTWmbrWglOpShGQFcLoxV_xw,1187
|
|
52
|
+
oagi/types/action_handler.py,sha256=NH8E-m5qpGqWcXzTSWfF7W0Xdp8SkzJsbhCmQ0B96cg,1075
|
|
53
|
+
oagi/types/async_action_handler.py,sha256=k1AaqSkFcXlxwW8sn-w0WFHGsIqHFLbcOPrkknmSVug,1116
|
|
54
|
+
oagi/types/async_image_provider.py,sha256=UwDl7VOCA3tiSP5k1fnxK86iEa84Yr57MVaoBSa3hOE,1203
|
|
55
|
+
oagi/types/image.py,sha256=KgPCCTJ6D5vHIaGZdbTE7eQEa1WlT6G9tf59ZuUCV2U,537
|
|
56
|
+
oagi/types/image_provider.py,sha256=IhKEnwCGZ5l_rO3AvJ6xv5RZMTmTDmqsFRynI9h0R_M,1145
|
|
57
|
+
oagi/types/step_observer.py,sha256=wXuChzsof7Rh4azvDTIQ22gAwZAYjMAOVIuL8ZGtw-M,2315
|
|
58
|
+
oagi/types/url.py,sha256=Q-1jf5L_4rad4dxyLTg4MXadGgpkH3w4dcoVrVupW-A,54
|
|
59
|
+
oagi/types/models/__init__.py,sha256=I86Z2moM8hCog_1K1FG_uATcBmWFv_UFetLAjzPzWAY,742
|
|
60
|
+
oagi/types/models/action.py,sha256=hh6mRRSSWgrW4jpZo71zGMCOcZpV5_COu4148uG6G48,967
|
|
61
|
+
oagi/types/models/client.py,sha256=fCN18DBq5XDjNyYB8w-2dFeQ_K9ywwdyh-rXa0GToU4,1357
|
|
62
|
+
oagi/types/models/image_config.py,sha256=tl6abVg_-IAPLwpaWprgknXu7wRWriMg-AEVyUX73v0,1567
|
|
63
|
+
oagi/types/models/step.py,sha256=RSI4H_2rrUBq_xyCoWKaq7JHdJWNobtQppaKC1l0aWU,471
|
|
64
|
+
oagi_core-0.10.0.dist-info/METADATA,sha256=7eAQXcjWgxixmcwQkherH_ytEoV6Jy3RwYQJWsfopcQ,8161
|
|
65
|
+
oagi_core-0.10.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
|
66
|
+
oagi_core-0.10.0.dist-info/entry_points.txt,sha256=zzgsOSWX6aN3KUB0Z1it8DMxFFBJBqmZVqMVAJRjYuw,44
|
|
67
|
+
oagi_core-0.10.0.dist-info/licenses/LICENSE,sha256=sy5DLA2M29jFT4UfWsuBF9BAr3FnRkYtnAu6oDZiIf8,1075
|
|
68
|
+
oagi_core-0.10.0.dist-info/RECORD,,
|