oagi-core 0.11.0__py3-none-any.whl → 0.12.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: oagi-core
3
- Version: 0.11.0
3
+ Version: 0.12.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>
@@ -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
 
@@ -272,6 +318,7 @@ See [`examples/socketio_client_example.py`](examples/socketio_client_example.py)
272
318
 
273
319
  ## Documentation
274
320
 
321
+ For full Lux documentation and guides, visit the [OAGI Developer Documentation](https://developer.agiopen.org/docs/index).
275
322
 
276
323
  ## License
277
324
 
@@ -1,24 +1,30 @@
1
- oagi/__init__.py,sha256=xI--F3inDKuNQ2caI4Xx0rdFuUxO24cEeAX6WoGi170,4836
2
- oagi/constants.py,sha256=ZhlY_g3Z8w8njvoVykuGe3nty8A1LoGpRo5oJPh6qS0,1142
1
+ oagi/__init__.py,sha256=hKfGbbvYFNoc8LsTd34aM6Uj-nGEJ0J8JbceXZP5xZ0,4801
2
+ oagi/constants.py,sha256=ywyMimjh15tC5p4MBZjkJIqOVElPRS50iJtrPE3VClw,1211
3
3
  oagi/exceptions.py,sha256=Rco37GQTPYUfc2vRO3hozxPF_s8mKFDpFvBg2UKWo3Y,3066
4
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
5
11
  oagi/agent/__init__.py,sha256=KTVLUMhbjgpTJoOWMUZkkiqwhgumvbOZV2tJ9XCLfao,901
6
- oagi/agent/default.py,sha256=Ers1Dk6BX-s24ZZXOfiXt9wsilx_LHuTNgi3Yj7Hin4,4653
12
+ oagi/agent/default.py,sha256=Ax05kBa8Fb14Ev8wd9LS6xkF65grf6qdxxTlgpkkDuk,4715
7
13
  oagi/agent/factories.py,sha256=syi_EOlU4SUjo-0CKaML8eIPu3ToUEKua2VHp9lvNF0,5839
8
14
  oagi/agent/protocol.py,sha256=IQJGiMN4yZIacrh5e9JQsoM9TyHb8wJRQR4LAk8dSA0,1615
9
15
  oagi/agent/registry.py,sha256=7bMA2-pH3xQ9ZavrHB_mnc2fOGSMeICPbOGtHoM7It0,4851
10
16
  oagi/agent/observer/__init__.py,sha256=YZ4qvR22pFB0mSDMX6iKKLbBA1dB-nqC7HZVvdMIVGw,909
11
17
  oagi/agent/observer/agent_observer.py,sha256=fBs4X2_YKhYVThJocjMM-65JAHQSCLJPvzy8OXMt5pY,2864
12
18
  oagi/agent/observer/events.py,sha256=xc3Z1UGpX69BqhO9cQiGmnRhDZbMYya1kuXm6bXtjWI,625
13
- oagi/agent/observer/exporters.py,sha256=uwVMIvsa5HR4VatvxJscvRErr7sUdjFtR5GOA6xms1w,11830
19
+ oagi/agent/observer/exporters.py,sha256=HeEE5bmWjgOATLkh1R-m1P7f1Ztb58BHk6xbxdsdxCw,12153
14
20
  oagi/agent/observer/protocol.py,sha256=jyRXoCG4CdvaPaDASar1rSbwc7vdpkar39KkGpwf8jw,411
15
- oagi/agent/observer/report_template.html,sha256=NOp280_-P2g_4TYbtqPhYxv-y_x3PwovoDUt_CajdoY,14729
21
+ oagi/agent/observer/report_template.html,sha256=HtvJLh3swTMfmIw4XyGFqquS4vjP9iOe5L2tTnOKpzY,15388
16
22
  oagi/agent/tasker/__init__.py,sha256=1iTEFe7lzcqh96TL9R0QADPpLJLrUP0shtZ4DlZSv_8,764
17
23
  oagi/agent/tasker/memory.py,sha256=NR13l5yxRA8GUE-oupAP4W1n80ZNG0SxpUfxsNltkUY,5033
18
24
  oagi/agent/tasker/models.py,sha256=sMQgwIMKhT1tvVF2yoc1hh8GwEiJ6i6qPMy9WoiA8JM,2137
19
- oagi/agent/tasker/planner.py,sha256=nSOOcB4NzrOONFhfNvYzxxrelU5NxpbLMpC7B5Q-L-k,15211
20
- oagi/agent/tasker/taskee_agent.py,sha256=jYG-c36zbhDM3EEt6-YzLlk-K6n7mjFNquEd6BPaRvw,17867
21
- oagi/agent/tasker/tasker_agent.py,sha256=kbWvvRVS12S8eFd0PRszFrcSSWRzz_f6Jd7LuaRcwJQ,11285
25
+ oagi/agent/tasker/planner.py,sha256=q6IvH6sfU2kYX1NcC9VHjGaQ0X9jF18yjuAYXisNCg0,15489
26
+ oagi/agent/tasker/taskee_agent.py,sha256=OugYJbTbFKxgNjbIyQBBH4Zm5u5PuWN1F6R81_eIro8,18090
27
+ oagi/agent/tasker/tasker_agent.py,sha256=yb0BdQzJyAPpK3njHPWgQruV8zpUGBXn1WjOGEMIO-g,11291
22
28
  oagi/cli/__init__.py,sha256=aDnJViTseShpo5fdGPTj-ELysZhmdvB6Z8mEj2D-_N4,359
23
29
  oagi/cli/agent.py,sha256=fd7WtR5zoRJmyHDr67zfBvEX-_BLIjPbBqp-dhy4AAk,11061
24
30
  oagi/cli/display.py,sha256=Y8_Dn5RIEfRqZUHVGF6URItW0C3XC7bPLWoAmmhvBS0,1829
@@ -27,10 +33,10 @@ oagi/cli/server.py,sha256=JFpzCOeaftITxesz8Ya-_Efs03bgotBg7aYwmMZhPwU,3033
27
33
  oagi/cli/tracking.py,sha256=TdrAcNq_-OjgXltFCoFc8NsO_k6yHbdzHnMn3vAAvKA,1707
28
34
  oagi/cli/utils.py,sha256=zIkTrr-ai__3cGSaxiXY-OJs69Fcxd1sHb2FoeyHFtE,3034
29
35
  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=vEUvyiUvTRf1GE4vTiz_bQjLv3psdmHyt0mfKJHq24M,1247
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=Ec5zhBSfJQmOUT8s6Mr8pN2g8ILY0uNYuX4M23vzfhs,1938
34
40
  oagi/handler/_macos.py,sha256=Gs8GrhA_WAyv9Yw0D41duliP32Xk6vouyMeWjWJJT90,5187
35
41
  oagi/handler/_windows.py,sha256=MSgPDYEOetSjbn9eJDSrdzBVlUGgGsTlegaTDc4C4Ss,2828
36
42
  oagi/handler/async_pyautogui_action_handler.py,sha256=wfNRBBURZnwQkNTcs9OPMmFJIAPtnXmcqxWbjda_q7I,1863
@@ -39,6 +45,7 @@ oagi/handler/capslock_manager.py,sha256=40LzWt1_1wbncF5koUTdbd9V3eo5Ex_mEWwjtEmH
39
45
  oagi/handler/pil_image.py,sha256=yUcAoGBL-aZ0PCjSaAmQsDwtyzjldXHqXQp_OYRk6e4,4080
40
46
  oagi/handler/pyautogui_action_handler.py,sha256=BVmpKuYAMINJ5Ue_PK_WxFScAqLeyXC64g4NWQUtG_M,10146
41
47
  oagi/handler/screenshot_maker.py,sha256=j1jTW-awx3vAnb1N5_FIMBC0Z-rNVQbiBP-S6Gh5dlE,1284
48
+ oagi/handler/utils.py,sha256=jj10z-v4_LUuVb8aClyXkUfZVEaqsWgi3be4t3Gw7oI,697
42
49
  oagi/server/__init__.py,sha256=uZx8u3vJUb87kkNzwmmVrgAgbqRu0WxyMIQCLSx56kk,452
43
50
  oagi/server/agent_wrappers.py,sha256=j8va0A7u80bzOM82nndAplK1uaO_T3kufHWScK6kfWM,3263
44
51
  oagi/server/config.py,sha256=AJ1PLKuxrc6pRuur1hm5DwG2g2otxPwOCfKgzIACkSk,1691
@@ -46,27 +53,25 @@ oagi/server/main.py,sha256=jnTxk7Prc5CzlsUnkBNJp4MOoYN-7HN_Be_m1d3COa8,4829
46
53
  oagi/server/models.py,sha256=DXjuf5icpCOgCUGMzzoLfRCoreM541KBWKBZnCk5_S0,2688
47
54
  oagi/server/session_store.py,sha256=l7t31rNWuZkIPLnaqrllVusHkJkE8j50PMfyb1di9mI,3750
48
55
  oagi/server/socketio_server.py,sha256=8RRf8mAmsArOX2nWylT0g5T5On0gzMod0TWRmk0vrgA,14218
49
- oagi/task/__init__.py,sha256=g_8_7ZLDLKuCGzyrB42OzY3gSOjd_SxzkJW3_pf-PXs,662
50
- oagi/task/async_.py,sha256=12BrdE-51bEz2-PZv5X2VW__I_nwq2K1YxGfD3wFxos,3190
51
- oagi/task/async_short.py,sha256=wVMYpsKGbvqYIe2Ws7cMf8-t7SZKmtrgjW1x_RENMgg,2820
52
- oagi/task/base.py,sha256=6F_nmJsb2Zw6nUibJyAEW0uQBY_jHiQINUbd_jT5wkQ,5696
53
- oagi/task/short.py,sha256=D5VX8QGy0o8W7njy74jx95PxU0Rv2Nvoa-2T17aBaZQ,2629
54
- oagi/task/sync.py,sha256=pKRpIFcetm1n2BgmYGWQeWgV3kKLAQRG9xPlBVQ_pho,3024
56
+ oagi/task/__init__.py,sha256=8l3z5nxA3RtGHP94Iu4ot1Wo3Lx-U7_Led2CsVwYINg,760
55
57
  oagi/types/__init__.py,sha256=_UyzzRnoKvp00BUBjxW9Tv3_xBNf8Lxb2PUC2DkjOkg,1384
56
58
  oagi/types/action_handler.py,sha256=NH8E-m5qpGqWcXzTSWfF7W0Xdp8SkzJsbhCmQ0B96cg,1075
57
59
  oagi/types/async_action_handler.py,sha256=k1AaqSkFcXlxwW8sn-w0WFHGsIqHFLbcOPrkknmSVug,1116
58
60
  oagi/types/async_image_provider.py,sha256=UwDl7VOCA3tiSP5k1fnxK86iEa84Yr57MVaoBSa3hOE,1203
59
61
  oagi/types/image.py,sha256=KgPCCTJ6D5vHIaGZdbTE7eQEa1WlT6G9tf59ZuUCV2U,537
60
62
  oagi/types/image_provider.py,sha256=IhKEnwCGZ5l_rO3AvJ6xv5RZMTmTDmqsFRynI9h0R_M,1145
61
- oagi/types/step_observer.py,sha256=wXuChzsof7Rh4azvDTIQ22gAwZAYjMAOVIuL8ZGtw-M,2315
63
+ oagi/types/step_observer.py,sha256=E7igVqpOeoizUkhXbGRRX80ZOuqoM-zcRyjNyOXwWc8,2380
62
64
  oagi/types/url.py,sha256=145jLl3yecFBVKhJDbrR63C48D3l9_w0kpA_8C_gM78,868
63
- oagi/types/models/__init__.py,sha256=gnFh4TddritHjT0Chy-4fv3KZIC6bYCUyGmWm_2IuZw,879
64
- oagi/types/models/action.py,sha256=Q14xfYJrj9IsrqxDpEIzd6iWS-gLmNHfIX6Ef8k0O9E,2497
65
- oagi/types/models/client.py,sha256=1xIKBgLSheHfqYbcyRKMDOLQJaKijaKQ5l-COc6e7_k,1471
65
+ oagi/types/models/__init__.py,sha256=VcNrVQvw9p8igBunOv3LQBPnRpp5WEcWBf1Nr9FGkeI,843
66
+ oagi/types/models/action.py,sha256=s3oPBCtbVAmavArjFZBEbL71QyW_akUrXpEDJuHqkYI,2583
67
+ oagi/types/models/client.py,sha256=5fUZVTPviTunoh2KXM3jmLPtPIrvPwrr8o2bR6Phj5M,1156
66
68
  oagi/types/models/image_config.py,sha256=tl6abVg_-IAPLwpaWprgknXu7wRWriMg-AEVyUX73v0,1567
67
69
  oagi/types/models/step.py,sha256=RSI4H_2rrUBq_xyCoWKaq7JHdJWNobtQppaKC1l0aWU,471
68
- oagi_core-0.11.0.dist-info/METADATA,sha256=y251pGqY3CfcN4umrr21EEMTUTRzvYUQXkruKv6d-e4,9497
69
- oagi_core-0.11.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
70
- oagi_core-0.11.0.dist-info/entry_points.txt,sha256=zzgsOSWX6aN3KUB0Z1it8DMxFFBJBqmZVqMVAJRjYuw,44
71
- oagi_core-0.11.0.dist-info/licenses/LICENSE,sha256=sy5DLA2M29jFT4UfWsuBF9BAr3FnRkYtnAu6oDZiIf8,1075
72
- oagi_core-0.11.0.dist-info/RECORD,,
70
+ oagi/utils/__init__.py,sha256=vHXyX66hEsf33OJJkmZSUjaTYU0UngfbtjcZgxfOj3A,441
71
+ oagi/utils/output_parser.py,sha256=U7vzmoD8pyzDg23z3vy-L9a_jKPsAlr3x8lIdPszrY8,5322
72
+ oagi/utils/prompt_builder.py,sha256=_Q1HY82YUrq3jSCTZ3Rszu3qmI3Wn_fmq8hf14NuwQM,2180
73
+ oagi_core-0.12.1.dist-info/METADATA,sha256=Qs8cvjTBeZCrlCh7DNc-Ai3oyFgw2NlsE60oab-vccE,12176
74
+ oagi_core-0.12.1.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
75
+ oagi_core-0.12.1.dist-info/entry_points.txt,sha256=zzgsOSWX6aN3KUB0Z1it8DMxFFBJBqmZVqMVAJRjYuw,44
76
+ oagi_core-0.12.1.dist-info/licenses/LICENSE,sha256=sy5DLA2M29jFT4UfWsuBF9BAr3FnRkYtnAu6oDZiIf8,1075
77
+ oagi_core-0.12.1.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
- )