oagi-core 0.9.0__tar.gz → 0.9.1__tar.gz
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_core-0.9.0 → oagi_core-0.9.1}/Makefile +2 -1
- {oagi_core-0.9.0 → oagi_core-0.9.1}/PKG-INFO +3 -29
- {oagi_core-0.9.0 → oagi_core-0.9.1}/README.md +1 -28
- {oagi_core-0.9.0 → oagi_core-0.9.1}/examples/execute_task_manual.py +12 -12
- {oagi_core-0.9.0 → oagi_core-0.9.1}/examples/screenshot_with_config.py +3 -27
- {oagi_core-0.9.0 → oagi_core-0.9.1}/metapackage/pyproject.toml +2 -2
- {oagi_core-0.9.0 → oagi_core-0.9.1}/pyproject.toml +2 -1
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/__init__.py +13 -16
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/agent/default.py +23 -7
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/agent/factories.py +5 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/agent/tasker/taskee_agent.py +40 -15
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/agent/tasker/tasker_agent.py +5 -1
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/cli/agent.py +31 -15
- oagi_core-0.9.1/src/oagi/cli/display.py +56 -0
- oagi_core-0.9.1/src/oagi/cli/tracking.py +45 -0
- oagi_core-0.9.1/src/oagi/handler/__init__.py +24 -0
- {oagi_core-0.9.0/src/oagi → oagi_core-0.9.1/src/oagi/handler}/async_pyautogui_action_handler.py +1 -1
- {oagi_core-0.9.0/src/oagi → oagi_core-0.9.1/src/oagi/handler}/async_screenshot_maker.py +1 -1
- {oagi_core-0.9.0/src/oagi → oagi_core-0.9.1/src/oagi/handler}/pil_image.py +2 -2
- {oagi_core-0.9.0/src/oagi → oagi_core-0.9.1/src/oagi/handler}/pyautogui_action_handler.py +2 -2
- {oagi_core-0.9.0/src/oagi → oagi_core-0.9.1/src/oagi/handler}/screenshot_maker.py +2 -2
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/logging.py +8 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/task/__init__.py +10 -3
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/task/async_.py +26 -1
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/task/async_short.py +15 -3
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/task/base.py +2 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/task/short.py +15 -3
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/task/sync.py +26 -1
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/__init__.py +2 -0
- oagi_core-0.9.1/src/oagi/types/step_observer.py +34 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_agent/test_default_agent.py +19 -13
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_async_handlers.py +3 -3
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_async_task.py +47 -45
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_cli.py +4 -2
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_pil_image.py +3 -3
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_pyautogui_action_handler.py +2 -2
- oagi_core-0.9.1/tests/test_task.py +427 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_taskee_agent.py +18 -16
- {oagi_core-0.9.0 → oagi_core-0.9.1}/uv.lock +3 -1
- oagi_core-0.9.0/examples/single_step.py +0 -19
- oagi_core-0.9.0/src/oagi/async_single_step.py +0 -85
- oagi_core-0.9.0/src/oagi/single_step.py +0 -87
- oagi_core-0.9.0/tests/test_single_step.py +0 -216
- oagi_core-0.9.0/tests/test_task.py +0 -423
- {oagi_core-0.9.0 → oagi_core-0.9.1}/.github/workflows/ci.yml +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/.github/workflows/release.yml +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/.gitignore +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/.python-version +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/CONTRIBUTING.md +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/LICENSE +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/examples/async_google_weather.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/examples/continued_session.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/examples/execute_task_auto.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/examples/google_weather.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/examples/hotel_booking.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/agent/__init__.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/agent/protocol.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/agent/registry.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/agent/tasker/__init__.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/agent/tasker/memory.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/agent/tasker/models.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/agent/tasker/planner.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/cli/__init__.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/cli/main.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/cli/server.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/cli/utils.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/client/__init__.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/client/async_.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/client/base.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/client/sync.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/exceptions.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/server/__init__.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/server/agent_wrappers.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/server/config.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/server/main.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/server/models.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/server/session_store.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/server/socketio_server.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/action_handler.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/async_action_handler.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/async_image_provider.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/image.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/image_provider.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/models/__init__.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/models/action.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/models/client.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/models/image_config.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/models/step.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/src/oagi/types/url_image.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/__init__.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/conftest.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_agent/test_agent_wrappers.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_agent_registry.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_async_client.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_logging.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_planner.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_planner_memory.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_screenshot_maker.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_server/__init__.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_server/test_config.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_server/test_session_store.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_server/test_socketio_integration.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_short_task.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_sync_client.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_tasker_agent.py +0 -0
- {oagi_core-0.9.0 → oagi_core-0.9.1}/tests/test_url_image.py +0 -0
|
@@ -54,4 +54,5 @@ version:
|
|
|
54
54
|
@echo "Updating version to $(VERSION) in all files..."
|
|
55
55
|
@sed -i '' 's/^version = ".*"/version = "$(VERSION)"/' pyproject.toml
|
|
56
56
|
@sed -i '' 's/^version = ".*"/version = "$(VERSION)"/' metapackage/pyproject.toml
|
|
57
|
-
@sed -i '' 's/oagi-core\[desktop,server\]==.*/oagi-core[desktop,server]==$(VERSION)",/' metapackage/pyproject.toml
|
|
57
|
+
@sed -i '' 's/oagi-core\[desktop,server\]==.*/oagi-core[desktop,server]==$(VERSION)",/' metapackage/pyproject.toml
|
|
58
|
+
make build-all
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: oagi-core
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.1
|
|
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>
|
|
@@ -28,6 +28,7 @@ License: MIT License
|
|
|
28
28
|
Requires-Python: >=3.10
|
|
29
29
|
Requires-Dist: httpx>=0.28.0
|
|
30
30
|
Requires-Dist: pydantic>=2.0.0
|
|
31
|
+
Requires-Dist: rich>=13.0.0
|
|
31
32
|
Provides-Extra: desktop
|
|
32
33
|
Requires-Dist: pillow>=11.3.0; extra == 'desktop'
|
|
33
34
|
Requires-Dist: pyautogui>=0.9.54; extra == 'desktop'
|
|
@@ -75,22 +76,6 @@ export OAGI_API_KEY="your-api-key"
|
|
|
75
76
|
export OAGI_BASE_URL="https://api.oagi.com" # or your server URL
|
|
76
77
|
```
|
|
77
78
|
|
|
78
|
-
### Single-Step Analysis
|
|
79
|
-
|
|
80
|
-
Analyze a screenshot and get recommended actions:
|
|
81
|
-
|
|
82
|
-
```python
|
|
83
|
-
from oagi import single_step
|
|
84
|
-
|
|
85
|
-
step = single_step(
|
|
86
|
-
task_description="Click the submit button",
|
|
87
|
-
screenshot="screenshot.png" # or bytes, or Image object
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
print(f"Actions: {step.actions}")
|
|
91
|
-
print(f"Complete: {step.is_complete}")
|
|
92
|
-
```
|
|
93
|
-
|
|
94
79
|
### Automated Task Execution
|
|
95
80
|
|
|
96
81
|
Run tasks automatically with screenshot capture and action execution:
|
|
@@ -142,9 +127,6 @@ config = ImageConfig(
|
|
|
142
127
|
height=700
|
|
143
128
|
)
|
|
144
129
|
compressed = image.transform(config)
|
|
145
|
-
|
|
146
|
-
# Use with single_step
|
|
147
|
-
step = single_step("Click button", screenshot=compressed)
|
|
148
130
|
```
|
|
149
131
|
|
|
150
132
|
### Async Support
|
|
@@ -153,16 +135,9 @@ Use async client for non-blocking operations and better concurrency:
|
|
|
153
135
|
|
|
154
136
|
```python
|
|
155
137
|
import asyncio
|
|
156
|
-
from oagi import
|
|
138
|
+
from oagi import AsyncShortTask
|
|
157
139
|
|
|
158
140
|
async def main():
|
|
159
|
-
# Single-step async analysis
|
|
160
|
-
step = await async_single_step(
|
|
161
|
-
"Find the search bar",
|
|
162
|
-
screenshot="screenshot.png"
|
|
163
|
-
)
|
|
164
|
-
print(f"Found {len(step.actions)} actions")
|
|
165
|
-
|
|
166
141
|
# Async task automation
|
|
167
142
|
task = AsyncShortTask()
|
|
168
143
|
async with task:
|
|
@@ -176,7 +151,6 @@ asyncio.run(main())
|
|
|
176
151
|
|
|
177
152
|
See the [`examples/`](examples/) directory for more usage patterns:
|
|
178
153
|
- `google_weather.py` - Basic task execution with `ShortTask`
|
|
179
|
-
- `single_step.py` - Basic single-step inference
|
|
180
154
|
- `screenshot_with_config.py` - Image compression and optimization
|
|
181
155
|
- `execute_task_auto.py` - Automated task execution
|
|
182
156
|
- `socketio_server_basic.py` - Socket.IO server example
|
|
@@ -35,22 +35,6 @@ export OAGI_API_KEY="your-api-key"
|
|
|
35
35
|
export OAGI_BASE_URL="https://api.oagi.com" # or your server URL
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
### Single-Step Analysis
|
|
39
|
-
|
|
40
|
-
Analyze a screenshot and get recommended actions:
|
|
41
|
-
|
|
42
|
-
```python
|
|
43
|
-
from oagi import single_step
|
|
44
|
-
|
|
45
|
-
step = single_step(
|
|
46
|
-
task_description="Click the submit button",
|
|
47
|
-
screenshot="screenshot.png" # or bytes, or Image object
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
print(f"Actions: {step.actions}")
|
|
51
|
-
print(f"Complete: {step.is_complete}")
|
|
52
|
-
```
|
|
53
|
-
|
|
54
38
|
### Automated Task Execution
|
|
55
39
|
|
|
56
40
|
Run tasks automatically with screenshot capture and action execution:
|
|
@@ -102,9 +86,6 @@ config = ImageConfig(
|
|
|
102
86
|
height=700
|
|
103
87
|
)
|
|
104
88
|
compressed = image.transform(config)
|
|
105
|
-
|
|
106
|
-
# Use with single_step
|
|
107
|
-
step = single_step("Click button", screenshot=compressed)
|
|
108
89
|
```
|
|
109
90
|
|
|
110
91
|
### Async Support
|
|
@@ -113,16 +94,9 @@ Use async client for non-blocking operations and better concurrency:
|
|
|
113
94
|
|
|
114
95
|
```python
|
|
115
96
|
import asyncio
|
|
116
|
-
from oagi import
|
|
97
|
+
from oagi import AsyncShortTask
|
|
117
98
|
|
|
118
99
|
async def main():
|
|
119
|
-
# Single-step async analysis
|
|
120
|
-
step = await async_single_step(
|
|
121
|
-
"Find the search bar",
|
|
122
|
-
screenshot="screenshot.png"
|
|
123
|
-
)
|
|
124
|
-
print(f"Found {len(step.actions)} actions")
|
|
125
|
-
|
|
126
100
|
# Async task automation
|
|
127
101
|
task = AsyncShortTask()
|
|
128
102
|
async with task:
|
|
@@ -136,7 +110,6 @@ asyncio.run(main())
|
|
|
136
110
|
|
|
137
111
|
See the [`examples/`](examples/) directory for more usage patterns:
|
|
138
112
|
- `google_weather.py` - Basic task execution with `ShortTask`
|
|
139
|
-
- `single_step.py` - Basic single-step inference
|
|
140
113
|
- `screenshot_with_config.py` - Image compression and optimization
|
|
141
114
|
- `execute_task_auto.py` - Automated task execution
|
|
142
115
|
- `socketio_server_basic.py` - Socket.IO server example
|
|
@@ -7,20 +7,20 @@
|
|
|
7
7
|
# -----------------------------------------------------------------------------
|
|
8
8
|
|
|
9
9
|
from oagi import (
|
|
10
|
+
Actor,
|
|
11
|
+
AsyncActor,
|
|
10
12
|
AsyncPyautoguiActionHandler,
|
|
11
13
|
AsyncScreenshotMaker,
|
|
12
|
-
AsyncTask,
|
|
13
14
|
PyautoguiActionHandler,
|
|
14
15
|
ScreenshotMaker,
|
|
15
|
-
Task,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def execute_task_manual(task_desc, max_steps=5):
|
|
20
20
|
# set OAGI_API_KEY and OAGI_BASE_URL
|
|
21
|
-
# or
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
# or Actor(api_key="your_api_key", base_url="your_base_url")
|
|
22
|
+
actor = Actor()
|
|
23
|
+
actor.init_task(task_desc, max_steps=max_steps)
|
|
24
24
|
executor = (
|
|
25
25
|
PyautoguiActionHandler()
|
|
26
26
|
) # executor = lambda actions: print(actions) for debugging
|
|
@@ -36,8 +36,8 @@ def execute_task_manual(task_desc, max_steps=5):
|
|
|
36
36
|
image = image_provider()
|
|
37
37
|
|
|
38
38
|
# For additional instructions
|
|
39
|
-
# step =
|
|
40
|
-
step =
|
|
39
|
+
# step = actor.step(image, instruction="some instruction")
|
|
40
|
+
step = actor.step(image)
|
|
41
41
|
|
|
42
42
|
# do something with step, maybe print to debug
|
|
43
43
|
print(f"Step {i}: {step.reason=}")
|
|
@@ -60,9 +60,9 @@ def execute_task_manual(task_desc, max_steps=5):
|
|
|
60
60
|
|
|
61
61
|
async def async_execute_task_manual(task_desc, max_steps=5):
|
|
62
62
|
# set OAGI_API_KEY and OAGI_BASE_URL
|
|
63
|
-
# or
|
|
64
|
-
async with
|
|
65
|
-
await
|
|
63
|
+
# or AsyncActor(api_key="your_api_key", base_url="your_base_url")
|
|
64
|
+
async with AsyncActor() as actor:
|
|
65
|
+
await actor.init_task(task_desc, max_steps=max_steps)
|
|
66
66
|
executor = AsyncPyautoguiActionHandler()
|
|
67
67
|
|
|
68
68
|
# by default, screenshot will be resized to 1260 * 700 and jpeg with quality 85
|
|
@@ -76,8 +76,8 @@ async def async_execute_task_manual(task_desc, max_steps=5):
|
|
|
76
76
|
image = await image_provider()
|
|
77
77
|
|
|
78
78
|
# For additional instructions
|
|
79
|
-
# step =
|
|
80
|
-
step = await
|
|
79
|
+
# step = actor.step(image, instruction="some instruction")
|
|
80
|
+
step = await actor.step(image)
|
|
81
81
|
|
|
82
82
|
# do something with step, maybe print to debug
|
|
83
83
|
print(f"Step {i}: {step.reason=}")
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Licensed under the MIT License.
|
|
7
7
|
# -----------------------------------------------------------------------------
|
|
8
8
|
|
|
9
|
-
from oagi import ImageConfig, PILImage, ScreenshotMaker
|
|
9
|
+
from oagi import ImageConfig, PILImage, ScreenshotMaker
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def example_full_png_screenshot():
|
|
@@ -53,33 +53,9 @@ def example_load_and_compress(file_name):
|
|
|
53
53
|
return compressed_image
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
def example_with_single_step(file_name):
|
|
57
|
-
"""Example 3: Use compressed image with single_step."""
|
|
58
|
-
print("\nExample 3: Use with single_step")
|
|
59
|
-
|
|
60
|
-
# Load and compress image
|
|
61
|
-
image = PILImage.from_file(file_name)
|
|
62
|
-
print(f"Original image dimensions: {image.image.size}")
|
|
63
|
-
|
|
64
|
-
config = ImageConfig(format="JPEG", quality=85, width=1260, height=700)
|
|
65
|
-
compressed = image.transform(config)
|
|
66
|
-
print(f"Compressed image dimensions: {compressed.image.size}")
|
|
67
|
-
|
|
68
|
-
# Use with single_step
|
|
69
|
-
step = single_step(
|
|
70
|
-
task_description="Click the submit button",
|
|
71
|
-
screenshot=compressed,
|
|
72
|
-
api_key="your-api-key-here",
|
|
73
|
-
base_url="http://127.0.0.1:8000",
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
print(f"Task complete: {step.is_complete}")
|
|
77
|
-
return step
|
|
78
|
-
|
|
79
|
-
|
|
80
56
|
def example_default_config():
|
|
81
|
-
"""Example
|
|
82
|
-
print("\nExample
|
|
57
|
+
"""Example 3: Default configuration (1260x700 JPEG with 85 quality)."""
|
|
58
|
+
print("\nExample 3: Default configuration")
|
|
83
59
|
|
|
84
60
|
default_maker = ScreenshotMaker() # Uses default ImageConfig
|
|
85
61
|
default_screenshot = default_maker()
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "oagi"
|
|
7
|
-
version = "0.9.
|
|
7
|
+
version = "0.9.1"
|
|
8
8
|
description = "Official API of OpenAGI Foundation (metapackage with all features)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -16,7 +16,7 @@ authors = [
|
|
|
16
16
|
requires-python = ">= 3.10"
|
|
17
17
|
|
|
18
18
|
dependencies = [
|
|
19
|
-
"oagi-core[desktop,server]==0.9.
|
|
19
|
+
"oagi-core[desktop,server]==0.9.1",
|
|
20
20
|
]
|
|
21
21
|
|
|
22
22
|
[project.urls]
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "oagi-core"
|
|
7
|
-
version = "0.9.
|
|
7
|
+
version = "0.9.1"
|
|
8
8
|
description = "Official API of OpenAGI Foundation"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -17,6 +17,7 @@ requires-python = ">= 3.10"
|
|
|
17
17
|
dependencies = [
|
|
18
18
|
"httpx>=0.28.0",
|
|
19
19
|
"pydantic>=2.0.0",
|
|
20
|
+
"rich>=13.0.0",
|
|
20
21
|
]
|
|
21
22
|
|
|
22
23
|
[project.urls]
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
# -----------------------------------------------------------------------------
|
|
8
8
|
import importlib
|
|
9
9
|
|
|
10
|
-
from oagi.async_single_step import async_single_step
|
|
11
10
|
from oagi.client import AsyncClient, SyncClient
|
|
12
11
|
from oagi.exceptions import (
|
|
13
12
|
APIError,
|
|
@@ -21,8 +20,7 @@ from oagi.exceptions import (
|
|
|
21
20
|
ServerError,
|
|
22
21
|
ValidationError,
|
|
23
22
|
)
|
|
24
|
-
from oagi.
|
|
25
|
-
from oagi.task import AsyncShortTask, AsyncTask, ShortTask, Task
|
|
23
|
+
from oagi.task import Actor, AsyncActor, AsyncShortTask, AsyncTask, ShortTask, Task
|
|
26
24
|
from oagi.types import (
|
|
27
25
|
AsyncActionHandler,
|
|
28
26
|
AsyncImageProvider,
|
|
@@ -33,12 +31,12 @@ from oagi.types.models import ErrorDetail, ErrorResponse, LLMResponse
|
|
|
33
31
|
# Lazy imports for pyautogui-dependent modules
|
|
34
32
|
# These will only be imported when actually accessed
|
|
35
33
|
_LAZY_IMPORTS = {
|
|
36
|
-
"AsyncPyautoguiActionHandler": "oagi.async_pyautogui_action_handler",
|
|
37
|
-
"AsyncScreenshotMaker": "oagi.async_screenshot_maker",
|
|
38
|
-
"PILImage": "oagi.pil_image",
|
|
39
|
-
"PyautoguiActionHandler": "oagi.pyautogui_action_handler",
|
|
40
|
-
"PyautoguiConfig": "oagi.pyautogui_action_handler",
|
|
41
|
-
"ScreenshotMaker": "oagi.screenshot_maker",
|
|
34
|
+
"AsyncPyautoguiActionHandler": "oagi.handler.async_pyautogui_action_handler",
|
|
35
|
+
"AsyncScreenshotMaker": "oagi.handler.async_screenshot_maker",
|
|
36
|
+
"PILImage": "oagi.handler.pil_image",
|
|
37
|
+
"PyautoguiActionHandler": "oagi.handler.pyautogui_action_handler",
|
|
38
|
+
"PyautoguiConfig": "oagi.handler.pyautogui_action_handler",
|
|
39
|
+
"ScreenshotMaker": "oagi.handler.screenshot_maker",
|
|
42
40
|
# Agent modules (to avoid circular imports)
|
|
43
41
|
"TaskerAgent": "oagi.agent.tasker",
|
|
44
42
|
# Server modules (optional - requires server dependencies)
|
|
@@ -59,18 +57,17 @@ def __getattr__(name: str):
|
|
|
59
57
|
|
|
60
58
|
__all__ = [
|
|
61
59
|
# Core sync classes
|
|
62
|
-
"
|
|
63
|
-
"
|
|
60
|
+
"Actor",
|
|
61
|
+
"AsyncActor",
|
|
62
|
+
"Task", # Deprecated: Use Actor instead
|
|
63
|
+
"ShortTask", # Deprecated
|
|
64
64
|
"SyncClient",
|
|
65
65
|
# Core async classes
|
|
66
|
-
"AsyncTask",
|
|
67
|
-
"AsyncShortTask",
|
|
66
|
+
"AsyncTask", # Deprecated: Use AsyncActor instead
|
|
67
|
+
"AsyncShortTask", # Deprecated
|
|
68
68
|
"AsyncClient",
|
|
69
69
|
# Agent classes
|
|
70
70
|
"TaskerAgent",
|
|
71
|
-
# Functions
|
|
72
|
-
"single_step",
|
|
73
|
-
"async_single_step",
|
|
74
71
|
# Async protocols
|
|
75
72
|
"AsyncActionHandler",
|
|
76
73
|
"AsyncImageProvider",
|
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
import logging
|
|
10
10
|
|
|
11
|
-
from .. import
|
|
11
|
+
from .. import AsyncActor
|
|
12
12
|
from ..types import (
|
|
13
13
|
AsyncActionHandler,
|
|
14
14
|
AsyncImageProvider,
|
|
15
|
+
AsyncStepObserver,
|
|
15
16
|
)
|
|
16
17
|
|
|
17
18
|
logger = logging.getLogger(__name__)
|
|
@@ -27,12 +28,14 @@ class AsyncDefaultAgent:
|
|
|
27
28
|
model: str = "lux-v1",
|
|
28
29
|
max_steps: int = 30,
|
|
29
30
|
temperature: float | None = None,
|
|
31
|
+
step_observer: AsyncStepObserver | None = None,
|
|
30
32
|
):
|
|
31
33
|
self.api_key = api_key
|
|
32
34
|
self.base_url = base_url
|
|
33
35
|
self.model = model
|
|
34
36
|
self.max_steps = max_steps
|
|
35
37
|
self.temperature = temperature
|
|
38
|
+
self.step_observer = step_observer
|
|
36
39
|
|
|
37
40
|
async def execute(
|
|
38
41
|
self,
|
|
@@ -40,11 +43,11 @@ class AsyncDefaultAgent:
|
|
|
40
43
|
action_handler: AsyncActionHandler,
|
|
41
44
|
image_provider: AsyncImageProvider,
|
|
42
45
|
) -> bool:
|
|
43
|
-
async with
|
|
46
|
+
async with AsyncActor(
|
|
44
47
|
api_key=self.api_key, base_url=self.base_url, model=self.model
|
|
45
|
-
) as self.
|
|
48
|
+
) as self.actor:
|
|
46
49
|
logger.info(f"Starting async task execution: {instruction}")
|
|
47
|
-
await self.
|
|
50
|
+
await self.actor.init_task(instruction, max_steps=self.max_steps)
|
|
48
51
|
|
|
49
52
|
for i in range(self.max_steps):
|
|
50
53
|
logger.debug(f"Executing step {i + 1}/{self.max_steps}")
|
|
@@ -53,15 +56,28 @@ class AsyncDefaultAgent:
|
|
|
53
56
|
image = await image_provider()
|
|
54
57
|
|
|
55
58
|
# Get next step from OAGI
|
|
56
|
-
step = await self.
|
|
59
|
+
step = await self.actor.step(image, temperature=self.temperature)
|
|
57
60
|
|
|
58
61
|
# Log reasoning
|
|
59
62
|
if step.reason:
|
|
60
|
-
logger.
|
|
63
|
+
logger.info(f"Step {i + 1}: {step.reason}")
|
|
64
|
+
|
|
65
|
+
# Notify observer if present
|
|
66
|
+
if self.step_observer and step.actions:
|
|
67
|
+
await self.step_observer.on_step(i + 1, step.reason, step.actions)
|
|
61
68
|
|
|
62
69
|
# Execute actions if any
|
|
63
70
|
if step.actions:
|
|
64
|
-
logger.
|
|
71
|
+
logger.info(f"Actions ({len(step.actions)}):")
|
|
72
|
+
for action in step.actions:
|
|
73
|
+
count_suffix = (
|
|
74
|
+
f" x{action.count}"
|
|
75
|
+
if action.count and action.count > 1
|
|
76
|
+
else ""
|
|
77
|
+
)
|
|
78
|
+
logger.info(
|
|
79
|
+
f" [{action.type.value}] {action.argument}{count_suffix}"
|
|
80
|
+
)
|
|
65
81
|
await action_handler(step.actions)
|
|
66
82
|
|
|
67
83
|
# Check if task is complete
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
# Licensed under the MIT License.
|
|
7
7
|
# -----------------------------------------------------------------------------
|
|
8
8
|
from oagi.agent.tasker import TaskerAgent
|
|
9
|
+
from oagi.types import AsyncStepObserver
|
|
9
10
|
|
|
10
11
|
from .default import AsyncDefaultAgent
|
|
11
12
|
from .protocol import AsyncAgent
|
|
@@ -19,6 +20,7 @@ def create_default_agent(
|
|
|
19
20
|
model: str = "lux-v1",
|
|
20
21
|
max_steps: int = 20,
|
|
21
22
|
temperature: float = 0.1,
|
|
23
|
+
step_observer: AsyncStepObserver | None = None,
|
|
22
24
|
) -> AsyncAgent:
|
|
23
25
|
return AsyncDefaultAgent(
|
|
24
26
|
api_key=api_key,
|
|
@@ -26,6 +28,7 @@ def create_default_agent(
|
|
|
26
28
|
model=model,
|
|
27
29
|
max_steps=max_steps,
|
|
28
30
|
temperature=temperature,
|
|
31
|
+
step_observer=step_observer,
|
|
29
32
|
)
|
|
30
33
|
|
|
31
34
|
|
|
@@ -37,6 +40,7 @@ def create_planner_agent(
|
|
|
37
40
|
max_steps: int = 30,
|
|
38
41
|
temperature: float = 0.0,
|
|
39
42
|
reflection_interval: int = 20,
|
|
43
|
+
step_observer: AsyncStepObserver | None = None,
|
|
40
44
|
) -> AsyncAgent:
|
|
41
45
|
tasker = TaskerAgent(
|
|
42
46
|
api_key=api_key,
|
|
@@ -45,6 +49,7 @@ def create_planner_agent(
|
|
|
45
49
|
max_steps=max_steps,
|
|
46
50
|
temperature=temperature,
|
|
47
51
|
reflection_interval=reflection_interval,
|
|
52
|
+
step_observer=step_observer,
|
|
48
53
|
)
|
|
49
54
|
# tasker.set_task()
|
|
50
55
|
return tasker
|
|
@@ -10,8 +10,8 @@ import logging
|
|
|
10
10
|
from datetime import datetime
|
|
11
11
|
from typing import Any
|
|
12
12
|
|
|
13
|
-
from oagi import
|
|
14
|
-
from oagi.types import AsyncActionHandler, AsyncImageProvider
|
|
13
|
+
from oagi import AsyncActor
|
|
14
|
+
from oagi.types import AsyncActionHandler, AsyncImageProvider, AsyncStepObserver
|
|
15
15
|
|
|
16
16
|
from ..protocol import AsyncAgent
|
|
17
17
|
from .memory import PlannerMemory
|
|
@@ -42,6 +42,7 @@ class TaskeeAgent(AsyncAgent):
|
|
|
42
42
|
planner: Planner | None = None,
|
|
43
43
|
external_memory: PlannerMemory | None = None,
|
|
44
44
|
todo_index: int | None = None,
|
|
45
|
+
step_observer: AsyncStepObserver | None = None,
|
|
45
46
|
):
|
|
46
47
|
"""Initialize the taskee agent.
|
|
47
48
|
|
|
@@ -55,6 +56,7 @@ class TaskeeAgent(AsyncAgent):
|
|
|
55
56
|
planner: Planner for planning and reflection
|
|
56
57
|
external_memory: External memory from parent agent
|
|
57
58
|
todo_index: Index of the todo being executed
|
|
59
|
+
step_observer: Optional observer for step tracking
|
|
58
60
|
"""
|
|
59
61
|
self.api_key = api_key
|
|
60
62
|
self.base_url = base_url
|
|
@@ -65,9 +67,10 @@ class TaskeeAgent(AsyncAgent):
|
|
|
65
67
|
self.planner = planner or Planner()
|
|
66
68
|
self.external_memory = external_memory
|
|
67
69
|
self.todo_index = todo_index
|
|
70
|
+
self.step_observer = step_observer
|
|
68
71
|
|
|
69
72
|
# Internal state
|
|
70
|
-
self.
|
|
73
|
+
self.actor: AsyncActor | None = None
|
|
71
74
|
self.current_todo: str = ""
|
|
72
75
|
self.current_instruction: str = ""
|
|
73
76
|
self.actions: list[Action] = []
|
|
@@ -135,10 +138,10 @@ class TaskeeAgent(AsyncAgent):
|
|
|
135
138
|
)
|
|
136
139
|
return False
|
|
137
140
|
finally:
|
|
138
|
-
# Clean up
|
|
139
|
-
if self.
|
|
140
|
-
await self.
|
|
141
|
-
self.
|
|
141
|
+
# Clean up actor
|
|
142
|
+
if self.actor:
|
|
143
|
+
await self.actor.close()
|
|
144
|
+
self.actor = None
|
|
142
145
|
|
|
143
146
|
async def _initial_plan(self, image_provider: AsyncImageProvider) -> None:
|
|
144
147
|
"""Generate initial plan for the todo.
|
|
@@ -199,17 +202,17 @@ class TaskeeAgent(AsyncAgent):
|
|
|
199
202
|
logger.info(f"Executing subtask with max {max_steps} steps")
|
|
200
203
|
|
|
201
204
|
# Use async with for automatic resource management
|
|
202
|
-
async with
|
|
205
|
+
async with AsyncActor(
|
|
203
206
|
api_key=self.api_key,
|
|
204
207
|
base_url=self.base_url,
|
|
205
208
|
model=self.model,
|
|
206
209
|
temperature=self.temperature,
|
|
207
|
-
) as
|
|
210
|
+
) as actor:
|
|
208
211
|
# Store reference for potential cleanup in execute's finally block
|
|
209
|
-
self.
|
|
212
|
+
self.actor = actor
|
|
210
213
|
|
|
211
|
-
# Initialize
|
|
212
|
-
await
|
|
214
|
+
# Initialize actor with current instruction
|
|
215
|
+
await actor.init_task(self.current_instruction)
|
|
213
216
|
|
|
214
217
|
steps_taken = 0
|
|
215
218
|
for step_num in range(max_steps):
|
|
@@ -218,7 +221,7 @@ class TaskeeAgent(AsyncAgent):
|
|
|
218
221
|
|
|
219
222
|
# Get next step from OAGI
|
|
220
223
|
try:
|
|
221
|
-
step = await
|
|
224
|
+
step = await actor.step(screenshot, instruction=None)
|
|
222
225
|
except Exception as e:
|
|
223
226
|
logger.error(f"Error getting step from OAGI: {e}")
|
|
224
227
|
self._record_action(
|
|
@@ -228,8 +231,24 @@ class TaskeeAgent(AsyncAgent):
|
|
|
228
231
|
)
|
|
229
232
|
break
|
|
230
233
|
|
|
234
|
+
# Log reasoning
|
|
235
|
+
if step.reason:
|
|
236
|
+
logger.info(f"Step {self.total_actions + 1}: {step.reason}")
|
|
237
|
+
|
|
231
238
|
# Record OAGI actions
|
|
232
239
|
if step.actions:
|
|
240
|
+
# Log actions with details
|
|
241
|
+
logger.info(f"Actions ({len(step.actions)}):")
|
|
242
|
+
for action in step.actions:
|
|
243
|
+
count_suffix = (
|
|
244
|
+
f" x{action.count}"
|
|
245
|
+
if action.count and action.count > 1
|
|
246
|
+
else ""
|
|
247
|
+
)
|
|
248
|
+
logger.info(
|
|
249
|
+
f" [{action.type.value}] {action.argument}{count_suffix}"
|
|
250
|
+
)
|
|
251
|
+
|
|
233
252
|
for action in step.actions:
|
|
234
253
|
self._record_action(
|
|
235
254
|
action_type=action.type.lower(),
|
|
@@ -237,6 +256,12 @@ class TaskeeAgent(AsyncAgent):
|
|
|
237
256
|
reasoning=step.reason,
|
|
238
257
|
)
|
|
239
258
|
|
|
259
|
+
# Notify observer if present
|
|
260
|
+
if self.step_observer:
|
|
261
|
+
await self.step_observer.on_step(
|
|
262
|
+
self.total_actions + 1, step.reason, step.actions
|
|
263
|
+
)
|
|
264
|
+
|
|
240
265
|
# Execute actions
|
|
241
266
|
await action_handler(step.actions)
|
|
242
267
|
self.total_actions += len(step.actions)
|
|
@@ -255,9 +280,9 @@ class TaskeeAgent(AsyncAgent):
|
|
|
255
280
|
logger.info("Reflection interval reached")
|
|
256
281
|
break
|
|
257
282
|
|
|
258
|
-
#
|
|
283
|
+
# Actor will be automatically closed by async with context manager
|
|
259
284
|
# Clear reference after context manager closes it
|
|
260
|
-
self.
|
|
285
|
+
self.actor = None
|
|
261
286
|
return steps_taken
|
|
262
287
|
|
|
263
288
|
async def _reflect_and_decide(self, image_provider: AsyncImageProvider) -> bool:
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import logging
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
-
from oagi.types import AsyncActionHandler, AsyncImageProvider
|
|
12
|
+
from oagi.types import AsyncActionHandler, AsyncImageProvider, AsyncStepObserver
|
|
13
13
|
|
|
14
14
|
from ..protocol import AsyncAgent
|
|
15
15
|
from .memory import PlannerMemory
|
|
@@ -39,6 +39,7 @@ class TaskerAgent(AsyncAgent):
|
|
|
39
39
|
temperature: float = 0.0,
|
|
40
40
|
reflection_interval: int = 20,
|
|
41
41
|
planner: Planner | None = None,
|
|
42
|
+
step_observer: AsyncStepObserver | None = None,
|
|
42
43
|
):
|
|
43
44
|
"""Initialize the tasker agent.
|
|
44
45
|
|
|
@@ -50,6 +51,7 @@ class TaskerAgent(AsyncAgent):
|
|
|
50
51
|
temperature: Sampling temperature
|
|
51
52
|
reflection_interval: Actions before reflection
|
|
52
53
|
planner: Planner for planning and reflection
|
|
54
|
+
step_observer: Optional observer for step tracking
|
|
53
55
|
"""
|
|
54
56
|
self.api_key = api_key
|
|
55
57
|
self.base_url = base_url
|
|
@@ -58,6 +60,7 @@ class TaskerAgent(AsyncAgent):
|
|
|
58
60
|
self.temperature = temperature
|
|
59
61
|
self.reflection_interval = reflection_interval
|
|
60
62
|
self.planner = planner or Planner()
|
|
63
|
+
self.step_observer = step_observer
|
|
61
64
|
|
|
62
65
|
# Memory for tracking workflow
|
|
63
66
|
self.memory = PlannerMemory()
|
|
@@ -174,6 +177,7 @@ class TaskerAgent(AsyncAgent):
|
|
|
174
177
|
planner=self.planner,
|
|
175
178
|
external_memory=self.memory, # Share memory with child
|
|
176
179
|
todo_index=todo_index, # Pass the todo index
|
|
180
|
+
step_observer=self.step_observer, # Pass step observer
|
|
177
181
|
)
|
|
178
182
|
|
|
179
183
|
self.current_todo_index = todo_index
|