oagi-core 0.10.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.
Files changed (68) hide show
  1. oagi/__init__.py +148 -0
  2. oagi/agent/__init__.py +33 -0
  3. oagi/agent/default.py +124 -0
  4. oagi/agent/factories.py +74 -0
  5. oagi/agent/observer/__init__.py +38 -0
  6. oagi/agent/observer/agent_observer.py +99 -0
  7. oagi/agent/observer/events.py +28 -0
  8. oagi/agent/observer/exporters.py +445 -0
  9. oagi/agent/observer/protocol.py +12 -0
  10. oagi/agent/protocol.py +55 -0
  11. oagi/agent/registry.py +155 -0
  12. oagi/agent/tasker/__init__.py +33 -0
  13. oagi/agent/tasker/memory.py +160 -0
  14. oagi/agent/tasker/models.py +77 -0
  15. oagi/agent/tasker/planner.py +408 -0
  16. oagi/agent/tasker/taskee_agent.py +512 -0
  17. oagi/agent/tasker/tasker_agent.py +324 -0
  18. oagi/cli/__init__.py +11 -0
  19. oagi/cli/agent.py +281 -0
  20. oagi/cli/display.py +56 -0
  21. oagi/cli/main.py +77 -0
  22. oagi/cli/server.py +94 -0
  23. oagi/cli/tracking.py +55 -0
  24. oagi/cli/utils.py +89 -0
  25. oagi/client/__init__.py +12 -0
  26. oagi/client/async_.py +290 -0
  27. oagi/client/base.py +457 -0
  28. oagi/client/sync.py +293 -0
  29. oagi/exceptions.py +118 -0
  30. oagi/handler/__init__.py +24 -0
  31. oagi/handler/_macos.py +55 -0
  32. oagi/handler/async_pyautogui_action_handler.py +44 -0
  33. oagi/handler/async_screenshot_maker.py +47 -0
  34. oagi/handler/pil_image.py +102 -0
  35. oagi/handler/pyautogui_action_handler.py +291 -0
  36. oagi/handler/screenshot_maker.py +41 -0
  37. oagi/logging.py +55 -0
  38. oagi/server/__init__.py +13 -0
  39. oagi/server/agent_wrappers.py +98 -0
  40. oagi/server/config.py +46 -0
  41. oagi/server/main.py +157 -0
  42. oagi/server/models.py +98 -0
  43. oagi/server/session_store.py +116 -0
  44. oagi/server/socketio_server.py +405 -0
  45. oagi/task/__init__.py +21 -0
  46. oagi/task/async_.py +101 -0
  47. oagi/task/async_short.py +76 -0
  48. oagi/task/base.py +157 -0
  49. oagi/task/short.py +76 -0
  50. oagi/task/sync.py +99 -0
  51. oagi/types/__init__.py +50 -0
  52. oagi/types/action_handler.py +30 -0
  53. oagi/types/async_action_handler.py +30 -0
  54. oagi/types/async_image_provider.py +38 -0
  55. oagi/types/image.py +17 -0
  56. oagi/types/image_provider.py +35 -0
  57. oagi/types/models/__init__.py +32 -0
  58. oagi/types/models/action.py +33 -0
  59. oagi/types/models/client.py +68 -0
  60. oagi/types/models/image_config.py +47 -0
  61. oagi/types/models/step.py +17 -0
  62. oagi/types/step_observer.py +93 -0
  63. oagi/types/url.py +3 -0
  64. oagi_core-0.10.1.dist-info/METADATA +245 -0
  65. oagi_core-0.10.1.dist-info/RECORD +68 -0
  66. oagi_core-0.10.1.dist-info/WHEEL +4 -0
  67. oagi_core-0.10.1.dist-info/entry_points.txt +2 -0
  68. oagi_core-0.10.1.dist-info/licenses/LICENSE +21 -0
oagi/task/base.py ADDED
@@ -0,0 +1,157 @@
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 URL, Image, Step
13
+ from ..types.models import LLMResponse
14
+
15
+ logger = get_logger("task.base")
16
+
17
+
18
+ class BaseActor:
19
+ """Base class with shared task management logic for sync/async actors."""
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
+ self.max_steps: int = 20 # Maximum steps allowed
34
+ self.current_step: int = 0 # Current step counter
35
+ # Client will be set by subclasses
36
+ self.api_key: str | None = None
37
+ self.base_url: str | None = None
38
+
39
+ def _prepare_init_task(
40
+ self,
41
+ task_desc: str,
42
+ max_steps: int,
43
+ ):
44
+ """Prepare task initialization (v2 API does not call server for init).
45
+
46
+ Args:
47
+ task_desc: Task description
48
+ max_steps: Maximum number of steps
49
+ """
50
+ self.task_id = uuid4().hex
51
+ self.task_description = task_desc
52
+ self.message_history = []
53
+ self.max_steps = max_steps
54
+ self.current_step = 0
55
+ logger.info(f"Task initialized: '{task_desc}' (max_steps: {max_steps})")
56
+
57
+ def _validate_and_increment_step(self):
58
+ if not self.task_description:
59
+ raise ValueError("Task description must be set. Call init_task() first.")
60
+ if self.current_step >= self.max_steps:
61
+ raise ValueError(
62
+ f"Max steps limit ({self.max_steps}) reached. "
63
+ "Call init_task() to start a new task."
64
+ )
65
+ self.current_step += 1
66
+
67
+ def _prepare_step(
68
+ self,
69
+ screenshot: Image | URL | bytes,
70
+ instruction: str | None,
71
+ temperature: float | None,
72
+ prefix: str = "",
73
+ ) -> dict:
74
+ self._validate_and_increment_step()
75
+ self._log_step_execution(prefix=prefix)
76
+
77
+ return {
78
+ "model": self.model,
79
+ "task_description": self.task_description,
80
+ "task_id": self.task_id,
81
+ "instruction": instruction,
82
+ "messages_history": self.message_history,
83
+ "temperature": self._get_temperature(temperature),
84
+ **self._prepare_screenshot_kwargs(screenshot),
85
+ }
86
+
87
+ def _handle_step_error(self, error: Exception, prefix: str = ""):
88
+ logger.error(f"Error during {prefix}step execution: {error}")
89
+ raise
90
+
91
+ def _prepare_screenshot(self, screenshot: Image | bytes) -> bytes:
92
+ if isinstance(screenshot, Image):
93
+ return screenshot.read()
94
+ return screenshot
95
+
96
+ def _get_temperature(self, temperature: float | None) -> float | None:
97
+ return temperature if temperature is not None else self.temperature
98
+
99
+ def _prepare_screenshot_kwargs(self, screenshot: Image | URL | bytes) -> dict:
100
+ if isinstance(screenshot, str):
101
+ return {"screenshot_url": screenshot}
102
+ return {"screenshot": self._prepare_screenshot(screenshot)}
103
+
104
+ def _handle_response_message_history(self, response: LLMResponse):
105
+ if response.raw_output:
106
+ self.message_history.append(
107
+ {
108
+ "role": "assistant",
109
+ "content": [{"type": "text", "text": response.raw_output}],
110
+ }
111
+ )
112
+
113
+ def _build_step_response(self, response: LLMResponse, prefix: str = "") -> Step:
114
+ # Update message history with assistant response
115
+ self._handle_response_message_history(response)
116
+
117
+ result = Step(
118
+ reason=response.reason,
119
+ actions=response.actions,
120
+ stop=response.is_complete,
121
+ )
122
+
123
+ if response.is_complete:
124
+ logger.info(f"{prefix}Task completed.")
125
+ else:
126
+ logger.debug(f"{prefix}Step completed with {len(response.actions)} actions")
127
+
128
+ return result
129
+
130
+ def _log_step_execution(self, prefix: str = ""):
131
+ logger.debug(f"Executing {prefix}step for task: '{self.task_description}'")
132
+
133
+
134
+ class BaseAutoMode:
135
+ """Base class with shared auto_mode logic for ShortTask implementations."""
136
+
137
+ def _log_auto_mode_start(self, task_desc: str, max_steps: int, prefix: str = ""):
138
+ logger.info(
139
+ f"Starting {prefix}auto mode for task: '{task_desc}' (max_steps: {max_steps})"
140
+ )
141
+
142
+ def _log_auto_mode_step(self, step_num: int, max_steps: int, prefix: str = ""):
143
+ logger.debug(f"{prefix.capitalize()}auto mode step {step_num}/{max_steps}")
144
+
145
+ def _log_auto_mode_actions(self, action_count: int, prefix: str = ""):
146
+ verb = "asynchronously" if "async" in prefix else ""
147
+ logger.debug(f"Executing {action_count} actions {verb}".strip())
148
+
149
+ def _log_auto_mode_completion(self, steps: int, prefix: str = ""):
150
+ logger.info(
151
+ f"{prefix.capitalize()}auto mode completed successfully after {steps} steps"
152
+ )
153
+
154
+ def _log_auto_mode_max_steps(self, max_steps: int, prefix: str = ""):
155
+ logger.warning(
156
+ f"{prefix.capitalize()}auto mode reached max steps ({max_steps}) without completion"
157
+ )
oagi/task/short.py ADDED
@@ -0,0 +1,76 @@
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 warnings
10
+
11
+ from ..logging import get_logger
12
+ from ..types import ActionHandler, ImageProvider
13
+ from .base import BaseAutoMode
14
+ from .sync import Actor
15
+
16
+ logger = get_logger("short_task")
17
+
18
+
19
+ class ShortTask(Actor, BaseAutoMode):
20
+ """Deprecated: This class is deprecated and will be removed in a future version.
21
+
22
+ Task implementation with automatic mode for short-duration tasks.
23
+ Please use Actor directly with custom automation logic instead.
24
+ """
25
+
26
+ def __init__(
27
+ self,
28
+ api_key: str | None = None,
29
+ base_url: str | None = None,
30
+ model: str = "lux-actor-1",
31
+ temperature: float | None = None,
32
+ ):
33
+ warnings.warn(
34
+ "ShortTask is deprecated and will be removed in a future version. "
35
+ "Please use Actor with custom automation logic instead.",
36
+ DeprecationWarning,
37
+ stacklevel=2,
38
+ )
39
+ super().__init__(
40
+ api_key=api_key, base_url=base_url, model=model, temperature=temperature
41
+ )
42
+
43
+ def auto_mode(
44
+ self,
45
+ task_desc: str,
46
+ max_steps: int = 20,
47
+ executor: ActionHandler = None,
48
+ image_provider: ImageProvider = None,
49
+ temperature: float | None = None,
50
+ ) -> bool:
51
+ """Run the task in automatic mode with the provided executor and image provider.
52
+
53
+ Args:
54
+ task_desc: Task description
55
+ max_steps: Maximum number of steps
56
+ executor: Handler to execute actions
57
+ image_provider: Provider for screenshots
58
+ temperature: Sampling temperature for all steps (overrides task default if provided)
59
+ """
60
+ self._log_auto_mode_start(task_desc, max_steps)
61
+
62
+ self.init_task(task_desc, max_steps=max_steps)
63
+
64
+ for i in range(max_steps):
65
+ self._log_auto_mode_step(i + 1, max_steps)
66
+ image = image_provider()
67
+ step = self.step(image, temperature=temperature)
68
+ if executor:
69
+ self._log_auto_mode_actions(len(step.actions))
70
+ executor(step.actions)
71
+ if step.stop:
72
+ self._log_auto_mode_completion(i + 1)
73
+ return True
74
+
75
+ self._log_auto_mode_max_steps(max_steps)
76
+ return False
oagi/task/sync.py ADDED
@@ -0,0 +1,99 @@
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 warnings
10
+
11
+ from ..client import SyncClient
12
+ from ..types import URL, Image, Step
13
+ from .base import BaseActor
14
+
15
+
16
+ class Actor(BaseActor):
17
+ """Base class for task automation with the OAGI API."""
18
+
19
+ def __init__(
20
+ self,
21
+ api_key: str | None = None,
22
+ base_url: str | None = None,
23
+ model: str = "lux-actor-1",
24
+ temperature: float | None = None,
25
+ ):
26
+ super().__init__(api_key, base_url, model, temperature)
27
+ self.client = SyncClient(base_url=base_url, api_key=api_key)
28
+ self.api_key = self.client.api_key
29
+ self.base_url = self.client.base_url
30
+
31
+ def init_task(
32
+ self,
33
+ task_desc: str,
34
+ max_steps: int = 20,
35
+ ):
36
+ """Initialize a new task with the given description.
37
+
38
+ Args:
39
+ task_desc: Task description
40
+ max_steps: Maximum number of steps allowed
41
+ """
42
+ self._prepare_init_task(task_desc, max_steps)
43
+
44
+ def step(
45
+ self,
46
+ screenshot: Image | URL | bytes,
47
+ instruction: str | None = None,
48
+ temperature: float | None = None,
49
+ ) -> Step:
50
+ """Send screenshot to the server and get the next actions.
51
+
52
+ Args:
53
+ screenshot: Screenshot as Image object or raw bytes
54
+ instruction: Optional additional instruction for this step
55
+ temperature: Sampling temperature for this step (overrides task default if provided)
56
+
57
+ Returns:
58
+ Step: The actions and reasoning for this step
59
+ """
60
+ kwargs = self._prepare_step(screenshot, instruction, temperature)
61
+
62
+ try:
63
+ response = self.client.create_message(**kwargs)
64
+ return self._build_step_response(response)
65
+ except Exception as e:
66
+ self._handle_step_error(e)
67
+
68
+ def close(self):
69
+ """Close the underlying HTTP client to free resources."""
70
+ self.client.close()
71
+
72
+ def __enter__(self):
73
+ return self
74
+
75
+ def __exit__(self, exc_type, exc_val, exc_tb):
76
+ self.close()
77
+
78
+
79
+ class Task(Actor):
80
+ """Deprecated: Use Actor instead.
81
+
82
+ This class is deprecated and will be removed in a future version.
83
+ Please use Actor instead.
84
+ """
85
+
86
+ def __init__(
87
+ self,
88
+ api_key: str | None = None,
89
+ base_url: str | None = None,
90
+ model: str = "lux-actor-1",
91
+ temperature: float | None = None,
92
+ ):
93
+ warnings.warn(
94
+ "Task is deprecated and will be removed in a future version. "
95
+ "Please use Actor instead.",
96
+ DeprecationWarning,
97
+ stacklevel=2,
98
+ )
99
+ super().__init__(api_key, base_url, model, temperature)
oagi/types/__init__.py ADDED
@@ -0,0 +1,50 @@
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 .step_observer import (
16
+ ActionEvent,
17
+ AsyncObserver,
18
+ AsyncStepObserver,
19
+ BaseEvent,
20
+ ImageEvent,
21
+ LogEvent,
22
+ ObserverEvent,
23
+ PlanEvent,
24
+ SplitEvent,
25
+ StepEvent,
26
+ )
27
+ from .url import URL
28
+
29
+ __all__ = [
30
+ "Action",
31
+ "ActionEvent",
32
+ "ActionType",
33
+ "AsyncObserver",
34
+ "AsyncStepObserver",
35
+ "BaseEvent",
36
+ "Image",
37
+ "ImageConfig",
38
+ "ImageEvent",
39
+ "LogEvent",
40
+ "ObserverEvent",
41
+ "PlanEvent",
42
+ "SplitEvent",
43
+ "Step",
44
+ "StepEvent",
45
+ "ActionHandler",
46
+ "AsyncActionHandler",
47
+ "ImageProvider",
48
+ "AsyncImageProvider",
49
+ "URL",
50
+ ]
@@ -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,38 @@
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
+ from .url import URL
13
+
14
+
15
+ class AsyncImageProvider(Protocol):
16
+ async def __call__(self) -> Image | URL:
17
+ """
18
+ Asynchronously provides an image.
19
+
20
+ This method is responsible for asynchronously capturing, generating, or retrieving
21
+ an image that can be used for task execution or analysis. The method should return
22
+ an object that implements the Image protocol.
23
+
24
+ Returns:
25
+ Image: An object implementing the Image protocol that represents
26
+ the captured or generated image.
27
+
28
+ Raises:
29
+ RuntimeError: If an error occurs during image capture or generation.
30
+ """
31
+
32
+ async def last_image(self) -> Image | URL:
33
+ """
34
+ Asynchronously returns the last captured image.
35
+
36
+ Returns:
37
+ Image: The last captured image.
38
+ """
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,35 @@
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
+ from .url import URL
13
+
14
+
15
+ class ImageProvider(Protocol):
16
+ def __call__(self) -> Image | URL:
17
+ """
18
+ Represents the functionality to invoke the callable object and produce an Image
19
+ result. Typically used to process or generate images using the defined logic
20
+ within the __call__ method.
21
+
22
+ Returns:
23
+ Image: The resulting image output from the callable logic.
24
+ """
25
+
26
+ def last_image(self) -> Image | URL:
27
+ """
28
+ Returns the last captured image.
29
+
30
+ This method retrieves the most recent image that was captured and stored
31
+ in memory. If there are no images available, the method may return None.
32
+
33
+ Returns:
34
+ Image: The last captured image, or None if no images are available.
35
+ """
@@ -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
+ ]
@@ -0,0 +1,33 @@
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 enum import Enum
10
+
11
+ from pydantic import BaseModel, Field
12
+
13
+
14
+ class ActionType(str, Enum):
15
+ CLICK = "click"
16
+ LEFT_DOUBLE = "left_double"
17
+ LEFT_TRIPLE = "left_triple"
18
+ RIGHT_SINGLE = "right_single"
19
+ DRAG = "drag"
20
+ HOTKEY = "hotkey"
21
+ TYPE = "type"
22
+ SCROLL = "scroll"
23
+ FINISH = "finish"
24
+ WAIT = "wait"
25
+ CALL_USER = "call_user"
26
+
27
+
28
+ class Action(BaseModel):
29
+ type: ActionType = Field(..., description="Type of action to perform")
30
+ argument: str = Field(..., description="Action argument in the specified format")
31
+ count: int | None = Field(
32
+ default=1, ge=1, description="Number of times to repeat the action"
33
+ )
@@ -0,0 +1,68 @@
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 pydantic import BaseModel, Field
10
+
11
+ from .action import Action
12
+
13
+
14
+ class Usage(BaseModel):
15
+ prompt_tokens: int
16
+ completion_tokens: int
17
+ total_tokens: int
18
+
19
+
20
+ class ErrorDetail(BaseModel):
21
+ """Detailed error information."""
22
+
23
+ code: str
24
+ message: str
25
+
26
+
27
+ class ErrorResponse(BaseModel):
28
+ """Standard error response format."""
29
+
30
+ error: ErrorDetail | None
31
+
32
+
33
+ class LLMResponse(BaseModel):
34
+ id: str
35
+ task_id: str
36
+ object: str = "task.completion"
37
+ created: int
38
+ model: str
39
+ task_description: str
40
+ is_complete: bool
41
+ actions: list[Action]
42
+ reason: str | None = None
43
+ usage: Usage
44
+ error: ErrorDetail | None = None
45
+ raw_output: str | None = None
46
+
47
+
48
+ class UploadFileResponse(BaseModel):
49
+ """Response from S3 presigned URL upload."""
50
+
51
+ url: str
52
+ uuid: str
53
+ expires_at: int
54
+ file_expires_at: int
55
+ download_url: str
56
+
57
+
58
+ class GenerateResponse(BaseModel):
59
+ """Response from /v1/generate endpoint."""
60
+
61
+ response: str
62
+ prompt_tokens: int
63
+ completion_tokens: int
64
+ cost: float | None = Field(
65
+ default=None,
66
+ deprecated=True,
67
+ description="This field is deprecated",
68
+ )