oagi-core 0.10.3__py3-none-any.whl → 0.12.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.
Files changed (44) hide show
  1. oagi/__init__.py +1 -3
  2. oagi/actor/__init__.py +21 -0
  3. oagi/{task → actor}/async_.py +23 -7
  4. oagi/{task → actor}/async_short.py +1 -1
  5. oagi/actor/base.py +222 -0
  6. oagi/{task → actor}/short.py +1 -1
  7. oagi/{task → actor}/sync.py +21 -5
  8. oagi/agent/default.py +5 -0
  9. oagi/agent/factories.py +75 -3
  10. oagi/agent/observer/exporters.py +6 -0
  11. oagi/agent/observer/report_template.html +19 -0
  12. oagi/agent/tasker/planner.py +31 -19
  13. oagi/agent/tasker/taskee_agent.py +26 -7
  14. oagi/agent/tasker/tasker_agent.py +4 -0
  15. oagi/cli/agent.py +54 -30
  16. oagi/client/async_.py +54 -96
  17. oagi/client/base.py +81 -133
  18. oagi/client/sync.py +52 -99
  19. oagi/constants.py +7 -2
  20. oagi/handler/__init__.py +16 -0
  21. oagi/handler/_macos.py +137 -0
  22. oagi/handler/_windows.py +101 -0
  23. oagi/handler/async_pyautogui_action_handler.py +8 -0
  24. oagi/handler/capslock_manager.py +55 -0
  25. oagi/handler/pyautogui_action_handler.py +21 -39
  26. oagi/server/session_store.py +3 -3
  27. oagi/server/socketio_server.py +4 -4
  28. oagi/task/__init__.py +22 -8
  29. oagi/types/__init__.py +2 -1
  30. oagi/types/models/__init__.py +0 -2
  31. oagi/types/models/action.py +4 -1
  32. oagi/types/models/client.py +1 -17
  33. oagi/types/step_observer.py +2 -0
  34. oagi/types/url.py +25 -0
  35. oagi/utils/__init__.py +12 -0
  36. oagi/utils/output_parser.py +166 -0
  37. oagi/utils/prompt_builder.py +44 -0
  38. {oagi_core-0.10.3.dist-info → oagi_core-0.12.0.dist-info}/METADATA +90 -10
  39. oagi_core-0.12.0.dist-info/RECORD +76 -0
  40. oagi/task/base.py +0 -158
  41. oagi_core-0.10.3.dist-info/RECORD +0 -70
  42. {oagi_core-0.10.3.dist-info → oagi_core-0.12.0.dist-info}/WHEEL +0 -0
  43. {oagi_core-0.10.3.dist-info → oagi_core-0.12.0.dist-info}/entry_points.txt +0 -0
  44. {oagi_core-0.10.3.dist-info → oagi_core-0.12.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,166 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Copyright (c) OpenAGI Foundation
3
+ # All rights reserved.
4
+ #
5
+ # This file is part of the official API project.
6
+ # Licensed under the MIT License.
7
+ # -----------------------------------------------------------------------------
8
+
9
+ import re
10
+
11
+ from ..types.models.action import Action, ActionType
12
+ from ..types.models.step import Step
13
+
14
+
15
+ def parse_raw_output(raw_output: str) -> Step:
16
+ """Parse raw LLM output into structured Step format.
17
+
18
+ Expected format:
19
+ <|think_start|> reasoning text <|think_end|>
20
+ <|action_start|> action1(args) & action2(args) & ... <|action_end|>
21
+
22
+ Args:
23
+ raw_output: Raw text output from the LLM
24
+
25
+ Returns:
26
+ Step object with parsed reasoning and actions
27
+ """
28
+ # Extract reasoning/thinking
29
+ think_pattern = r"<\|think_start\|>(.*?)<\|think_end\|>"
30
+ think_match = re.search(think_pattern, raw_output, re.DOTALL)
31
+ reason = think_match.group(1).strip() if think_match else ""
32
+
33
+ # Extract action block
34
+ action_pattern = r"<\|action_start\|>(.*?)<\|action_end\|>"
35
+ action_match = re.search(action_pattern, raw_output, re.DOTALL)
36
+
37
+ actions: list[Action] = []
38
+ stop = False
39
+
40
+ if action_match:
41
+ action_block = action_match.group(1).strip()
42
+ action_texts = _split_actions(action_block)
43
+
44
+ for action_text in action_texts:
45
+ parsed_action = _parse_action(action_text.strip())
46
+ if parsed_action:
47
+ actions.append(parsed_action)
48
+ if parsed_action.type == ActionType.FINISH:
49
+ stop = True
50
+
51
+ return Step(reason=reason, actions=actions, stop=stop)
52
+
53
+
54
+ def _split_actions(action_block: str) -> list[str]:
55
+ """Split action block by & separator, but only when & is outside parentheses.
56
+
57
+ Note: This parser does NOT handle '&' inside quoted strings.
58
+ E.g., type("a&b") would incorrectly split. The LLM should avoid
59
+ this pattern by using alternative escape sequences.
60
+
61
+ Args:
62
+ action_block: String containing one or more actions separated by &
63
+
64
+ Returns:
65
+ List of individual action strings
66
+ """
67
+ actions: list[str] = []
68
+ current_action: list[str] = []
69
+ paren_level = 0
70
+
71
+ for char in action_block:
72
+ if char == "(":
73
+ paren_level += 1
74
+ current_action.append(char)
75
+ elif char == ")":
76
+ paren_level -= 1
77
+ current_action.append(char)
78
+ elif char == "&" and paren_level == 0:
79
+ action_str = "".join(current_action).strip()
80
+ if action_str:
81
+ actions.append(action_str)
82
+ current_action = []
83
+ else:
84
+ current_action.append(char)
85
+
86
+ # Add the last action
87
+ action_str = "".join(current_action).strip()
88
+ if action_str:
89
+ actions.append(action_str)
90
+
91
+ return actions
92
+
93
+
94
+ def _parse_action(action_text: str) -> Action | None:
95
+ """Parse individual action text into Action object.
96
+
97
+ Expected formats:
98
+ - click(x, y) # left-click at position
99
+ - left_double(x, y) # left-double-click at position
100
+ - left_triple(x, y) # left-triple-click at position
101
+ - right_single(x, y) # right-click at position
102
+ - drag(x1, y1, x2, y2) # drag from (x1, y1) to (x2, y2)
103
+ - hotkey(key, c) # press key c times
104
+ - type(text) # type text string
105
+ - scroll(x, y, direction, c) # scroll at position
106
+ - wait() # wait for a while
107
+ - finish() # indicate task is finished
108
+
109
+ Args:
110
+ action_text: String representation of a single action
111
+
112
+ Returns:
113
+ Action object or None if parsing fails
114
+ """
115
+ # Match action format: action_type(arguments)
116
+ match = re.match(r"(\w+)\((.*)\)", action_text.strip())
117
+ if not match:
118
+ return None
119
+
120
+ action_type = match.group(1).lower()
121
+ arguments = match.group(2).strip()
122
+
123
+ # Parse count from arguments for actions that support it
124
+ count = 1
125
+
126
+ # Validate and map action type to enum
127
+ try:
128
+ action_enum = ActionType(action_type)
129
+ except ValueError:
130
+ return None
131
+
132
+ # Parse specific action types and extract count where applicable
133
+ match action_enum:
134
+ case ActionType.HOTKEY:
135
+ # hotkey(key, c) - press key c times
136
+ args = arguments.rsplit(",", 1)
137
+ if len(args) >= 2 and args[1].strip():
138
+ key = args[0].strip()
139
+ try:
140
+ count = int(args[1].strip())
141
+ except ValueError:
142
+ count = 1
143
+ else:
144
+ key = arguments.strip()
145
+ count = 1
146
+ arguments = key
147
+
148
+ case ActionType.SCROLL:
149
+ # scroll(x, y, direction, c) - scroll at position
150
+ args = arguments.split(",")
151
+ if len(args) >= 4:
152
+ x = args[0].strip()
153
+ y = args[1].strip()
154
+ direction = args[2].strip()
155
+ try:
156
+ count = int(args[3].strip())
157
+ except (ValueError, IndexError):
158
+ count = 1
159
+ # Reconstruct arguments without count
160
+ arguments = f"{x},{y},{direction}"
161
+
162
+ case _:
163
+ # For other actions, use default count of 1
164
+ pass
165
+
166
+ return Action(type=action_enum, argument=arguments, count=count)
@@ -0,0 +1,44 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Copyright (c) OpenAGI Foundation
3
+ # All rights reserved.
4
+ #
5
+ # This file is part of the official API project.
6
+ # Licensed under the MIT License.
7
+ # -----------------------------------------------------------------------------
8
+
9
+ instruction_template = """You are a Desktop Agent completing computer use tasks from a user instruction.
10
+
11
+ Every step, you will look at the screenshot and output the desired actions in a format as:
12
+
13
+ <|think_start|> brief description of your intent and reasoning <|think_end|>
14
+ <|action_start|> one of the allowed actions as below <|action_end|>
15
+
16
+ In the action field, you have the following action formats:
17
+ 1. click(x, y) # left-click at the position (x, y), where x and y are integers normalized between 0 and 1000
18
+ 2. left_double(x, y) # left-double-click at the position (x, y), where x and y are integers normalized between 0 and 1000
19
+ 3. left_triple(x, y) # left-triple-click at the position (x, y), where x and y are integers normalized between 0 and 1000
20
+ 4. right_single(x, y) # right-click at the position (x, y), where x and y are integers normalized between 0 and 1000
21
+ 5. drag(x1, y1, x2, y2) # drag the mouse from (x1, y1) to (x2, y2) to select or move contents, where x1, y1, x2, y2 are integers normalized between 0 and 1000
22
+ 6. hotkey(key, c) # press the key for c times
23
+ 7. type(text) # type a text string on the keyboard
24
+ 8. scroll(x, y, direction, c) # scroll the mouse at position (x, y) in the direction of up or down for c times, where x and y are integers normalized between 0 and 1000
25
+ 9. wait() # wait for a while
26
+ 10. finish() # indicate the task is finished
27
+
28
+ Directly output the text beginning with <|think_start|>, no additional text is needed for this scenario.
29
+
30
+ The user instruction is:
31
+ {instruction}
32
+ """
33
+
34
+
35
+ def build_prompt(task_description: str) -> str:
36
+ """Build the instruction prompt for the OAGI model.
37
+
38
+ Args:
39
+ task_description: The task description to include in the prompt
40
+
41
+ Returns:
42
+ The formatted prompt string with action format documentation
43
+ """
44
+ return instruction_template.format(instruction=task_description)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: oagi-core
3
- Version: 0.10.3
3
+ Version: 0.12.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>
@@ -26,25 +26,71 @@ License: MIT License
26
26
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
27
  SOFTWARE.
28
28
  Requires-Python: >=3.10
29
- Requires-Dist: httpx>=0.28.0
29
+ Requires-Dist: httpx>=0.24.0
30
+ Requires-Dist: openai>=1.3.0
30
31
  Requires-Dist: pydantic>=2.0.0
31
- Requires-Dist: rich>=13.0.0
32
+ Requires-Dist: rich>=10.0.0
32
33
  Provides-Extra: desktop
33
- Requires-Dist: pillow>=11.3.0; extra == 'desktop'
34
+ Requires-Dist: pillow>=9.0.0; extra == 'desktop'
34
35
  Requires-Dist: pyautogui>=0.9.54; extra == 'desktop'
35
- Requires-Dist: pyobjc-framework-applicationservices>=9.0; (sys_platform == 'darwin') and extra == 'desktop'
36
- Requires-Dist: pyobjc-framework-quartz>=9.0; (sys_platform == 'darwin') and extra == 'desktop'
36
+ Requires-Dist: pyobjc-framework-applicationservices>=8.0; (sys_platform == 'darwin') and extra == 'desktop'
37
+ Requires-Dist: pyobjc-framework-quartz>=8.0; (sys_platform == 'darwin') and extra == 'desktop'
37
38
  Provides-Extra: server
38
- Requires-Dist: fastapi[standard]>=0.115.0; extra == 'server'
39
+ Requires-Dist: fastapi[standard]>=0.100.0; extra == 'server'
39
40
  Requires-Dist: pydantic-settings>=2.0.0; extra == 'server'
40
- Requires-Dist: python-socketio>=5.11.0; extra == 'server'
41
- Requires-Dist: uvicorn[standard]>=0.32.0; extra == 'server'
41
+ Requires-Dist: python-socketio>=5.5.0; extra == 'server'
42
+ Requires-Dist: uvicorn[standard]>=0.20.0; extra == 'server'
42
43
  Description-Content-Type: text/markdown
43
44
 
44
45
  # OAGI Python SDK
45
46
 
47
+ [![PyPI version](https://img.shields.io/pypi/v/oagi-core)](https://pypi.org/project/oagi-core/)
48
+ [![Python version](https://img.shields.io/pypi/pyversions/oagi-core)](https://pypi.org/project/oagi-core/)
49
+ [![License](https://img.shields.io/github/license/agiopen-org/oagi-python)](https://github.com/agiopen-org/oagi-python/blob/main/LICENSE)
50
+ [![Build status](https://img.shields.io/github/actions/workflow/status/agiopen-org/oagi-python/ci.yml?branch=main)](https://github.com/agiopen-org/oagi-python/actions/workflows/ci.yml)
51
+
46
52
  Python SDK for the OAGI API - vision-based task automation.
47
53
 
54
+ ## What is OAGI?
55
+
56
+ OAGI is the Python SDK for **Lux**, the world's most advanced computer-use model from the OpenAGI Foundation.
57
+
58
+ **Computer Use** is AI's ability to operate human-facing software — not just through APIs, but by operating computers natively, just as human users do. It's a paradigm shift in what AI can do: not just generating, reasoning, or researching, but actually operating on your computer.
59
+
60
+ Lux comes in three modes, giving you control over depth, speed, and style of execution:
61
+
62
+ - **Tasker** — Strictly follows step-by-step instructions with ultra-stable, controllable execution
63
+ - **Actor** — Ideal for immediate tasks, completing actions at near-instant speed
64
+ - **Thinker** — Understands vague, complex goals, performing hour-long executions
65
+
66
+ ### Use Cases
67
+
68
+ With Lux, possibilities are endless. Here are a few examples:
69
+
70
+ - **Web Scraping & Data Crawl** — Navigate websites, sort results, and collect product information autonomously
71
+ - **Software QA** — Automate repetitive testing tasks, navigate applications, perform test actions, and validate expected behaviors
72
+ - **Financial Data Extraction** — Navigate to sites like NASDAQ and extract insider activity data
73
+ - **Data Entry** — Enter accurate data across dashboards and forms
74
+ - **Workflow Automation** — Chain together multi-step tasks across different applications
75
+
76
+ ## Table of Contents
77
+
78
+ - [What is OAGI?](#what-is-oagi)
79
+ - [Installation](#installation)
80
+ - [Quick Start](#quick-start)
81
+ - [Automated Task Execution](#automated-task-execution)
82
+ - [Command Line Interface](#command-line-interface)
83
+ - [Image Processing](#image-processing)
84
+ - [Manual Control with Actor](#manual-control-with-actor)
85
+ - [Examples](#examples)
86
+ - [Socket.IO Server (Optional)](#socketio-server-optional)
87
+ - [Installation](#installation-1)
88
+ - [Running the Server](#running-the-server)
89
+ - [Server Features](#server-features)
90
+ - [Client Integration](#client-integration)
91
+ - [Documentation](#documentation)
92
+ - [License](#license)
93
+
48
94
  ## Installation
49
95
 
50
96
  ```bash
@@ -74,7 +120,7 @@ pip install oagi-core[server] # Server support
74
120
 
75
121
  Set your API credentials:
76
122
  ```bash
77
- export OAGI_API_KEY="your-api-key" # get your API key from https://developer.openagi.org/
123
+ export OAGI_API_KEY="your-api-key" # get your API key from https://developer.agiopen.org/
78
124
  # export OAGI_BASE_URL="https://api.agiopen.org/", # optional, defaults to production endpoint
79
125
  ```
80
126
 
@@ -116,6 +162,39 @@ config = PyautoguiConfig(
116
162
  action_handler = AsyncPyautoguiActionHandler(config=config)
117
163
  ```
118
164
 
165
+ ### Command Line Interface
166
+
167
+ Run agents directly from the terminal:
168
+
169
+ ```bash
170
+ # Run with actor model
171
+ oagi agent run "Go to nasdaq.com, search for AAPL. Under More, go to Insider Activity" --model lux-actor-1
172
+
173
+ # Run with thinker mode (uses lux-thinker-1 model with more steps)
174
+ oagi agent run "Look up the store hours for the nearest Apple Store to zip code 23456 using the Apple Store Locator" --model lux-thinker-1
175
+
176
+ # Run pre-configured tasker workflows (no instruction needed)
177
+ oagi agent run --mode tasker:software_qa
178
+
179
+ # List all available modes
180
+ oagi agent modes
181
+
182
+ # Check macOS permissions (screen recording & accessibility)
183
+ oagi agent permission
184
+
185
+ # Export execution history
186
+ oagi agent run "Complete the form" --export html --export-file report.html
187
+ ```
188
+
189
+ CLI options:
190
+ - `--mode`: Agent mode (default: actor). Use `oagi agent modes` to list available modes
191
+ - `--model`: Override the model (default: determined by mode)
192
+ - `--max-steps`: Maximum steps (default: determined by mode)
193
+ - `--temperature`: Sampling temperature (default: determined by mode)
194
+ - `--step-delay`: Delay after each action before next screenshot (default: 0.3s)
195
+ - `--export`: Export format (markdown, html, json)
196
+ - `--export-file`: Output file path for export
197
+
119
198
  ### Image Processing
120
199
 
121
200
  Process and optimize images before sending to API:
@@ -239,6 +318,7 @@ See [`examples/socketio_client_example.py`](examples/socketio_client_example.py)
239
318
 
240
319
  ## Documentation
241
320
 
321
+ For full Lux documentation and guides, visit the [OAGI Developer Documentation](https://developer.agiopen.org/docs/index).
242
322
 
243
323
  ## License
244
324
 
@@ -0,0 +1,76 @@
1
+ oagi/__init__.py,sha256=hKfGbbvYFNoc8LsTd34aM6Uj-nGEJ0J8JbceXZP5xZ0,4801
2
+ oagi/constants.py,sha256=ywyMimjh15tC5p4MBZjkJIqOVElPRS50iJtrPE3VClw,1211
3
+ oagi/exceptions.py,sha256=Rco37GQTPYUfc2vRO3hozxPF_s8mKFDpFvBg2UKWo3Y,3066
4
+ oagi/logging.py,sha256=YT3KCMFj5fzO98R9xlDDgfSotUuz1xRD6OZeYM2rKoo,1760
5
+ oagi/actor/__init__.py,sha256=g_8_7ZLDLKuCGzyrB42OzY3gSOjd_SxzkJW3_pf-PXs,662
6
+ oagi/actor/async_.py,sha256=DcU6ifAcrYI1GSrTFgMPrWhikjmnJfZVaFsun15DG_k,3768
7
+ oagi/actor/async_short.py,sha256=QSo67aPsd_rxA2J2TR1fv6nJD6wO00q3S-QQYNK93q4,2821
8
+ oagi/actor/base.py,sha256=UUZdS1tufZDIbtQHLs-es6ptGHQpa-EPWf7RSbVpQnU,7921
9
+ oagi/actor/short.py,sha256=wKLCxvf7Ys6rYxXpHe4zbZdbf_1q1qcmm5WyWubwj3E,2630
10
+ oagi/actor/sync.py,sha256=QTY1WNTI75jwkWBghdVViHIp5rYkbm3kumlLedU8YeQ,3588
11
+ oagi/agent/__init__.py,sha256=KTVLUMhbjgpTJoOWMUZkkiqwhgumvbOZV2tJ9XCLfao,901
12
+ oagi/agent/default.py,sha256=YKAAq_XJrM-YpYuLtDtEH9XA502eijsdiawQKAf4iJ0,4709
13
+ oagi/agent/factories.py,sha256=syi_EOlU4SUjo-0CKaML8eIPu3ToUEKua2VHp9lvNF0,5839
14
+ oagi/agent/protocol.py,sha256=IQJGiMN4yZIacrh5e9JQsoM9TyHb8wJRQR4LAk8dSA0,1615
15
+ oagi/agent/registry.py,sha256=7bMA2-pH3xQ9ZavrHB_mnc2fOGSMeICPbOGtHoM7It0,4851
16
+ oagi/agent/observer/__init__.py,sha256=YZ4qvR22pFB0mSDMX6iKKLbBA1dB-nqC7HZVvdMIVGw,909
17
+ oagi/agent/observer/agent_observer.py,sha256=fBs4X2_YKhYVThJocjMM-65JAHQSCLJPvzy8OXMt5pY,2864
18
+ oagi/agent/observer/events.py,sha256=xc3Z1UGpX69BqhO9cQiGmnRhDZbMYya1kuXm6bXtjWI,625
19
+ oagi/agent/observer/exporters.py,sha256=HeEE5bmWjgOATLkh1R-m1P7f1Ztb58BHk6xbxdsdxCw,12153
20
+ oagi/agent/observer/protocol.py,sha256=jyRXoCG4CdvaPaDASar1rSbwc7vdpkar39KkGpwf8jw,411
21
+ oagi/agent/observer/report_template.html,sha256=HtvJLh3swTMfmIw4XyGFqquS4vjP9iOe5L2tTnOKpzY,15388
22
+ oagi/agent/tasker/__init__.py,sha256=1iTEFe7lzcqh96TL9R0QADPpLJLrUP0shtZ4DlZSv_8,764
23
+ oagi/agent/tasker/memory.py,sha256=NR13l5yxRA8GUE-oupAP4W1n80ZNG0SxpUfxsNltkUY,5033
24
+ oagi/agent/tasker/models.py,sha256=sMQgwIMKhT1tvVF2yoc1hh8GwEiJ6i6qPMy9WoiA8JM,2137
25
+ oagi/agent/tasker/planner.py,sha256=q6IvH6sfU2kYX1NcC9VHjGaQ0X9jF18yjuAYXisNCg0,15489
26
+ oagi/agent/tasker/taskee_agent.py,sha256=VquuEkkjpLYOVPamHDz53e9GClj6v93VPMHoiNmR8-U,18084
27
+ oagi/agent/tasker/tasker_agent.py,sha256=kbWvvRVS12S8eFd0PRszFrcSSWRzz_f6Jd7LuaRcwJQ,11285
28
+ oagi/cli/__init__.py,sha256=aDnJViTseShpo5fdGPTj-ELysZhmdvB6Z8mEj2D-_N4,359
29
+ oagi/cli/agent.py,sha256=fd7WtR5zoRJmyHDr67zfBvEX-_BLIjPbBqp-dhy4AAk,11061
30
+ oagi/cli/display.py,sha256=Y8_Dn5RIEfRqZUHVGF6URItW0C3XC7bPLWoAmmhvBS0,1829
31
+ oagi/cli/main.py,sha256=faHns0HaQCGyylDn2YZLpjQESuEiMYjoQVoMkt8FsH4,2292
32
+ oagi/cli/server.py,sha256=JFpzCOeaftITxesz8Ya-_Efs03bgotBg7aYwmMZhPwU,3033
33
+ oagi/cli/tracking.py,sha256=TdrAcNq_-OjgXltFCoFc8NsO_k6yHbdzHnMn3vAAvKA,1707
34
+ oagi/cli/utils.py,sha256=zIkTrr-ai__3cGSaxiXY-OJs69Fcxd1sHb2FoeyHFtE,3034
35
+ oagi/client/__init__.py,sha256=F9DShPUdb6vZYmN1fpM1VYzp4MWqUao_e_R1KYmM4Q4,410
36
+ oagi/client/async_.py,sha256=m7hkJSebH2MyXAwEbpsFw0UQm6aRJQ8HZiULBlZxvM4,9385
37
+ oagi/client/base.py,sha256=kKkdpd-YkjFfTVCOQzVRjjkQnCpH2hZLtyM1vKizy6I,14693
38
+ oagi/client/sync.py,sha256=-wtaW1H5jgj32_1TDVxMO7zdZ47ZV6ZG7a6jF2ztbv0,9158
39
+ oagi/handler/__init__.py,sha256=vEUvyiUvTRf1GE4vTiz_bQjLv3psdmHyt0mfKJHq24M,1247
40
+ oagi/handler/_macos.py,sha256=Gs8GrhA_WAyv9Yw0D41duliP32Xk6vouyMeWjWJJT90,5187
41
+ oagi/handler/_windows.py,sha256=MSgPDYEOetSjbn9eJDSrdzBVlUGgGsTlegaTDc4C4Ss,2828
42
+ oagi/handler/async_pyautogui_action_handler.py,sha256=wfNRBBURZnwQkNTcs9OPMmFJIAPtnXmcqxWbjda_q7I,1863
43
+ oagi/handler/async_screenshot_maker.py,sha256=8QCtUV59ozpOpvkqhUMb8QDI2qje2gsoFT1qB60tfJM,1689
44
+ oagi/handler/capslock_manager.py,sha256=40LzWt1_1wbncF5koUTdbd9V3eo5Ex_mEWwjtEmHAf4,1878
45
+ oagi/handler/pil_image.py,sha256=yUcAoGBL-aZ0PCjSaAmQsDwtyzjldXHqXQp_OYRk6e4,4080
46
+ oagi/handler/pyautogui_action_handler.py,sha256=BVmpKuYAMINJ5Ue_PK_WxFScAqLeyXC64g4NWQUtG_M,10146
47
+ oagi/handler/screenshot_maker.py,sha256=j1jTW-awx3vAnb1N5_FIMBC0Z-rNVQbiBP-S6Gh5dlE,1284
48
+ oagi/server/__init__.py,sha256=uZx8u3vJUb87kkNzwmmVrgAgbqRu0WxyMIQCLSx56kk,452
49
+ oagi/server/agent_wrappers.py,sha256=j8va0A7u80bzOM82nndAplK1uaO_T3kufHWScK6kfWM,3263
50
+ oagi/server/config.py,sha256=AJ1PLKuxrc6pRuur1hm5DwG2g2otxPwOCfKgzIACkSk,1691
51
+ oagi/server/main.py,sha256=jnTxk7Prc5CzlsUnkBNJp4MOoYN-7HN_Be_m1d3COa8,4829
52
+ oagi/server/models.py,sha256=DXjuf5icpCOgCUGMzzoLfRCoreM541KBWKBZnCk5_S0,2688
53
+ oagi/server/session_store.py,sha256=l7t31rNWuZkIPLnaqrllVusHkJkE8j50PMfyb1di9mI,3750
54
+ oagi/server/socketio_server.py,sha256=8RRf8mAmsArOX2nWylT0g5T5On0gzMod0TWRmk0vrgA,14218
55
+ oagi/task/__init__.py,sha256=8l3z5nxA3RtGHP94Iu4ot1Wo3Lx-U7_Led2CsVwYINg,760
56
+ oagi/types/__init__.py,sha256=_UyzzRnoKvp00BUBjxW9Tv3_xBNf8Lxb2PUC2DkjOkg,1384
57
+ oagi/types/action_handler.py,sha256=NH8E-m5qpGqWcXzTSWfF7W0Xdp8SkzJsbhCmQ0B96cg,1075
58
+ oagi/types/async_action_handler.py,sha256=k1AaqSkFcXlxwW8sn-w0WFHGsIqHFLbcOPrkknmSVug,1116
59
+ oagi/types/async_image_provider.py,sha256=UwDl7VOCA3tiSP5k1fnxK86iEa84Yr57MVaoBSa3hOE,1203
60
+ oagi/types/image.py,sha256=KgPCCTJ6D5vHIaGZdbTE7eQEa1WlT6G9tf59ZuUCV2U,537
61
+ oagi/types/image_provider.py,sha256=IhKEnwCGZ5l_rO3AvJ6xv5RZMTmTDmqsFRynI9h0R_M,1145
62
+ oagi/types/step_observer.py,sha256=E7igVqpOeoizUkhXbGRRX80ZOuqoM-zcRyjNyOXwWc8,2380
63
+ oagi/types/url.py,sha256=145jLl3yecFBVKhJDbrR63C48D3l9_w0kpA_8C_gM78,868
64
+ oagi/types/models/__init__.py,sha256=VcNrVQvw9p8igBunOv3LQBPnRpp5WEcWBf1Nr9FGkeI,843
65
+ oagi/types/models/action.py,sha256=s3oPBCtbVAmavArjFZBEbL71QyW_akUrXpEDJuHqkYI,2583
66
+ oagi/types/models/client.py,sha256=5fUZVTPviTunoh2KXM3jmLPtPIrvPwrr8o2bR6Phj5M,1156
67
+ oagi/types/models/image_config.py,sha256=tl6abVg_-IAPLwpaWprgknXu7wRWriMg-AEVyUX73v0,1567
68
+ oagi/types/models/step.py,sha256=RSI4H_2rrUBq_xyCoWKaq7JHdJWNobtQppaKC1l0aWU,471
69
+ oagi/utils/__init__.py,sha256=vHXyX66hEsf33OJJkmZSUjaTYU0UngfbtjcZgxfOj3A,441
70
+ oagi/utils/output_parser.py,sha256=U7vzmoD8pyzDg23z3vy-L9a_jKPsAlr3x8lIdPszrY8,5322
71
+ oagi/utils/prompt_builder.py,sha256=_Q1HY82YUrq3jSCTZ3Rszu3qmI3Wn_fmq8hf14NuwQM,2180
72
+ oagi_core-0.12.0.dist-info/METADATA,sha256=a8SJt-skg0xQjodJEqwLd0EOJzhw8BrHBUIqlYGEf1Y,12176
73
+ oagi_core-0.12.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
74
+ oagi_core-0.12.0.dist-info/entry_points.txt,sha256=zzgsOSWX6aN3KUB0Z1it8DMxFFBJBqmZVqMVAJRjYuw,44
75
+ oagi_core-0.12.0.dist-info/licenses/LICENSE,sha256=sy5DLA2M29jFT4UfWsuBF9BAr3FnRkYtnAu6oDZiIf8,1075
76
+ oagi_core-0.12.0.dist-info/RECORD,,
oagi/task/base.py DELETED
@@ -1,158 +0,0 @@
1
- # -----------------------------------------------------------------------------
2
- # Copyright (c) OpenAGI Foundation
3
- # All rights reserved.
4
- #
5
- # This file is part of the official API project.
6
- # Licensed under the MIT License.
7
- # -----------------------------------------------------------------------------
8
-
9
- from uuid import uuid4
10
-
11
- from ..constants import DEFAULT_MAX_STEPS
12
- from ..logging import get_logger
13
- from ..types import URL, Image, Step
14
- from ..types.models import LLMResponse
15
-
16
- logger = get_logger("task.base")
17
-
18
-
19
- class BaseActor:
20
- """Base class with shared task management logic for sync/async actors."""
21
-
22
- def __init__(
23
- self,
24
- api_key: str | None,
25
- base_url: str | None,
26
- model: str,
27
- temperature: float | None,
28
- ):
29
- self.task_id: str = uuid4().hex # Client-side generated UUID
30
- self.task_description: str | None = None
31
- self.model = model
32
- self.temperature = temperature
33
- self.message_history: list = [] # OpenAI-compatible message history
34
- self.max_steps: int = DEFAULT_MAX_STEPS
35
- self.current_step: int = 0 # Current step counter
36
- # Client will be set by subclasses
37
- self.api_key: str | None = None
38
- self.base_url: str | None = None
39
-
40
- def _prepare_init_task(
41
- self,
42
- task_desc: str,
43
- max_steps: int,
44
- ):
45
- """Prepare task initialization (v2 API does not call server for init).
46
-
47
- Args:
48
- task_desc: Task description
49
- max_steps: Maximum number of steps
50
- """
51
- self.task_id = uuid4().hex
52
- self.task_description = task_desc
53
- self.message_history = []
54
- self.max_steps = max_steps
55
- self.current_step = 0
56
- logger.info(f"Task initialized: '{task_desc}' (max_steps: {max_steps})")
57
-
58
- def _validate_and_increment_step(self):
59
- if not self.task_description:
60
- raise ValueError("Task description must be set. Call init_task() first.")
61
- if self.current_step >= self.max_steps:
62
- raise ValueError(
63
- f"Max steps limit ({self.max_steps}) reached. "
64
- "Call init_task() to start a new task."
65
- )
66
- self.current_step += 1
67
-
68
- def _prepare_step(
69
- self,
70
- screenshot: Image | URL | bytes,
71
- instruction: str | None,
72
- temperature: float | None,
73
- prefix: str = "",
74
- ) -> dict:
75
- self._validate_and_increment_step()
76
- self._log_step_execution(prefix=prefix)
77
-
78
- return {
79
- "model": self.model,
80
- "task_description": self.task_description,
81
- "task_id": self.task_id,
82
- "instruction": instruction,
83
- "messages_history": self.message_history,
84
- "temperature": self._get_temperature(temperature),
85
- **self._prepare_screenshot_kwargs(screenshot),
86
- }
87
-
88
- def _handle_step_error(self, error: Exception, prefix: str = ""):
89
- logger.error(f"Error during {prefix}step execution: {error}")
90
- raise
91
-
92
- def _prepare_screenshot(self, screenshot: Image | bytes) -> bytes:
93
- if isinstance(screenshot, Image):
94
- return screenshot.read()
95
- return screenshot
96
-
97
- def _get_temperature(self, temperature: float | None) -> float | None:
98
- return temperature if temperature is not None else self.temperature
99
-
100
- def _prepare_screenshot_kwargs(self, screenshot: Image | URL | bytes) -> dict:
101
- if isinstance(screenshot, str):
102
- return {"screenshot_url": screenshot}
103
- return {"screenshot": self._prepare_screenshot(screenshot)}
104
-
105
- def _handle_response_message_history(self, response: LLMResponse):
106
- if response.raw_output:
107
- self.message_history.append(
108
- {
109
- "role": "assistant",
110
- "content": [{"type": "text", "text": response.raw_output}],
111
- }
112
- )
113
-
114
- def _build_step_response(self, response: LLMResponse, prefix: str = "") -> Step:
115
- # Update message history with assistant response
116
- self._handle_response_message_history(response)
117
-
118
- result = Step(
119
- reason=response.reason,
120
- actions=response.actions,
121
- stop=response.is_complete,
122
- )
123
-
124
- if response.is_complete:
125
- logger.info(f"{prefix}Task completed.")
126
- else:
127
- logger.debug(f"{prefix}Step completed with {len(response.actions)} actions")
128
-
129
- return result
130
-
131
- def _log_step_execution(self, prefix: str = ""):
132
- logger.debug(f"Executing {prefix}step for task: '{self.task_description}'")
133
-
134
-
135
- class BaseAutoMode:
136
- """Base class with shared auto_mode logic for ShortTask implementations."""
137
-
138
- def _log_auto_mode_start(self, task_desc: str, max_steps: int, prefix: str = ""):
139
- logger.info(
140
- f"Starting {prefix}auto mode for task: '{task_desc}' (max_steps: {max_steps})"
141
- )
142
-
143
- def _log_auto_mode_step(self, step_num: int, max_steps: int, prefix: str = ""):
144
- logger.debug(f"{prefix.capitalize()}auto mode step {step_num}/{max_steps}")
145
-
146
- def _log_auto_mode_actions(self, action_count: int, prefix: str = ""):
147
- verb = "asynchronously" if "async" in prefix else ""
148
- logger.debug(f"Executing {action_count} actions {verb}".strip())
149
-
150
- def _log_auto_mode_completion(self, steps: int, prefix: str = ""):
151
- logger.info(
152
- f"{prefix.capitalize()}auto mode completed successfully after {steps} steps"
153
- )
154
-
155
- def _log_auto_mode_max_steps(self, max_steps: int, prefix: str = ""):
156
- logger.warning(
157
- f"{prefix.capitalize()}auto mode reached max steps ({max_steps}) without completion"
158
- )
@@ -1,70 +0,0 @@
1
- oagi/__init__.py,sha256=xI--F3inDKuNQ2caI4Xx0rdFuUxO24cEeAX6WoGi170,4836
2
- oagi/constants.py,sha256=ZhlY_g3Z8w8njvoVykuGe3nty8A1LoGpRo5oJPh6qS0,1142
3
- oagi/exceptions.py,sha256=Rco37GQTPYUfc2vRO3hozxPF_s8mKFDpFvBg2UKWo3Y,3066
4
- oagi/logging.py,sha256=YT3KCMFj5fzO98R9xlDDgfSotUuz1xRD6OZeYM2rKoo,1760
5
- oagi/agent/__init__.py,sha256=KTVLUMhbjgpTJoOWMUZkkiqwhgumvbOZV2tJ9XCLfao,901
6
- oagi/agent/default.py,sha256=zHcTGyMv5QKE2tqwAsKsN6YyMWeSxCGCMzmv2PHdzMk,4520
7
- oagi/agent/factories.py,sha256=i-GIOEYmwBiiTq4W8UzKfZPkuZcMuOrlc_8dkxM1zLs,2727
8
- oagi/agent/protocol.py,sha256=IQJGiMN4yZIacrh5e9JQsoM9TyHb8wJRQR4LAk8dSA0,1615
9
- oagi/agent/registry.py,sha256=7bMA2-pH3xQ9ZavrHB_mnc2fOGSMeICPbOGtHoM7It0,4851
10
- oagi/agent/observer/__init__.py,sha256=YZ4qvR22pFB0mSDMX6iKKLbBA1dB-nqC7HZVvdMIVGw,909
11
- oagi/agent/observer/agent_observer.py,sha256=fBs4X2_YKhYVThJocjMM-65JAHQSCLJPvzy8OXMt5pY,2864
12
- oagi/agent/observer/events.py,sha256=xc3Z1UGpX69BqhO9cQiGmnRhDZbMYya1kuXm6bXtjWI,625
13
- oagi/agent/observer/exporters.py,sha256=uwVMIvsa5HR4VatvxJscvRErr7sUdjFtR5GOA6xms1w,11830
14
- oagi/agent/observer/protocol.py,sha256=jyRXoCG4CdvaPaDASar1rSbwc7vdpkar39KkGpwf8jw,411
15
- oagi/agent/observer/report_template.html,sha256=NOp280_-P2g_4TYbtqPhYxv-y_x3PwovoDUt_CajdoY,14729
16
- oagi/agent/tasker/__init__.py,sha256=1iTEFe7lzcqh96TL9R0QADPpLJLrUP0shtZ4DlZSv_8,764
17
- oagi/agent/tasker/memory.py,sha256=NR13l5yxRA8GUE-oupAP4W1n80ZNG0SxpUfxsNltkUY,5033
18
- oagi/agent/tasker/models.py,sha256=sMQgwIMKhT1tvVF2yoc1hh8GwEiJ6i6qPMy9WoiA8JM,2137
19
- oagi/agent/tasker/planner.py,sha256=RxDilAGJAaC8gu9EkTwBATDLv7lQlzc3LMyxs0KMR74,14516
20
- oagi/agent/tasker/taskee_agent.py,sha256=MHl_ZH0p8fJ9iSG-VZe_4WUzdyjg4cLZbvEnccQcV2w,17263
21
- oagi/agent/tasker/tasker_agent.py,sha256=P0O4Ned8U0JfMFLWT2JCYXyfuHbU8XziPSotrRuNzMM,11157
22
- oagi/cli/__init__.py,sha256=aDnJViTseShpo5fdGPTj-ELysZhmdvB6Z8mEj2D-_N4,359
23
- oagi/cli/agent.py,sha256=eFwdVZdZcG9ZTMupwoH_JqKSRKDAto3j3z4Xqz5XH7g,10225
24
- oagi/cli/display.py,sha256=Y8_Dn5RIEfRqZUHVGF6URItW0C3XC7bPLWoAmmhvBS0,1829
25
- oagi/cli/main.py,sha256=faHns0HaQCGyylDn2YZLpjQESuEiMYjoQVoMkt8FsH4,2292
26
- oagi/cli/server.py,sha256=JFpzCOeaftITxesz8Ya-_Efs03bgotBg7aYwmMZhPwU,3033
27
- oagi/cli/tracking.py,sha256=TdrAcNq_-OjgXltFCoFc8NsO_k6yHbdzHnMn3vAAvKA,1707
28
- oagi/cli/utils.py,sha256=zIkTrr-ai__3cGSaxiXY-OJs69Fcxd1sHb2FoeyHFtE,3034
29
- oagi/client/__init__.py,sha256=F9DShPUdb6vZYmN1fpM1VYzp4MWqUao_e_R1KYmM4Q4,410
30
- oagi/client/async_.py,sha256=Z8DyQHEl_XAyw1Fs0o3qQzEX9lGlZhqCTSEtQh5XHSw,11204
31
- oagi/client/base.py,sha256=tKYmhJufg7sqEOOp7nn0S9jv4hDYfM-pBuluh0pqew0,16756
32
- oagi/client/sync.py,sha256=CcesgCk_b26v_DF9OKpjfSHKSMjK0N2ywAxwaGnJ4fo,11040
33
- oagi/handler/__init__.py,sha256=Ha11L42K33K3L9S4lQ10UC0DnD5g6egtQUsJpS_tKgg,835
34
- oagi/handler/_macos.py,sha256=aHkp-xGzvWL_SBjuS690i9jf93OITFJfGHzHeYCK65I,1957
35
- oagi/handler/async_pyautogui_action_handler.py,sha256=hQzseR1yBD0QMpgsEVNsUmuApGVAIIyGYD06BXd82Dc,1615
36
- oagi/handler/async_screenshot_maker.py,sha256=8QCtUV59ozpOpvkqhUMb8QDI2qje2gsoFT1qB60tfJM,1689
37
- oagi/handler/pil_image.py,sha256=yUcAoGBL-aZ0PCjSaAmQsDwtyzjldXHqXQp_OYRk6e4,4080
38
- oagi/handler/pyautogui_action_handler.py,sha256=vxSkD_Xsshxb6cfoFFd_zpAwQm21cYTk4w1BGenKZes,10604
39
- oagi/handler/screenshot_maker.py,sha256=j1jTW-awx3vAnb1N5_FIMBC0Z-rNVQbiBP-S6Gh5dlE,1284
40
- oagi/server/__init__.py,sha256=uZx8u3vJUb87kkNzwmmVrgAgbqRu0WxyMIQCLSx56kk,452
41
- oagi/server/agent_wrappers.py,sha256=j8va0A7u80bzOM82nndAplK1uaO_T3kufHWScK6kfWM,3263
42
- oagi/server/config.py,sha256=AJ1PLKuxrc6pRuur1hm5DwG2g2otxPwOCfKgzIACkSk,1691
43
- oagi/server/main.py,sha256=jnTxk7Prc5CzlsUnkBNJp4MOoYN-7HN_Be_m1d3COa8,4829
44
- oagi/server/models.py,sha256=DXjuf5icpCOgCUGMzzoLfRCoreM541KBWKBZnCk5_S0,2688
45
- oagi/server/session_store.py,sha256=319CDqGT9bnqaHK5JiLCG2mKxJmIbq1eH3BpjhWLxdI,3685
46
- oagi/server/socketio_server.py,sha256=0JUf8Y6r9Y7gmltznnsGsEeTp1FhT7AxohSHeBuH3R8,14233
47
- oagi/task/__init__.py,sha256=g_8_7ZLDLKuCGzyrB42OzY3gSOjd_SxzkJW3_pf-PXs,662
48
- oagi/task/async_.py,sha256=12BrdE-51bEz2-PZv5X2VW__I_nwq2K1YxGfD3wFxos,3190
49
- oagi/task/async_short.py,sha256=wVMYpsKGbvqYIe2Ws7cMf8-t7SZKmtrgjW1x_RENMgg,2820
50
- oagi/task/base.py,sha256=6F_nmJsb2Zw6nUibJyAEW0uQBY_jHiQINUbd_jT5wkQ,5696
51
- oagi/task/short.py,sha256=D5VX8QGy0o8W7njy74jx95PxU0Rv2Nvoa-2T17aBaZQ,2629
52
- oagi/task/sync.py,sha256=pKRpIFcetm1n2BgmYGWQeWgV3kKLAQRG9xPlBVQ_pho,3024
53
- oagi/types/__init__.py,sha256=nhxQBaDssygtscetliQa3AaryvuNZhkVmBYsVcuR-qg,1332
54
- oagi/types/action_handler.py,sha256=NH8E-m5qpGqWcXzTSWfF7W0Xdp8SkzJsbhCmQ0B96cg,1075
55
- oagi/types/async_action_handler.py,sha256=k1AaqSkFcXlxwW8sn-w0WFHGsIqHFLbcOPrkknmSVug,1116
56
- oagi/types/async_image_provider.py,sha256=UwDl7VOCA3tiSP5k1fnxK86iEa84Yr57MVaoBSa3hOE,1203
57
- oagi/types/image.py,sha256=KgPCCTJ6D5vHIaGZdbTE7eQEa1WlT6G9tf59ZuUCV2U,537
58
- oagi/types/image_provider.py,sha256=IhKEnwCGZ5l_rO3AvJ6xv5RZMTmTDmqsFRynI9h0R_M,1145
59
- oagi/types/step_observer.py,sha256=wXuChzsof7Rh4azvDTIQ22gAwZAYjMAOVIuL8ZGtw-M,2315
60
- oagi/types/url.py,sha256=Q-1jf5L_4rad4dxyLTg4MXadGgpkH3w4dcoVrVupW-A,54
61
- oagi/types/models/__init__.py,sha256=gnFh4TddritHjT0Chy-4fv3KZIC6bYCUyGmWm_2IuZw,879
62
- oagi/types/models/action.py,sha256=Q14xfYJrj9IsrqxDpEIzd6iWS-gLmNHfIX6Ef8k0O9E,2497
63
- oagi/types/models/client.py,sha256=1xIKBgLSheHfqYbcyRKMDOLQJaKijaKQ5l-COc6e7_k,1471
64
- oagi/types/models/image_config.py,sha256=tl6abVg_-IAPLwpaWprgknXu7wRWriMg-AEVyUX73v0,1567
65
- oagi/types/models/step.py,sha256=RSI4H_2rrUBq_xyCoWKaq7JHdJWNobtQppaKC1l0aWU,471
66
- oagi_core-0.10.3.dist-info/METADATA,sha256=XvsZ9dqWB1fDxdazYcT5u8-k9aeKqZBmtmmm_x0JEMo,8269
67
- oagi_core-0.10.3.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
68
- oagi_core-0.10.3.dist-info/entry_points.txt,sha256=zzgsOSWX6aN3KUB0Z1it8DMxFFBJBqmZVqMVAJRjYuw,44
69
- oagi_core-0.10.3.dist-info/licenses/LICENSE,sha256=sy5DLA2M29jFT4UfWsuBF9BAr3FnRkYtnAu6oDZiIf8,1075
70
- oagi_core-0.10.3.dist-info/RECORD,,