asteroid-odyssey 1.3.2__py3-none-any.whl → 1.3.4__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.
- asteroid_odyssey/agents_v1_gen/models/agent_profile.py +3 -3
- asteroid_odyssey/agents_v2_gen/__init__.py +57 -43
- asteroid_odyssey/agents_v2_gen/api/__init__.py +1 -1
- asteroid_odyssey/agents_v2_gen/api/default_api.py +1199 -0
- asteroid_odyssey/agents_v2_gen/api_client.py +1 -1
- asteroid_odyssey/agents_v2_gen/configuration.py +4 -14
- asteroid_odyssey/agents_v2_gen/exceptions.py +1 -1
- asteroid_odyssey/agents_v2_gen/models/__init__.py +28 -21
- asteroid_odyssey/agents_v2_gen/models/activity_payload_union_action_completed.py +4 -4
- asteroid_odyssey/agents_v2_gen/models/activity_payload_union_action_failed.py +4 -4
- asteroid_odyssey/agents_v2_gen/models/activity_payload_union_action_started.py +4 -4
- asteroid_odyssey/agents_v2_gen/models/activity_payload_union_file_added.py +100 -0
- asteroid_odyssey/agents_v2_gen/models/activity_payload_union_generic.py +4 -4
- asteroid_odyssey/agents_v2_gen/models/activity_payload_union_status_changed.py +4 -4
- asteroid_odyssey/agents_v2_gen/models/activity_payload_union_step_completed.py +4 -4
- asteroid_odyssey/agents_v2_gen/models/activity_payload_union_step_started.py +4 -4
- asteroid_odyssey/agents_v2_gen/models/activity_payload_union_terminal.py +4 -4
- asteroid_odyssey/agents_v2_gen/models/activity_payload_union_transitioned_node.py +4 -4
- asteroid_odyssey/agents_v2_gen/models/activity_payload_union_user_message_received.py +4 -4
- asteroid_odyssey/agents_v2_gen/models/{execution_activity.py → agents_execution_activity.py} +8 -8
- asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_action_completed_payload.py +87 -0
- asteroid_odyssey/agents_v2_gen/models/{execution_activity_action_completed_payload.py → agents_execution_activity_action_failed_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/{execution_activity_action_failed_payload.py → agents_execution_activity_action_started_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_file_added_payload.py +104 -0
- asteroid_odyssey/agents_v2_gen/models/{execution_activity_action_started_payload.py → agents_execution_activity_generic_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/{execution_activity_payload_union.py → agents_execution_activity_payload_union.py} +26 -12
- asteroid_odyssey/agents_v2_gen/models/{execution_activity_status_changed_payload.py → agents_execution_activity_status_changed_payload.py} +26 -20
- asteroid_odyssey/agents_v2_gen/models/{execution_activity_step_started_payload.py → agents_execution_activity_step_completed_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/{execution_activity_step_completed_payload.py → agents_execution_activity_step_started_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/{execution_activity_transitioned_node_payload.py → agents_execution_activity_transitioned_node_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/{execution_activity_user_message_received_payload.py → agents_execution_activity_user_message_received_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/{execution_awaiting_confirmation_payload.py → agents_execution_awaiting_confirmation_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/agents_execution_cancel_reason.py +38 -0
- asteroid_odyssey/agents_v2_gen/models/agents_execution_cancelled_payload.py +88 -0
- asteroid_odyssey/agents_v2_gen/models/{execution_completed_payload.py → agents_execution_completed_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/{execution_failed_payload.py → agents_execution_failed_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/{execution_paused_payload.py → agents_execution_paused_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/{execution_status.py → agents_execution_status.py} +4 -4
- asteroid_odyssey/agents_v2_gen/models/{execution_terminal_payload.py → agents_execution_terminal_payload.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/{execution_activity_generic_payload.py → agents_execution_user_messages_add_text_body.py} +5 -5
- asteroid_odyssey/agents_v2_gen/models/agents_files_file.py +108 -0
- asteroid_odyssey/agents_v2_gen/models/common_bad_request_error_body.py +96 -0
- asteroid_odyssey/agents_v2_gen/models/common_forbidden_error_body.py +96 -0
- asteroid_odyssey/agents_v2_gen/models/{error.py → common_not_found_error_body.py} +15 -8
- asteroid_odyssey/agents_v2_gen/models/{versions.py → version.py} +5 -6
- asteroid_odyssey/agents_v2_gen/rest.py +1 -1
- asteroid_odyssey/client.py +177 -6
- {asteroid_odyssey-1.3.2.dist-info → asteroid_odyssey-1.3.4.dist-info}/METADATA +2 -1
- asteroid_odyssey-1.3.4.dist-info/RECORD +84 -0
- asteroid_odyssey/agents_v2_gen/api/execution_api.py +0 -625
- asteroid_odyssey/agents_v2_gen/models/execution_user_messages_add_text_body.py +0 -87
- asteroid_odyssey-1.3.2.dist-info/RECORD +0 -77
- {asteroid_odyssey-1.3.2.dist-info → asteroid_odyssey-1.3.4.dist-info}/WHEEL +0 -0
- {asteroid_odyssey-1.3.2.dist-info → asteroid_odyssey-1.3.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Agent Service
|
|
5
|
+
|
|
6
|
+
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
|
7
|
+
|
|
8
|
+
The version of the OpenAPI document: v1
|
|
9
|
+
Generated by OpenAPI Generator (https://openapi-generator.tech)
|
|
10
|
+
|
|
11
|
+
Do not edit the class manually.
|
|
12
|
+
""" # noqa: E501
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
import pprint
|
|
17
|
+
import re # noqa: F401
|
|
18
|
+
import json
|
|
19
|
+
|
|
20
|
+
from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr, field_validator
|
|
21
|
+
from typing import Any, ClassVar, Dict, List, Union
|
|
22
|
+
from typing import Optional, Set
|
|
23
|
+
from typing_extensions import Self
|
|
24
|
+
|
|
25
|
+
class CommonForbiddenErrorBody(BaseModel):
|
|
26
|
+
"""
|
|
27
|
+
CommonForbiddenErrorBody
|
|
28
|
+
""" # noqa: E501
|
|
29
|
+
code: Union[StrictFloat, StrictInt]
|
|
30
|
+
message: StrictStr
|
|
31
|
+
__properties: ClassVar[List[str]] = ["code", "message"]
|
|
32
|
+
|
|
33
|
+
@field_validator('code')
|
|
34
|
+
def code_validate_enum(cls, value):
|
|
35
|
+
"""Validates the enum"""
|
|
36
|
+
if value not in set([403]):
|
|
37
|
+
raise ValueError("must be one of enum values (403)")
|
|
38
|
+
return value
|
|
39
|
+
|
|
40
|
+
model_config = ConfigDict(
|
|
41
|
+
populate_by_name=True,
|
|
42
|
+
validate_assignment=True,
|
|
43
|
+
protected_namespaces=(),
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def to_str(self) -> str:
|
|
48
|
+
"""Returns the string representation of the model using alias"""
|
|
49
|
+
return pprint.pformat(self.model_dump(by_alias=True))
|
|
50
|
+
|
|
51
|
+
def to_json(self) -> str:
|
|
52
|
+
"""Returns the JSON representation of the model using alias"""
|
|
53
|
+
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
|
|
54
|
+
return json.dumps(self.to_dict())
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def from_json(cls, json_str: str) -> Optional[Self]:
|
|
58
|
+
"""Create an instance of CommonForbiddenErrorBody from a JSON string"""
|
|
59
|
+
return cls.from_dict(json.loads(json_str))
|
|
60
|
+
|
|
61
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
62
|
+
"""Return the dictionary representation of the model using alias.
|
|
63
|
+
|
|
64
|
+
This has the following differences from calling pydantic's
|
|
65
|
+
`self.model_dump(by_alias=True)`:
|
|
66
|
+
|
|
67
|
+
* `None` is only added to the output dict for nullable fields that
|
|
68
|
+
were set at model initialization. Other fields with value `None`
|
|
69
|
+
are ignored.
|
|
70
|
+
"""
|
|
71
|
+
excluded_fields: Set[str] = set([
|
|
72
|
+
])
|
|
73
|
+
|
|
74
|
+
_dict = self.model_dump(
|
|
75
|
+
by_alias=True,
|
|
76
|
+
exclude=excluded_fields,
|
|
77
|
+
exclude_none=True,
|
|
78
|
+
)
|
|
79
|
+
return _dict
|
|
80
|
+
|
|
81
|
+
@classmethod
|
|
82
|
+
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
|
|
83
|
+
"""Create an instance of CommonForbiddenErrorBody from a dict"""
|
|
84
|
+
if obj is None:
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
if not isinstance(obj, dict):
|
|
88
|
+
return cls.model_validate(obj)
|
|
89
|
+
|
|
90
|
+
_obj = cls.model_validate({
|
|
91
|
+
"code": obj.get("code"),
|
|
92
|
+
"message": obj.get("message")
|
|
93
|
+
})
|
|
94
|
+
return _obj
|
|
95
|
+
|
|
96
|
+
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document:
|
|
8
|
+
The version of the OpenAPI document: v1
|
|
9
9
|
Generated by OpenAPI Generator (https://openapi-generator.tech)
|
|
10
10
|
|
|
11
11
|
Do not edit the class manually.
|
|
@@ -17,19 +17,26 @@ import pprint
|
|
|
17
17
|
import re # noqa: F401
|
|
18
18
|
import json
|
|
19
19
|
|
|
20
|
-
from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr
|
|
21
|
-
from typing import Any, ClassVar, Dict, List
|
|
20
|
+
from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr, field_validator
|
|
21
|
+
from typing import Any, ClassVar, Dict, List, Union
|
|
22
22
|
from typing import Optional, Set
|
|
23
23
|
from typing_extensions import Self
|
|
24
24
|
|
|
25
|
-
class
|
|
25
|
+
class CommonNotFoundErrorBody(BaseModel):
|
|
26
26
|
"""
|
|
27
|
-
|
|
27
|
+
CommonNotFoundErrorBody
|
|
28
28
|
""" # noqa: E501
|
|
29
|
-
code: StrictInt
|
|
29
|
+
code: Union[StrictFloat, StrictInt]
|
|
30
30
|
message: StrictStr
|
|
31
31
|
__properties: ClassVar[List[str]] = ["code", "message"]
|
|
32
32
|
|
|
33
|
+
@field_validator('code')
|
|
34
|
+
def code_validate_enum(cls, value):
|
|
35
|
+
"""Validates the enum"""
|
|
36
|
+
if value not in set([404]):
|
|
37
|
+
raise ValueError("must be one of enum values (404)")
|
|
38
|
+
return value
|
|
39
|
+
|
|
33
40
|
model_config = ConfigDict(
|
|
34
41
|
populate_by_name=True,
|
|
35
42
|
validate_assignment=True,
|
|
@@ -48,7 +55,7 @@ class Error(BaseModel):
|
|
|
48
55
|
|
|
49
56
|
@classmethod
|
|
50
57
|
def from_json(cls, json_str: str) -> Optional[Self]:
|
|
51
|
-
"""Create an instance of
|
|
58
|
+
"""Create an instance of CommonNotFoundErrorBody from a JSON string"""
|
|
52
59
|
return cls.from_dict(json.loads(json_str))
|
|
53
60
|
|
|
54
61
|
def to_dict(self) -> Dict[str, Any]:
|
|
@@ -73,7 +80,7 @@ class Error(BaseModel):
|
|
|
73
80
|
|
|
74
81
|
@classmethod
|
|
75
82
|
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
|
|
76
|
-
"""Create an instance of
|
|
83
|
+
"""Create an instance of CommonNotFoundErrorBody from a dict"""
|
|
77
84
|
if obj is None:
|
|
78
85
|
return None
|
|
79
86
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document:
|
|
8
|
+
The version of the OpenAPI document: v1
|
|
9
9
|
Generated by OpenAPI Generator (https://openapi-generator.tech)
|
|
10
10
|
|
|
11
11
|
Do not edit the class manually.
|
|
@@ -18,20 +18,19 @@ from enum import Enum
|
|
|
18
18
|
from typing_extensions import Self
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
class
|
|
21
|
+
class Version(str, Enum):
|
|
22
22
|
"""
|
|
23
|
-
|
|
23
|
+
Version
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
26
|
"""
|
|
27
27
|
allowed enum values
|
|
28
28
|
"""
|
|
29
|
-
|
|
30
|
-
V2 = 'v2'
|
|
29
|
+
V1 = 'v1'
|
|
31
30
|
|
|
32
31
|
@classmethod
|
|
33
32
|
def from_json(cls, json_str: str) -> Self:
|
|
34
|
-
"""Create an instance of
|
|
33
|
+
"""Create an instance of Version from a JSON string"""
|
|
35
34
|
return cls(json.loads(json_str))
|
|
36
35
|
|
|
37
36
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document:
|
|
8
|
+
The version of the OpenAPI document: v1
|
|
9
9
|
Generated by OpenAPI Generator (https://openapi-generator.tech)
|
|
10
10
|
|
|
11
11
|
Do not edit the class manually.
|
asteroid_odyssey/client.py
CHANGED
|
@@ -11,6 +11,8 @@ without modifying any generated files.
|
|
|
11
11
|
import time
|
|
12
12
|
import os
|
|
13
13
|
import base64
|
|
14
|
+
import requests
|
|
15
|
+
from pathlib import Path
|
|
14
16
|
from typing import Dict, Any, Optional, List, Union, Tuple, NamedTuple
|
|
15
17
|
from cryptography.hazmat.primitives import serialization
|
|
16
18
|
from cryptography.hazmat.primitives.asymmetric import padding, rsa
|
|
@@ -35,9 +37,10 @@ from .agents_v1_gen.exceptions import ApiException
|
|
|
35
37
|
from .agents_v2_gen import (
|
|
36
38
|
Configuration as AgentsV2Configuration,
|
|
37
39
|
ApiClient as AgentsV2ApiClient,
|
|
38
|
-
|
|
39
|
-
ExecutionActivity,
|
|
40
|
-
ExecutionUserMessagesAddTextBody,
|
|
40
|
+
DefaultApi as AgentsV2ExecutionApi,
|
|
41
|
+
AgentsExecutionActivity as ExecutionActivity,
|
|
42
|
+
AgentsExecutionUserMessagesAddTextBody as ExecutionUserMessagesAddTextBody,
|
|
43
|
+
AgentsFilesFile as File,
|
|
41
44
|
)
|
|
42
45
|
|
|
43
46
|
|
|
@@ -775,7 +778,7 @@ class AsteroidClient:
|
|
|
775
778
|
Raises:
|
|
776
779
|
Exception: If the execution activities request fails
|
|
777
780
|
"""
|
|
778
|
-
return self.agents_v2_execution_api.
|
|
781
|
+
return self.agents_v2_execution_api.execution_activities_get(execution_id, order="desc", limit=n)
|
|
779
782
|
def add_message_to_execution(self, execution_id: str, message: str) -> None:
|
|
780
783
|
"""
|
|
781
784
|
Add a message to an execution.
|
|
@@ -790,8 +793,125 @@ class AsteroidClient:
|
|
|
790
793
|
add_message_to_execution(client, "execution_id", "Hello, world!")
|
|
791
794
|
"""
|
|
792
795
|
message_body = ExecutionUserMessagesAddTextBody(message=message)
|
|
793
|
-
return self.agents_v2_execution_api.
|
|
796
|
+
return self.agents_v2_execution_api.execution_user_messages_add(execution_id, message_body)
|
|
794
797
|
|
|
798
|
+
def get_execution_files(self, execution_id: str) -> List[File]:
|
|
799
|
+
"""
|
|
800
|
+
Get a list of files associated with an execution.
|
|
801
|
+
Args:
|
|
802
|
+
execution_id: The execution identifier
|
|
803
|
+
Returns:
|
|
804
|
+
A list of files associated with the execution
|
|
805
|
+
Raises:
|
|
806
|
+
Exception: If the files request fails
|
|
807
|
+
Example:
|
|
808
|
+
files = client.get_execution_files("execution_id")
|
|
809
|
+
for file in files:
|
|
810
|
+
print(f"File: {file.file_name}, Size: {file.file_size}")
|
|
811
|
+
"""
|
|
812
|
+
try:
|
|
813
|
+
return self.agents_v2_execution_api.execution_context_files_get(execution_id)
|
|
814
|
+
except ApiException as e:
|
|
815
|
+
raise AsteroidAPIError(f"Failed to get execution files: {e}") from e
|
|
816
|
+
|
|
817
|
+
def download_execution_file(self, file: File, download_path: Union[str, Path],
|
|
818
|
+
create_dirs: bool = True, timeout: int = 30) -> str:
|
|
819
|
+
"""
|
|
820
|
+
Download a file from an execution using its signed URL.
|
|
821
|
+
|
|
822
|
+
Args:
|
|
823
|
+
file: The File object containing the signed URL and metadata
|
|
824
|
+
download_path: Path where the file should be saved. Can be a directory or full file path
|
|
825
|
+
create_dirs: Whether to create parent directories if they don't exist (default: True)
|
|
826
|
+
timeout: Request timeout in seconds (default: 30)
|
|
827
|
+
|
|
828
|
+
Returns:
|
|
829
|
+
The full path where the file was saved
|
|
830
|
+
|
|
831
|
+
Raises:
|
|
832
|
+
AsteroidAPIError: If the download fails
|
|
833
|
+
FileNotFoundError: If the parent directory doesn't exist and create_dirs is False
|
|
834
|
+
|
|
835
|
+
Example:
|
|
836
|
+
files = client.get_execution_files("execution_id")
|
|
837
|
+
for file in files:
|
|
838
|
+
# Download to specific directory
|
|
839
|
+
saved_path = client.download_execution_file(file, "/path/to/downloads/")
|
|
840
|
+
print(f"Downloaded {file.file_name} to {saved_path}")
|
|
841
|
+
|
|
842
|
+
# Download with specific filename
|
|
843
|
+
saved_path = client.download_execution_file(file, "/path/to/downloads/my_file.txt")
|
|
844
|
+
print(f"Downloaded to {saved_path}")
|
|
845
|
+
"""
|
|
846
|
+
final_path = None
|
|
847
|
+
try:
|
|
848
|
+
# Convert to Path object for easier manipulation
|
|
849
|
+
download_path = Path(download_path)
|
|
850
|
+
|
|
851
|
+
# Determine the final file path
|
|
852
|
+
if download_path.is_dir() or str(download_path).endswith('/'):
|
|
853
|
+
# If download_path is a directory, use the original filename
|
|
854
|
+
final_path = download_path / file.file_name
|
|
855
|
+
else:
|
|
856
|
+
# If download_path includes a filename, use it as-is
|
|
857
|
+
final_path = download_path
|
|
858
|
+
|
|
859
|
+
# Create parent directories if needed
|
|
860
|
+
if create_dirs:
|
|
861
|
+
final_path.parent.mkdir(parents=True, exist_ok=True)
|
|
862
|
+
elif not final_path.parent.exists():
|
|
863
|
+
raise FileNotFoundError(f"Parent directory does not exist: {final_path.parent}")
|
|
864
|
+
|
|
865
|
+
# Download the file using the signed URL
|
|
866
|
+
response = requests.get(file.signed_url, timeout=timeout, stream=True)
|
|
867
|
+
response.raise_for_status()
|
|
868
|
+
|
|
869
|
+
# Verify content length if available
|
|
870
|
+
expected_size = file.file_size
|
|
871
|
+
content_length = response.headers.get('content-length')
|
|
872
|
+
if content_length and int(content_length) != expected_size:
|
|
873
|
+
raise AsteroidAPIError(
|
|
874
|
+
f"Content length mismatch: expected {expected_size}, got {content_length}"
|
|
875
|
+
)
|
|
876
|
+
|
|
877
|
+
# Write the file in chunks to handle large files efficiently
|
|
878
|
+
chunk_size = 8192
|
|
879
|
+
total_size = 0
|
|
880
|
+
|
|
881
|
+
with open(final_path, 'wb') as f:
|
|
882
|
+
for chunk in response.iter_content(chunk_size=chunk_size):
|
|
883
|
+
if chunk: # Filter out keep-alive chunks
|
|
884
|
+
f.write(chunk)
|
|
885
|
+
total_size += len(chunk)
|
|
886
|
+
|
|
887
|
+
# Final verification of the downloaded file size
|
|
888
|
+
if total_size != expected_size:
|
|
889
|
+
raise AsteroidAPIError(
|
|
890
|
+
f"Downloaded file size mismatch: expected {expected_size}, got {total_size}"
|
|
891
|
+
)
|
|
892
|
+
|
|
893
|
+
return str(final_path)
|
|
894
|
+
|
|
895
|
+
except requests.exceptions.RequestException as e:
|
|
896
|
+
# Clean up partial file on network error
|
|
897
|
+
if final_path and final_path.exists():
|
|
898
|
+
final_path.unlink(missing_ok=True)
|
|
899
|
+
raise AsteroidAPIError(f"Failed to download file {file.file_name}: {e}") from e
|
|
900
|
+
except OSError as e:
|
|
901
|
+
# Clean up partial file on I/O error
|
|
902
|
+
if final_path and final_path.exists():
|
|
903
|
+
final_path.unlink(missing_ok=True)
|
|
904
|
+
raise AsteroidAPIError(f"Failed to save file {file.file_name}: {e}") from e
|
|
905
|
+
except AsteroidAPIError:
|
|
906
|
+
# Clean up partial file on size mismatch or other API errors
|
|
907
|
+
if final_path and final_path.exists():
|
|
908
|
+
final_path.unlink(missing_ok=True)
|
|
909
|
+
raise
|
|
910
|
+
except Exception as e:
|
|
911
|
+
# Clean up partial file on unexpected error
|
|
912
|
+
if final_path and final_path.exists():
|
|
913
|
+
final_path.unlink(missing_ok=True)
|
|
914
|
+
raise AsteroidAPIError(f"Unexpected error downloading file {file.file_name}: {e}") from e
|
|
795
915
|
|
|
796
916
|
# Convenience functions that mirror the TypeScript SDK pattern
|
|
797
917
|
def create_client(api_key: str, base_url: Optional[str] = None) -> AsteroidClient:
|
|
@@ -1086,6 +1206,56 @@ def add_message_to_execution(client: AsteroidClient, execution_id: str, message:
|
|
|
1086
1206
|
"""
|
|
1087
1207
|
return client.add_message_to_execution(execution_id, message)
|
|
1088
1208
|
|
|
1209
|
+
def get_execution_files(client: AsteroidClient, execution_id: str) -> List[File]:
|
|
1210
|
+
"""
|
|
1211
|
+
Get a list of files associated with an execution.
|
|
1212
|
+
Args:
|
|
1213
|
+
client: The AsteroidClient instance
|
|
1214
|
+
execution_id: The execution identifier
|
|
1215
|
+
Returns:
|
|
1216
|
+
A list of files associated with the execution
|
|
1217
|
+
Raises:
|
|
1218
|
+
Exception: If the files request fails
|
|
1219
|
+
Example:
|
|
1220
|
+
files = get_execution_files(client, "execution_id")
|
|
1221
|
+
for file in files:
|
|
1222
|
+
print(f"File: {file.file_name}, Size: {file.file_size}")
|
|
1223
|
+
"""
|
|
1224
|
+
return client.get_execution_files(execution_id)
|
|
1225
|
+
|
|
1226
|
+
def download_execution_file(client: AsteroidClient, file: File, download_path: Union[str, Path],
|
|
1227
|
+
create_dirs: bool = True, timeout: int = 30) -> str:
|
|
1228
|
+
"""
|
|
1229
|
+
Download a file from an execution using its signed URL.
|
|
1230
|
+
|
|
1231
|
+
Args:
|
|
1232
|
+
client: The AsteroidClient instance
|
|
1233
|
+
file: The File object containing the signed URL and metadata
|
|
1234
|
+
download_path: Path where the file should be saved. Can be a directory or full file path
|
|
1235
|
+
create_dirs: Whether to create parent directories if they don't exist (default: True)
|
|
1236
|
+
timeout: Request timeout in seconds (default: 30)
|
|
1237
|
+
|
|
1238
|
+
Returns:
|
|
1239
|
+
The full path where the file was saved
|
|
1240
|
+
|
|
1241
|
+
Raises:
|
|
1242
|
+
AsteroidAPIError: If the download fails
|
|
1243
|
+
FileNotFoundError: If the parent directory doesn't exist and create_dirs is False
|
|
1244
|
+
|
|
1245
|
+
Example:
|
|
1246
|
+
files = get_execution_files(client, "execution_id")
|
|
1247
|
+
for file in files:
|
|
1248
|
+
# Download to specific directory
|
|
1249
|
+
saved_path = download_execution_file(client, file, "/path/to/downloads/")
|
|
1250
|
+
print(f"Downloaded {file.file_name} to {saved_path}")
|
|
1251
|
+
|
|
1252
|
+
# Download with specific filename
|
|
1253
|
+
saved_path = download_execution_file(client, file, "/path/to/downloads/my_file.txt")
|
|
1254
|
+
print(f"Downloaded to {saved_path}")
|
|
1255
|
+
"""
|
|
1256
|
+
return client.download_execution_file(file, download_path, create_dirs, timeout)
|
|
1257
|
+
|
|
1258
|
+
|
|
1089
1259
|
|
|
1090
1260
|
def wait_for_agent_interaction(
|
|
1091
1261
|
client: AsteroidClient,
|
|
@@ -1157,7 +1327,8 @@ __all__ = [
|
|
|
1157
1327
|
'delete_agent_profile',
|
|
1158
1328
|
'get_last_n_execution_activities',
|
|
1159
1329
|
'add_message_to_execution',
|
|
1160
|
-
'
|
|
1330
|
+
'get_execution_files',
|
|
1331
|
+
'download_execution_file',
|
|
1161
1332
|
'wait_for_agent_interaction',
|
|
1162
1333
|
'get_credentials_public_key',
|
|
1163
1334
|
'AsteroidAPIError',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: asteroid-odyssey
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.4
|
|
4
4
|
Summary: A Python SDK for browser automation using Asteroid platform.
|
|
5
5
|
Author-email: David Mlcoch <founders@asteroid.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -22,6 +22,7 @@ Requires-Dist: pydantic>=2
|
|
|
22
22
|
Requires-Dist: typing-extensions>=4.7.1
|
|
23
23
|
Requires-Dist: requests>=2.28.0
|
|
24
24
|
Requires-Dist: cryptography>=41.0.0
|
|
25
|
+
Requires-Dist: lazy-imports>=1.0.0
|
|
25
26
|
Provides-Extra: dev
|
|
26
27
|
Requires-Dist: pytest>=7.2.1; extra == "dev"
|
|
27
28
|
Requires-Dist: pytest-cov>=2.8.1; extra == "dev"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
asteroid_odyssey/__init__.py,sha256=Yf0kbvXjjKVBPQV51JCQmId5-CrOhFriHTMOkZmzG2Q,1241
|
|
2
|
+
asteroid_odyssey/client.py,sha256=vEIieav9_q6kBj0oBOJW0djEHmOlSBrh_ynyHXHYnCc,51097
|
|
3
|
+
asteroid_odyssey/agents_v1_gen/__init__.py,sha256=bc-NDFcUy9zBjdMcfRgZtKtMotoyz74VMR9jKeCjgkM,4386
|
|
4
|
+
asteroid_odyssey/agents_v1_gen/api_client.py,sha256=Fq7Uh5yc9Mwza9NgCE1A0g2zrJ_hl5qQ_WFkACeHxWw,27747
|
|
5
|
+
asteroid_odyssey/agents_v1_gen/api_response.py,sha256=eMxw1mpmJcoGZ3gs9z6jM4oYoZ10Gjk333s9sKxGv7s,652
|
|
6
|
+
asteroid_odyssey/agents_v1_gen/configuration.py,sha256=Q5iAuaxcXVhsirre6lzbDLNP6okMLJacsp9UxNvt-5I,19060
|
|
7
|
+
asteroid_odyssey/agents_v1_gen/exceptions.py,sha256=xauMukb96TkgN7Rx5c_d_XWOJb7ldCY5SuTmybyKTr8,6414
|
|
8
|
+
asteroid_odyssey/agents_v1_gen/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
asteroid_odyssey/agents_v1_gen/rest.py,sha256=WJRyCYuQaJij3dz1-1tH0Gd9XHZ8msE7xRfT2hIzfxk,9427
|
|
10
|
+
asteroid_odyssey/agents_v1_gen/api/__init__.py,sha256=oj1pzgrbo8C6FrpBVC7IvfUu-uplU4JQjfE_jZE0Mz4,265
|
|
11
|
+
asteroid_odyssey/agents_v1_gen/api/agent_profile_api.py,sha256=uOgyH3VN8LseS5Mq2uFxAbZM5iH88O0YEmXFTMc8bQ0,66369
|
|
12
|
+
asteroid_odyssey/agents_v1_gen/api/api_api.py,sha256=vqZ7wQEQGOpa1D6U1QLL27XK-0DY5_v9tdQJNt_lpsM,19217
|
|
13
|
+
asteroid_odyssey/agents_v1_gen/api/execution_api.py,sha256=RXYDwX_VKMfM44IrKRb-c5D3FXnAPw8QQcpqDoGpL3Q,67849
|
|
14
|
+
asteroid_odyssey/agents_v1_gen/models/__init__.py,sha256=B4qBgPxwjUAB2yKdPOgFj_uYNjxMYCwaLrKUBrKTuiI,2053
|
|
15
|
+
asteroid_odyssey/agents_v1_gen/models/agent_profile.py,sha256=gOiHYIGH626wvvNSo9kbMu6fTLwC0xg_pN3aV_ubOO0,5388
|
|
16
|
+
asteroid_odyssey/agents_v1_gen/models/browser_session_recording_response.py,sha256=OgYXsMiADk5IIDKkWJTy0RfnnBO3Zbaq9mEUyaxTaH0,2590
|
|
17
|
+
asteroid_odyssey/agents_v1_gen/models/cookie.py,sha256=jvK-SgpFn8Untq3JnHTxDQnznT6Snn7Vnykba1-c3XU,4020
|
|
18
|
+
asteroid_odyssey/agents_v1_gen/models/country_code.py,sha256=pYFM0OC_maaGfUsFTTnKtSJxXKQiNS0pU3O0LLFz_Uo,802
|
|
19
|
+
asteroid_odyssey/agents_v1_gen/models/create_agent_profile_request.py,sha256=jqHaASZlDkTWSpF9AYEsc4QyEpfN9uY4QPw0uMhcSOA,5194
|
|
20
|
+
asteroid_odyssey/agents_v1_gen/models/credential.py,sha256=MSzwgGLjNiH_fclHpZpYKKDWn-498etD1CLS_EfmA7k,3033
|
|
21
|
+
asteroid_odyssey/agents_v1_gen/models/delete_agent_profile200_response.py,sha256=y6gaG8VLeC2muBcw-i6KG64i-xrHq1v-8A7T8ViwBwk,2514
|
|
22
|
+
asteroid_odyssey/agents_v1_gen/models/error_response.py,sha256=njnDeKZeMPiteuX4l3MsWTHkG4qEiv8sbIUTv0Z8yQY,2459
|
|
23
|
+
asteroid_odyssey/agents_v1_gen/models/execution_response.py,sha256=c4PJNQDsWlQwumSonH1Sxqcb1q521FhNGgZugoinZNA,2513
|
|
24
|
+
asteroid_odyssey/agents_v1_gen/models/execution_result.py,sha256=o6V8oHt9QR7vfRcCrnHwk8exwALUollWBfShze_lzBM,3354
|
|
25
|
+
asteroid_odyssey/agents_v1_gen/models/execution_result_response.py,sha256=zBGBV9FOtCOFE9vDwfWEJkcKMkXYOHluo2ycJlW_S2A,3603
|
|
26
|
+
asteroid_odyssey/agents_v1_gen/models/execution_status_response.py,sha256=ykdr-9kRFmIs3FnmsYWrlX4s-096wlMy3BQX6CCdiBc,3050
|
|
27
|
+
asteroid_odyssey/agents_v1_gen/models/health_check200_response.py,sha256=x_6F6rhTvqpuMUFtD5ynLrUFY4vuVdkWfDRkTx2hVp0,2548
|
|
28
|
+
asteroid_odyssey/agents_v1_gen/models/health_check500_response.py,sha256=b6pG-pqUKkQ5oqmWWyakdr7YYjnTYYeZjoVHkcU-TSY,2533
|
|
29
|
+
asteroid_odyssey/agents_v1_gen/models/proxy_type.py,sha256=5AUJvncQEl77V3QLJCIidk-WQRU1BlhMJo9ARUUdo1Y,704
|
|
30
|
+
asteroid_odyssey/agents_v1_gen/models/status.py,sha256=tnt_4jdoMzcjo6J0vttf2QKLNK0FC9XcjZKbGC3sbz0,889
|
|
31
|
+
asteroid_odyssey/agents_v1_gen/models/structured_agent_execution_request.py,sha256=VZyW85pVz9T27aiG4ZlGywnnxTOaJCAjHSDz8D2YxY8,2913
|
|
32
|
+
asteroid_odyssey/agents_v1_gen/models/update_agent_profile_request.py,sha256=ZggUpiv1G87Ds85n7XDCR0Lc3buwK-1C2kt0Zp3xUM0,5646
|
|
33
|
+
asteroid_odyssey/agents_v1_gen/models/upload_execution_files200_response.py,sha256=u85oEP2bEuhszonE78VcrB_keT0UZpv16CTGvfse_v4,2735
|
|
34
|
+
asteroid_odyssey/agents_v2_gen/__init__.py,sha256=YNowdnGKWF2EMi7BfujX5aZuuILj2xCn8ObvrshcDgg,8895
|
|
35
|
+
asteroid_odyssey/agents_v2_gen/api_client.py,sha256=5-DkUzSQSF8wRtHdsj3kAHulIPXr4JT208dZVnVA-uI,27807
|
|
36
|
+
asteroid_odyssey/agents_v2_gen/api_response.py,sha256=eMxw1mpmJcoGZ3gs9z6jM4oYoZ10Gjk333s9sKxGv7s,652
|
|
37
|
+
asteroid_odyssey/agents_v2_gen/configuration.py,sha256=Yd0DkWDdOlu6WFCN3zk3iK_zTufQeivQfmkuwa2EWu8,18931
|
|
38
|
+
asteroid_odyssey/agents_v2_gen/exceptions.py,sha256=UnVNkXG6lZtS5J3YpOcPu3rg5SUP1XRwSyYJl30rM0M,6474
|
|
39
|
+
asteroid_odyssey/agents_v2_gen/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
|
+
asteroid_odyssey/agents_v2_gen/rest.py,sha256=QqZeidPIb2Qk0BnQ_LuE6aJBuhxTmTraNYS70d-8XGQ,9487
|
|
41
|
+
asteroid_odyssey/agents_v2_gen/api/__init__.py,sha256=jvLhL8WKW4InzOreSDe3WhP-Uo37bExtU5Lrn-mwB_w,118
|
|
42
|
+
asteroid_odyssey/agents_v2_gen/api/default_api.py,sha256=rHjS8Ikp6GAVN9ECnc35uE4BeMAu9BqF_pQhq9BOL2s,47754
|
|
43
|
+
asteroid_odyssey/agents_v2_gen/models/__init__.py,sha256=uUT8Zw-i0hNN0LeTjtyaIc0OsI7G6dZPzDbHFXB-B7E,4861
|
|
44
|
+
asteroid_odyssey/agents_v2_gen/models/activity_payload_union_action_completed.py,sha256=gVlMAXp-Ydq34A-chIQawsjNMBdaiIudn2Nxu6XbcAY,3414
|
|
45
|
+
asteroid_odyssey/agents_v2_gen/models/activity_payload_union_action_failed.py,sha256=HF2es7XXOhpAcbTd2WAy7i0RyCfkot6FsZPn6UKkAuA,3384
|
|
46
|
+
asteroid_odyssey/agents_v2_gen/models/activity_payload_union_action_started.py,sha256=-lMn_Sj_Ci27NqsH345jhq0PjXoCPXRBeREkc18FVZU,3394
|
|
47
|
+
asteroid_odyssey/agents_v2_gen/models/activity_payload_union_file_added.py,sha256=1j0eL5GgcRO9l9LP3ChZaOw2IAXz0bqOGXzLFWiuQn8,3354
|
|
48
|
+
asteroid_odyssey/agents_v2_gen/models/activity_payload_union_generic.py,sha256=4wyRtRR73Sv1q7mjyVtDrmoW6D98xRvh6nTQEsasmnY,3331
|
|
49
|
+
asteroid_odyssey/agents_v2_gen/models/activity_payload_union_status_changed.py,sha256=d_Y43Wr8LGzjFDvuOQS2BcqF-127deg0bBpPtSjdcHY,3394
|
|
50
|
+
asteroid_odyssey/agents_v2_gen/models/activity_payload_union_step_completed.py,sha256=MF58NYdi_r-ix3yrY6huqQKYKFIQBM-bUn231eGbLjo,3394
|
|
51
|
+
asteroid_odyssey/agents_v2_gen/models/activity_payload_union_step_started.py,sha256=3dPj9xwnRY2CoabU1ILe_hPvcZvicMVEWEnxGbCbMJ0,3374
|
|
52
|
+
asteroid_odyssey/agents_v2_gen/models/activity_payload_union_terminal.py,sha256=B9p8Uqnuh8OEPXqZQoupBAHctbUqGgE1Q5SFkh3QwIU,3308
|
|
53
|
+
asteroid_odyssey/agents_v2_gen/models/activity_payload_union_transitioned_node.py,sha256=3_yDUszoQac4_MI5VxYpf0KvMIoIvQSw8VYZPqiDBeU,3424
|
|
54
|
+
asteroid_odyssey/agents_v2_gen/models/activity_payload_union_user_message_received.py,sha256=U5XMxiPSfxntvFBnJwAQnYCi55y8DNO5hTas3ZIjzQE,3457
|
|
55
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity.py,sha256=ZaqHV8COfTp_uCk6zQcyAigsaZwpm1RloaPeC6oQ4-g,3228
|
|
56
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_action_completed_payload.py,sha256=UnHxt4cfv1TbNsQ_6pTcrQqCLpWi5IQ_p7kv-HWPFF8,2611
|
|
57
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_action_failed_payload.py,sha256=Ms4yDc7s2fNyBhLqB0mST6v3gFviaoH0JNM45P2Qzns,2599
|
|
58
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_action_started_payload.py,sha256=AU9erFl0z9RgS49ZBdlEgHRxLSnpAAME4pyPmGOaF3c,2603
|
|
59
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_file_added_payload.py,sha256=iWN5FUFyoQgyDghWSdXRmPOG6E2GbxXiNXogcQGOmNM,3431
|
|
60
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_generic_payload.py,sha256=7MweXfhGyd2eSckTh86-FBp_FMOjHx-XJ_QIJ926nI4,2579
|
|
61
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_payload_union.py,sha256=23nfUW1WwpqyHzrdsY5z3x3NCy7Y-6sUbChb7pr8qdg,16040
|
|
62
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_status_changed_payload.py,sha256=U4wWCj5UXUYwg1Dprq7xf6tA2sjW9d9Q5CzzmmEqNro,5823
|
|
63
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_step_completed_payload.py,sha256=lIdf1SgIhTZpMz0t2Jd9Mn4uX-ZCzsRYFZqa3F5Ge5Y,2651
|
|
64
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_step_started_payload.py,sha256=Ey6hBAi9Ovzh8VELa6q1Ob5gWyASZ7nf-oknxyu8rr8,2643
|
|
65
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_transitioned_node_payload.py,sha256=vjHsh3yRgSuyJA-DQOYKwGft0lq_NTNC8lP6aaXQTO4,2793
|
|
66
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_activity_user_message_received_payload.py,sha256=Sn2v55vYwgb6uhjVWd12ZogZooJTZ-XzSz1EDos5ucc,2742
|
|
67
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_awaiting_confirmation_payload.py,sha256=ebQJgeBSCQpLM_Z601NFSg8xQF9b5MsvGVY59dgCWW4,2595
|
|
68
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_cancel_reason.py,sha256=oOJGrFL0N4BYFQLcT8WfBCbhk2ccyly733vqwEd-Ewc,843
|
|
69
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_cancelled_payload.py,sha256=1rU132jiPc4Ol2S8VqzAn0SDglL6UjcSNDpP-QHuD9Q,2667
|
|
70
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_completed_payload.py,sha256=1ZC5upBHqQhB4IgLONrISvj7OZxOibi0Ls5RDST-wBs,3330
|
|
71
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_failed_payload.py,sha256=hCmL2EpSQoHZFDNH2q8zVot0k5UBkJ9f-XdIVsSo998,2539
|
|
72
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_paused_payload.py,sha256=slW-OsLyXs3JyDE9Zx8YGIU2y0msgoKCbHDG8IkYG8k,2539
|
|
73
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_status.py,sha256=xGM7e94JQGqf9tA4nl0hpmJWFLTIyLhPDLR-bnx_QuY,977
|
|
74
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_terminal_payload.py,sha256=R03OwsvXt6wTv7pHO6Ux6h9kqpIZX5KBnctf8GM0wmE,2959
|
|
75
|
+
asteroid_odyssey/agents_v2_gen/models/agents_execution_user_messages_add_text_body.py,sha256=RvfuJaVRDkEunpPBdLBVEfj7muuIokoQXHxZJ_o1FHE,2583
|
|
76
|
+
asteroid_odyssey/agents_v2_gen/models/agents_files_file.py,sha256=nw4_8muCPxjAaRkjXNtM3iD-_IBwOjjX223q9pq7R5s,3613
|
|
77
|
+
asteroid_odyssey/agents_v2_gen/models/common_bad_request_error_body.py,sha256=cZQcZH6c2RmQleZe57-mfUsCKW74lGGtVMWbJFGc1ho,2889
|
|
78
|
+
asteroid_odyssey/agents_v2_gen/models/common_forbidden_error_body.py,sha256=9yADAujD_9eTW4BtZ7oYifmFCDTpAw-j1jEEJhwdAVs,2885
|
|
79
|
+
asteroid_odyssey/agents_v2_gen/models/common_not_found_error_body.py,sha256=BAVAweVD5ltGL2lWfdDNwaq82CI4iVkPVE_E9JfEpi8,2881
|
|
80
|
+
asteroid_odyssey/agents_v2_gen/models/version.py,sha256=Vjiri_a5CcDJ1lSziRqif5HuFpaxneVDLIB1r8SFIkE,707
|
|
81
|
+
asteroid_odyssey-1.3.4.dist-info/METADATA,sha256=n_kHfoad4D8d4BvE2S0XnC3gjLGdCpsGK-TYNbrtv-4,7108
|
|
82
|
+
asteroid_odyssey-1.3.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
83
|
+
asteroid_odyssey-1.3.4.dist-info/top_level.txt,sha256=h4T6NKscnThJ4Nhzors2NKlJeZzepnM7XvDgsnfi5HA,17
|
|
84
|
+
asteroid_odyssey-1.3.4.dist-info/RECORD,,
|