oagi-core 0.9.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 (60) hide show
  1. oagi/__init__.py +108 -0
  2. oagi/agent/__init__.py +31 -0
  3. oagi/agent/default.py +75 -0
  4. oagi/agent/factories.py +50 -0
  5. oagi/agent/protocol.py +55 -0
  6. oagi/agent/registry.py +155 -0
  7. oagi/agent/tasker/__init__.py +35 -0
  8. oagi/agent/tasker/memory.py +184 -0
  9. oagi/agent/tasker/models.py +83 -0
  10. oagi/agent/tasker/planner.py +385 -0
  11. oagi/agent/tasker/taskee_agent.py +395 -0
  12. oagi/agent/tasker/tasker_agent.py +323 -0
  13. oagi/async_pyautogui_action_handler.py +44 -0
  14. oagi/async_screenshot_maker.py +47 -0
  15. oagi/async_single_step.py +85 -0
  16. oagi/cli/__init__.py +11 -0
  17. oagi/cli/agent.py +125 -0
  18. oagi/cli/main.py +77 -0
  19. oagi/cli/server.py +94 -0
  20. oagi/cli/utils.py +82 -0
  21. oagi/client/__init__.py +12 -0
  22. oagi/client/async_.py +293 -0
  23. oagi/client/base.py +465 -0
  24. oagi/client/sync.py +296 -0
  25. oagi/exceptions.py +118 -0
  26. oagi/logging.py +47 -0
  27. oagi/pil_image.py +102 -0
  28. oagi/pyautogui_action_handler.py +268 -0
  29. oagi/screenshot_maker.py +41 -0
  30. oagi/server/__init__.py +13 -0
  31. oagi/server/agent_wrappers.py +98 -0
  32. oagi/server/config.py +46 -0
  33. oagi/server/main.py +157 -0
  34. oagi/server/models.py +98 -0
  35. oagi/server/session_store.py +116 -0
  36. oagi/server/socketio_server.py +405 -0
  37. oagi/single_step.py +87 -0
  38. oagi/task/__init__.py +14 -0
  39. oagi/task/async_.py +97 -0
  40. oagi/task/async_short.py +64 -0
  41. oagi/task/base.py +121 -0
  42. oagi/task/short.py +64 -0
  43. oagi/task/sync.py +97 -0
  44. oagi/types/__init__.py +28 -0
  45. oagi/types/action_handler.py +30 -0
  46. oagi/types/async_action_handler.py +30 -0
  47. oagi/types/async_image_provider.py +37 -0
  48. oagi/types/image.py +17 -0
  49. oagi/types/image_provider.py +34 -0
  50. oagi/types/models/__init__.py +32 -0
  51. oagi/types/models/action.py +33 -0
  52. oagi/types/models/client.py +64 -0
  53. oagi/types/models/image_config.py +47 -0
  54. oagi/types/models/step.py +17 -0
  55. oagi/types/url_image.py +47 -0
  56. oagi_core-0.9.0.dist-info/METADATA +257 -0
  57. oagi_core-0.9.0.dist-info/RECORD +60 -0
  58. oagi_core-0.9.0.dist-info/WHEEL +4 -0
  59. oagi_core-0.9.0.dist-info/entry_points.txt +2 -0
  60. oagi_core-0.9.0.dist-info/licenses/LICENSE +21 -0
oagi/task/__init__.py ADDED
@@ -0,0 +1,14 @@
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 .async_ import AsyncTask
10
+ from .async_short import AsyncShortTask
11
+ from .short import ShortTask
12
+ from .sync import Task
13
+
14
+ __all__ = ["Task", "AsyncTask", "ShortTask", "AsyncShortTask"]
oagi/task/async_.py ADDED
@@ -0,0 +1,97 @@
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 ..client import AsyncClient
10
+ from ..logging import get_logger
11
+ from ..types import Image, Step
12
+ from .base import BaseTask
13
+
14
+ logger = get_logger("async_task")
15
+
16
+
17
+ class AsyncTask(BaseTask):
18
+ """Async base class for task automation with the OAGI API."""
19
+
20
+ def __init__(
21
+ self,
22
+ api_key: str | None = None,
23
+ base_url: str | None = None,
24
+ model: str = "vision-model-v1",
25
+ temperature: float | None = None,
26
+ ):
27
+ super().__init__(api_key, base_url, model, temperature)
28
+ self.client = AsyncClient(base_url=base_url, api_key=api_key)
29
+ self.api_key = self.client.api_key
30
+ self.base_url = self.client.base_url
31
+
32
+ async def init_task(
33
+ self,
34
+ task_desc: str,
35
+ max_steps: int = 5,
36
+ ):
37
+ """Initialize a new task with the given description.
38
+
39
+ Args:
40
+ task_desc: Task description
41
+ max_steps: Maximum number of steps (for logging)
42
+ """
43
+ self._prepare_init_task(task_desc, max_steps)
44
+
45
+ async def step(
46
+ self,
47
+ screenshot: Image | bytes,
48
+ instruction: str | None = None,
49
+ temperature: float | None = None,
50
+ ) -> Step:
51
+ """Send screenshot to the server and get the next actions.
52
+
53
+ Args:
54
+ screenshot: Screenshot as Image object or raw bytes
55
+ instruction: Optional additional instruction for this step
56
+ temperature: Sampling temperature for this step (overrides task default if provided)
57
+
58
+ Returns:
59
+ Step: The actions and reasoning for this step
60
+ """
61
+ self._validate_step_preconditions()
62
+ self._log_step_execution(prefix="async ")
63
+
64
+ try:
65
+ # Use provided temperature or fall back to task default
66
+ temp = self._get_temperature(temperature)
67
+
68
+ # Prepare screenshot kwargs (handles URLImage vs bytes/Image)
69
+ screenshot_kwargs = self._prepare_screenshot_kwargs(screenshot)
70
+
71
+ # Call API with dynamically determined screenshot argument
72
+ response = await self.client.create_message(
73
+ model=self.model,
74
+ task_description=self.task_description,
75
+ task_id=self.task_id,
76
+ instruction=instruction,
77
+ messages_history=self.message_history,
78
+ temperature=temp,
79
+ **screenshot_kwargs,
80
+ )
81
+
82
+ # Convert API response to Step (also updates message_history)
83
+ return self._build_step_response(response, prefix="Async ")
84
+
85
+ except Exception as e:
86
+ logger.error(f"Error during async step execution: {e}")
87
+ raise
88
+
89
+ async def close(self):
90
+ """Close the underlying HTTP client to free resources."""
91
+ await self.client.close()
92
+
93
+ async def __aenter__(self):
94
+ return self
95
+
96
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
97
+ await self.close()
@@ -0,0 +1,64 @@
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 ..logging import get_logger
10
+ from ..types import AsyncActionHandler, AsyncImageProvider
11
+ from .async_ import AsyncTask
12
+ from .base import BaseAutoMode
13
+
14
+ logger = get_logger("async_short_task")
15
+
16
+
17
+ class AsyncShortTask(AsyncTask, BaseAutoMode):
18
+ """Async task implementation with automatic mode for short-duration tasks."""
19
+
20
+ def __init__(
21
+ self,
22
+ api_key: str | None = None,
23
+ base_url: str | None = None,
24
+ model: str = "vision-model-v1",
25
+ temperature: float | None = None,
26
+ ):
27
+ super().__init__(
28
+ api_key=api_key, base_url=base_url, model=model, temperature=temperature
29
+ )
30
+
31
+ async def auto_mode(
32
+ self,
33
+ task_desc: str,
34
+ max_steps: int = 5,
35
+ executor: AsyncActionHandler = None,
36
+ image_provider: AsyncImageProvider = None,
37
+ temperature: float | None = None,
38
+ ) -> bool:
39
+ """Run the task in automatic mode with the provided executor and image provider.
40
+
41
+ Args:
42
+ task_desc: Task description
43
+ max_steps: Maximum number of steps
44
+ executor: Async handler to execute actions
45
+ image_provider: Async provider for screenshots
46
+ temperature: Sampling temperature for all steps (overrides task default if provided)
47
+ """
48
+ self._log_auto_mode_start(task_desc, max_steps, prefix="async ")
49
+
50
+ await self.init_task(task_desc, max_steps=max_steps)
51
+
52
+ for i in range(max_steps):
53
+ self._log_auto_mode_step(i + 1, max_steps, prefix="async ")
54
+ image = await image_provider()
55
+ step = await self.step(image, temperature=temperature)
56
+ if executor:
57
+ self._log_auto_mode_actions(len(step.actions), prefix="async ")
58
+ await executor(step.actions)
59
+ if step.stop:
60
+ self._log_auto_mode_completion(i + 1, prefix="async ")
61
+ return True
62
+
63
+ self._log_auto_mode_max_steps(max_steps, prefix="async ")
64
+ return False
oagi/task/base.py ADDED
@@ -0,0 +1,121 @@
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 ..logging import get_logger
12
+ from ..types import Image, Step, URLImage
13
+ from ..types.models import LLMResponse
14
+
15
+ logger = get_logger("task.base")
16
+
17
+
18
+ class BaseTask:
19
+ """Base class with shared task management logic for sync/async tasks."""
20
+
21
+ def __init__(
22
+ self,
23
+ api_key: str | None,
24
+ base_url: str | None,
25
+ model: str,
26
+ temperature: float | None,
27
+ ):
28
+ self.task_id: str = uuid4().hex # Client-side generated UUID
29
+ self.task_description: str | None = None
30
+ self.model = model
31
+ self.temperature = temperature
32
+ self.message_history: list = [] # OpenAI-compatible message history
33
+ # Client will be set by subclasses
34
+ self.api_key: str | None = None
35
+ self.base_url: str | None = None
36
+
37
+ def _prepare_init_task(
38
+ self,
39
+ task_desc: str,
40
+ max_steps: int,
41
+ ):
42
+ """Prepare task initialization (v2 API does not call server for init).
43
+
44
+ Args:
45
+ task_desc: Task description
46
+ max_steps: Maximum number of steps
47
+ """
48
+ self.task_description = task_desc
49
+ logger.info(f"Task initialized: '{task_desc}' (max_steps: {max_steps})")
50
+
51
+ def _validate_step_preconditions(self):
52
+ if not self.task_description:
53
+ raise ValueError("Task description must be set. Call init_task() first.")
54
+
55
+ def _prepare_screenshot(self, screenshot: Image | bytes) -> bytes:
56
+ if isinstance(screenshot, Image):
57
+ return screenshot.read()
58
+ return screenshot
59
+
60
+ def _get_temperature(self, temperature: float | None) -> float | None:
61
+ return temperature if temperature is not None else self.temperature
62
+
63
+ def _prepare_screenshot_kwargs(self, screenshot: Image | bytes) -> dict:
64
+ if isinstance(screenshot, URLImage):
65
+ return {"screenshot_url": screenshot.get_url()}
66
+ return {"screenshot": self._prepare_screenshot(screenshot)}
67
+
68
+ def _handle_response_message_history(self, response: LLMResponse):
69
+ if response.raw_output:
70
+ self.message_history.append(
71
+ {
72
+ "role": "assistant",
73
+ "content": [{"type": "text", "text": response.raw_output}],
74
+ }
75
+ )
76
+
77
+ def _build_step_response(self, response: LLMResponse, prefix: str = "") -> Step:
78
+ # Update message history with assistant response
79
+ self._handle_response_message_history(response)
80
+
81
+ result = Step(
82
+ reason=response.reason,
83
+ actions=response.actions,
84
+ stop=response.is_complete,
85
+ )
86
+
87
+ if response.is_complete:
88
+ logger.info(f"{prefix}Task completed.")
89
+ else:
90
+ logger.debug(f"{prefix}Step completed with {len(response.actions)} actions")
91
+
92
+ return result
93
+
94
+ def _log_step_execution(self, prefix: str = ""):
95
+ logger.debug(f"Executing {prefix}step for task: '{self.task_description}'")
96
+
97
+
98
+ class BaseAutoMode:
99
+ """Base class with shared auto_mode logic for ShortTask implementations."""
100
+
101
+ def _log_auto_mode_start(self, task_desc: str, max_steps: int, prefix: str = ""):
102
+ logger.info(
103
+ f"Starting {prefix}auto mode for task: '{task_desc}' (max_steps: {max_steps})"
104
+ )
105
+
106
+ def _log_auto_mode_step(self, step_num: int, max_steps: int, prefix: str = ""):
107
+ logger.debug(f"{prefix.capitalize()}auto mode step {step_num}/{max_steps}")
108
+
109
+ def _log_auto_mode_actions(self, action_count: int, prefix: str = ""):
110
+ verb = "asynchronously" if "async" in prefix else ""
111
+ logger.debug(f"Executing {action_count} actions {verb}".strip())
112
+
113
+ def _log_auto_mode_completion(self, steps: int, prefix: str = ""):
114
+ logger.info(
115
+ f"{prefix.capitalize()}auto mode completed successfully after {steps} steps"
116
+ )
117
+
118
+ def _log_auto_mode_max_steps(self, max_steps: int, prefix: str = ""):
119
+ logger.warning(
120
+ f"{prefix.capitalize()}auto mode reached max steps ({max_steps}) without completion"
121
+ )
oagi/task/short.py ADDED
@@ -0,0 +1,64 @@
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 ..logging import get_logger
10
+ from ..types import ActionHandler, ImageProvider
11
+ from .base import BaseAutoMode
12
+ from .sync import Task
13
+
14
+ logger = get_logger("short_task")
15
+
16
+
17
+ class ShortTask(Task, BaseAutoMode):
18
+ """Task implementation with automatic mode for short-duration tasks."""
19
+
20
+ def __init__(
21
+ self,
22
+ api_key: str | None = None,
23
+ base_url: str | None = None,
24
+ model: str = "vision-model-v1",
25
+ temperature: float | None = None,
26
+ ):
27
+ super().__init__(
28
+ api_key=api_key, base_url=base_url, model=model, temperature=temperature
29
+ )
30
+
31
+ def auto_mode(
32
+ self,
33
+ task_desc: str,
34
+ max_steps: int = 5,
35
+ executor: ActionHandler = None,
36
+ image_provider: ImageProvider = None,
37
+ temperature: float | None = None,
38
+ ) -> bool:
39
+ """Run the task in automatic mode with the provided executor and image provider.
40
+
41
+ Args:
42
+ task_desc: Task description
43
+ max_steps: Maximum number of steps
44
+ executor: Handler to execute actions
45
+ image_provider: Provider for screenshots
46
+ temperature: Sampling temperature for all steps (overrides task default if provided)
47
+ """
48
+ self._log_auto_mode_start(task_desc, max_steps)
49
+
50
+ self.init_task(task_desc, max_steps=max_steps)
51
+
52
+ for i in range(max_steps):
53
+ self._log_auto_mode_step(i + 1, max_steps)
54
+ image = image_provider()
55
+ step = self.step(image, temperature=temperature)
56
+ if executor:
57
+ self._log_auto_mode_actions(len(step.actions))
58
+ executor(step.actions)
59
+ if step.stop:
60
+ self._log_auto_mode_completion(i + 1)
61
+ return True
62
+
63
+ self._log_auto_mode_max_steps(max_steps)
64
+ return False
oagi/task/sync.py ADDED
@@ -0,0 +1,97 @@
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 ..client import SyncClient
10
+ from ..logging import get_logger
11
+ from ..types import Image, Step
12
+ from .base import BaseTask
13
+
14
+ logger = get_logger("task")
15
+
16
+
17
+ class Task(BaseTask):
18
+ """Base class for task automation with the OAGI API."""
19
+
20
+ def __init__(
21
+ self,
22
+ api_key: str | None = None,
23
+ base_url: str | None = None,
24
+ model: str = "vision-model-v1",
25
+ temperature: float | None = None,
26
+ ):
27
+ super().__init__(api_key, base_url, model, temperature)
28
+ self.client = SyncClient(base_url=base_url, api_key=api_key)
29
+ self.api_key = self.client.api_key
30
+ self.base_url = self.client.base_url
31
+
32
+ def init_task(
33
+ self,
34
+ task_desc: str,
35
+ max_steps: int = 5,
36
+ ):
37
+ """Initialize a new task with the given description.
38
+
39
+ Args:
40
+ task_desc: Task description
41
+ max_steps: Maximum number of steps (for logging)
42
+ """
43
+ self._prepare_init_task(task_desc, max_steps)
44
+
45
+ def step(
46
+ self,
47
+ screenshot: Image | bytes,
48
+ instruction: str | None = None,
49
+ temperature: float | None = None,
50
+ ) -> Step:
51
+ """Send screenshot to the server and get the next actions.
52
+
53
+ Args:
54
+ screenshot: Screenshot as Image object or raw bytes
55
+ instruction: Optional additional instruction for this step
56
+ temperature: Sampling temperature for this step (overrides task default if provided)
57
+
58
+ Returns:
59
+ Step: The actions and reasoning for this step
60
+ """
61
+ self._validate_step_preconditions()
62
+ self._log_step_execution()
63
+
64
+ try:
65
+ # Use provided temperature or fall back to task default
66
+ temp = self._get_temperature(temperature)
67
+
68
+ # Prepare screenshot kwargs (handles URLImage vs bytes/Image)
69
+ screenshot_kwargs = self._prepare_screenshot_kwargs(screenshot)
70
+
71
+ # Call API with dynamically determined screenshot argument
72
+ response = self.client.create_message(
73
+ model=self.model,
74
+ task_description=self.task_description,
75
+ task_id=self.task_id,
76
+ instruction=instruction,
77
+ messages_history=self.message_history,
78
+ temperature=temp,
79
+ **screenshot_kwargs,
80
+ )
81
+
82
+ # Convert API response to Step (also updates message_history)
83
+ return self._build_step_response(response)
84
+
85
+ except Exception as e:
86
+ logger.error(f"Error during step execution: {e}")
87
+ raise
88
+
89
+ def close(self):
90
+ """Close the underlying HTTP client to free resources."""
91
+ self.client.close()
92
+
93
+ def __enter__(self):
94
+ return self
95
+
96
+ def __exit__(self, exc_type, exc_val, exc_tb):
97
+ self.close()
oagi/types/__init__.py ADDED
@@ -0,0 +1,28 @@
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 .action_handler import ActionHandler
10
+ from .async_action_handler import AsyncActionHandler
11
+ from .async_image_provider import AsyncImageProvider
12
+ from .image import Image
13
+ from .image_provider import ImageProvider
14
+ from .models import Action, ActionType, ImageConfig, Step
15
+ from .url_image import URLImage
16
+
17
+ __all__ = [
18
+ "Action",
19
+ "ActionType",
20
+ "Image",
21
+ "ImageConfig",
22
+ "Step",
23
+ "ActionHandler",
24
+ "AsyncActionHandler",
25
+ "ImageProvider",
26
+ "AsyncImageProvider",
27
+ "URLImage",
28
+ ]
@@ -0,0 +1,30 @@
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 typing import Protocol
10
+
11
+ from .models import Action
12
+
13
+
14
+ class ActionHandler(Protocol):
15
+ def __call__(self, actions: list[Action]) -> None:
16
+ """
17
+ Executes a list of actions.
18
+
19
+ This method takes a list of `Action` objects and executes them. It is used
20
+ to perform operations represented by the `Action` instances. This method
21
+ does not return any value and modifies the system based on the input actions.
22
+
23
+ Parameters:
24
+ actions (list[Action]): A list of `Action` objects to be executed. Each
25
+ `Action` must encapsulate the logic that is intended to be applied
26
+ during the call.
27
+
28
+ Raises:
29
+ RuntimeError: If an error occurs during the execution of the actions.
30
+ """
@@ -0,0 +1,30 @@
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 typing import Protocol
10
+
11
+ from .models import Action
12
+
13
+
14
+ class AsyncActionHandler(Protocol):
15
+ async def __call__(self, actions: list[Action]) -> None:
16
+ """
17
+ Asynchronously executes a list of actions.
18
+
19
+ This method takes a list of `Action` objects and executes them asynchronously.
20
+ It is used to perform operations represented by the `Action` instances. This
21
+ method does not return any value and modifies the system based on the input actions.
22
+
23
+ Parameters:
24
+ actions (list[Action]): A list of `Action` objects to be executed. Each
25
+ `Action` must encapsulate the logic that is intended to be applied
26
+ during the call.
27
+
28
+ Raises:
29
+ RuntimeError: If an error occurs during the execution of the actions.
30
+ """
@@ -0,0 +1,37 @@
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 typing import Protocol
10
+
11
+ from .image import Image
12
+
13
+
14
+ class AsyncImageProvider(Protocol):
15
+ async def __call__(self) -> Image:
16
+ """
17
+ Asynchronously provides an image.
18
+
19
+ This method is responsible for asynchronously capturing, generating, or retrieving
20
+ an image that can be used for task execution or analysis. The method should return
21
+ an object that implements the Image protocol.
22
+
23
+ Returns:
24
+ Image: An object implementing the Image protocol that represents
25
+ the captured or generated image.
26
+
27
+ Raises:
28
+ RuntimeError: If an error occurs during image capture or generation.
29
+ """
30
+
31
+ async def last_image(self) -> Image:
32
+ """
33
+ Asynchronously returns the last captured image.
34
+
35
+ Returns:
36
+ Image: The last captured image.
37
+ """
oagi/types/image.py ADDED
@@ -0,0 +1,17 @@
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 typing import Protocol, runtime_checkable
10
+
11
+
12
+ @runtime_checkable
13
+ class Image(Protocol):
14
+ """Protocol for image objects that can be read as bytes."""
15
+
16
+ def read(self) -> bytes:
17
+ """Read the image data as bytes."""
@@ -0,0 +1,34 @@
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 typing import Protocol
10
+
11
+ from .image import Image
12
+
13
+
14
+ class ImageProvider(Protocol):
15
+ def __call__(self) -> Image:
16
+ """
17
+ Represents the functionality to invoke the callable object and produce an Image
18
+ result. Typically used to process or generate images using the defined logic
19
+ within the __call__ method.
20
+
21
+ Returns:
22
+ Image: The resulting image output from the callable logic.
23
+ """
24
+
25
+ def last_image(self) -> Image:
26
+ """
27
+ Returns the last captured image.
28
+
29
+ This method retrieves the most recent image that was captured and stored
30
+ in memory. If there are no images available, the method may return None.
31
+
32
+ Returns:
33
+ Image: The last captured image, or None if no images are available.
34
+ """
@@ -0,0 +1,32 @@
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 .action import Action, ActionType
10
+ from .client import (
11
+ ErrorDetail,
12
+ ErrorResponse,
13
+ GenerateResponse,
14
+ LLMResponse,
15
+ UploadFileResponse,
16
+ Usage,
17
+ )
18
+ from .image_config import ImageConfig
19
+ from .step import Step
20
+
21
+ __all__ = [
22
+ "Action",
23
+ "ActionType",
24
+ "ErrorDetail",
25
+ "ErrorResponse",
26
+ "GenerateResponse",
27
+ "ImageConfig",
28
+ "LLMResponse",
29
+ "Step",
30
+ "UploadFileResponse",
31
+ "Usage",
32
+ ]