Skip to content

Commit 1e76273

Browse files
committed
chore: release version 0.5.0
This release includes the following changes: New Features: - Context Clear API: Added clear_async, get_clear_status, and synchronous clear methods with configurable timeout and state tracking - SDK Telemetry: Session creation now records SDK version and release status - Context Sync Enhancements: Introduced UploadMode and lifecycle enums for flexible synchronization policies - Session Parameters: Made image_id optional in CreateSessionParams - Browser Module: Added variables parameter to ActOptions for parameterized automation instructions - Browser Module: Added use_vision parameter to ObserveOptions and ExtractOptions API Changes: - Added ClearContextRequest and ClearContextResponse models - Enhanced ContextService with clear operations - Updated ContextSync with new upload modes and lifecycle policies - Added version_utils and _release modules for SDK versioning Documentation: - Updated API reference documentation for all modules - Enhanced context usage guide and sync policy documentation - Updated examples and guides to reflect new features - Fixed documentation formatting issues Testing: - Added unit tests for Code, Command, FileSystem, ContextManager modules - Added integration tests for context clear operations - Added tests for recycle policy and file archive mode Files Changed: - 48 files modified, 1216 insertions(+), 511 deletions(-) - New files: clear_context_request.py, clear_context_response.py, version_utils.py, _release.py, and multiple test files
1 parent b2c37c5 commit 1e76273

66 files changed

Lines changed: 5740 additions & 983 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,3 @@ dmypy.json
133133
.cursorrules
134134
CLAUDE.md
135135
.DS_Store
136-
137-
# Dual repository management scripts and files
138-
scripts/dual-repo-management/
139-
sync-internal-to-external.sh
140-
sync-external-to-internal.sh
141-
DUAL_DIRECTORY_WORKFLOW.md

CHANGES.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,36 @@
11
# Changelog
22

3+
## [0.5.0] - 2025-11-20
4+
5+
### New Features
6+
- **Context Clear API**: Added `clear_async`, `get_clear_status`, and synchronous `clear` with
7+
configurable timeout, poll interval, and explicit state tracking.
8+
- **SDK Telemetry**: Session creation now records SDK version and release status, with explicit
9+
release flagging injected during the official build process.
10+
- **Context Sync Enhancements**: Introduced `UploadMode` and lifecycle enums for more flexible
11+
synchronization policies.
12+
- **Session Parameters**: Enforced `image_id` as a required field in `CreateSessionParams`,
13+
improving validation and error messaging.
14+
- **Testing Framework**: Expanded unit tests to cover Code, Command, FileSystem, ContextManager,
15+
SessionParams, response models, and context clear flows.
16+
17+
### Bug Fixes
18+
- Added `error_message` propagation to `ContextSyncResult`, ensuring API failures surface in sync
19+
results.
20+
- Aligned sample code and tests to use valid `image_id` values and consistent data paths, fixing
21+
persistence-related flakes.
22+
23+
### Documentation
24+
- Updated context usage guide, sync policy docs, API references, and data persistence examples to
25+
reflect the new features.
26+
27+
### Testing & CI
28+
- Added a RecyclePolicy integration test and tightened context sync test coverage, including path
29+
uniqueness checks.
30+
- CI now runs unit tests by default, installs pytest automatically, and includes pipeline
31+
optimizations plus master-branch triggers.
32+
33+
334
## [0.4.0] - 2025-10-31
435

536
### New Features

agb/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from .session_params import CreateSessionParams
66
from .context import Context, ContextService, ContextResult, ContextListResult
77
from .context_manager import ContextManager, ContextStatusData, ContextInfoResult, ContextSyncResult
8-
from .context_sync import ContextSync, SyncPolicy, UploadPolicy, DownloadPolicy, DeletePolicy, ExtractPolicy, UploadStrategy, DownloadStrategy
8+
from .context_sync import ContextSync, SyncPolicy, UploadPolicy, DownloadPolicy, DeletePolicy, ExtractPolicy, UploadStrategy, DownloadStrategy, UploadMode
99
from .extension import ExtensionsService, ExtensionOption, Extension
1010

1111
__all__ = [
@@ -14,5 +14,5 @@
1414
"Context", "ContextService", "ContextResult", "ContextListResult",
1515
"ContextManager", "ContextStatusData", "ContextInfoResult", "ContextSyncResult",
1616
"ContextSync", "SyncPolicy", "UploadPolicy", "DownloadPolicy", "DeletePolicy", "ExtractPolicy",
17-
"UploadStrategy", "DownloadStrategy","ExtensionsService","ExtensionOption","Extension",
17+
"UploadStrategy", "DownloadStrategy", "UploadMode", "ExtensionsService","ExtensionOption","Extension",
1818
]

agb/_release.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Release version flag.
4+
5+
This file is modified during the CI/CD build process to set IS_RELEASE_VERSION = True
6+
for official releases.
7+
"""
8+
9+
IS_RELEASE_VERSION = False
10+

agb/agb.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,15 @@
1515
CreateSessionResponse,
1616
CreateMcpSessionRequestPersistenceDataList,
1717
GetSessionRequest,
18-
GetSessionResponse,
1918
ListSessionRequest,
20-
ListSessionResponse,
2119
)
2220
from agb.config import Config, load_config
2321
from agb.model.response import DeleteResult, SessionResult, GetSessionResult, GetSessionData, SessionListResult
2422
from agb.session import BaseSession, Session
2523
from agb.session_params import CreateSessionParams
2624
from agb.context import ContextService
2725
from agb.logger import get_logger, log_operation_start, log_operation_success, log_warning
26+
from agb.version_utils import get_sdk_version, is_release_version
2827

2928
logger = get_logger(__name__)
3029

@@ -82,18 +81,43 @@ def create(self, params: Optional[CreateSessionParams] = None) -> SessionResult:
8281
"""
8382
try:
8483
if params is None:
85-
params = CreateSessionParams()
84+
error_msg = "params is required and cannot be None"
85+
logger.error(error_msg)
86+
return SessionResult(
87+
request_id="",
88+
success=False,
89+
error_message=error_msg,
90+
)
8691

87-
request = CreateSessionRequest(authorization=f"Bearer {self.api_key}")
92+
# Validate image_id is required
93+
if not params.image_id or (isinstance(params.image_id, str) and not params.image_id.strip()):
94+
error_msg = "image_id is required and cannot be empty or None"
95+
logger.error(error_msg)
96+
return SessionResult(
97+
request_id="",
98+
success=False,
99+
error_message=error_msg,
100+
)
88101

89-
if params.image_id:
90-
request.image_id = params.image_id
102+
request = CreateSessionRequest(authorization=f"Bearer {self.api_key}")
103+
request.image_id = params.image_id
91104

92-
# Add labels if provided
105+
# Add labels if provided
93106
if params.labels:
94107
# Convert labels to JSON string
95108
request.labels = json.dumps(params.labels)
96109

110+
# Add SDK stats for telemetry
111+
sdk_version = get_sdk_version()
112+
is_release = is_release_version()
113+
sdk_stats = {
114+
"source": "sdk",
115+
"sdk_language": "python",
116+
"sdk_version": sdk_version,
117+
"is_release": is_release
118+
}
119+
request.sdk_stats = sdk_stats
120+
97121
# Flag to indicate if we need to wait for context synchronization
98122
needs_context_sync = False
99123

agb/api/client.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
ModifyContextResponse,
4040
DeleteContextRequest,
4141
DeleteContextResponse,
42+
ClearContextRequest,
43+
ClearContextResponse,
4244
SyncContextRequest,
4345
SyncContextResponse,
4446
GetContextInfoRequest,
@@ -407,6 +409,23 @@ def delete_context(self, request: DeleteContextRequest) -> DeleteContextResponse
407409
# Always close the HTTP client to release resources
408410
http_client.close()
409411

412+
def clear_context(self, request: ClearContextRequest) -> ClearContextResponse:
413+
"""
414+
Clear context using HTTP client
415+
"""
416+
if not request.authorization:
417+
raise ValueError("authorization is required")
418+
419+
# Get HTTP client and make request directly with the input request
420+
http_client = self._get_http_client(request.authorization)
421+
422+
try:
423+
response = http_client.clear_context(request)
424+
return response
425+
finally:
426+
# Always close the HTTP client to release resources
427+
http_client.close()
428+
410429
def sync_context(self, request: SyncContextRequest) -> SyncContextResponse:
411430
"""
412431
Sync context using HTTP client

agb/api/http_client.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
from .models.modify_context_response import ModifyContextResponse
4646
from .models.delete_context_request import DeleteContextRequest
4747
from .models.delete_context_response import DeleteContextResponse
48+
from .models.clear_context_request import ClearContextRequest
49+
from .models.clear_context_response import ClearContextResponse
4850
from .models.sync_context_request import SyncContextRequest
4951
from .models.sync_context_response import SyncContextResponse
5052
from .models.get_context_info_request import GetContextInfoRequest
@@ -906,6 +908,37 @@ def delete_context(self, request: DeleteContextRequest) -> DeleteContextResponse
906908
# Return structured response object
907909
return DeleteContextResponse.from_http_response(response_dict)
908910

911+
def clear_context(self, request: ClearContextRequest) -> ClearContextResponse:
912+
"""
913+
HTTP request interface for clearing context
914+
915+
Args:
916+
request (ClearContextRequest): Request object for clearing context
917+
918+
Returns:
919+
ClearContextResponse: Structured response object
920+
"""
921+
# Build request headers
922+
headers: Dict[str, str] = {}
923+
924+
# Build query parameters
925+
params = request.get_params()
926+
927+
# Build request body
928+
body = request.get_body()
929+
930+
# Call _make_request
931+
response_dict = self._make_request(
932+
method="POST",
933+
endpoint="/sdk/ClearContext",
934+
headers=headers,
935+
params=params,
936+
json_data=body,
937+
)
938+
939+
# Return structured response object
940+
return ClearContextResponse.from_http_response(response_dict)
941+
909942
def sync_context(self, request: SyncContextRequest) -> SyncContextResponse:
910943
"""
911944
HTTP request interface for syncing context

agb/api/models/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
from .modify_context_response import ModifyContextResponse
3535
from .delete_context_request import DeleteContextRequest
3636
from .delete_context_response import DeleteContextResponse
37+
from .clear_context_request import ClearContextRequest
38+
from .clear_context_response import ClearContextResponse
3739
from .sync_context_request import SyncContextRequest
3840
from .sync_context_response import SyncContextResponse
3941
from .get_context_info_request import GetContextInfoRequest
@@ -80,6 +82,8 @@
8082
"ModifyContextResponse",
8183
"DeleteContextRequest",
8284
"DeleteContextResponse",
85+
"ClearContextRequest",
86+
"ClearContextResponse",
8387
"SyncContextRequest",
8488
"SyncContextResponse",
8589
"GetContextInfoRequest",
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from typing import Optional
2+
3+
4+
class ClearContextRequest:
5+
"""Request model for clearing a context."""
6+
7+
def __init__(
8+
self,
9+
authorization: str = "",
10+
id: str = "",
11+
):
12+
"""
13+
Initialize ClearContextRequest.
14+
15+
Args:
16+
authorization (str): Authorization token.
17+
id (str): ID of the context to clear.
18+
"""
19+
self.authorization = authorization
20+
self.id = id
21+
22+
def get_params(self) -> dict:
23+
"""Get the query parameters as a dictionary."""
24+
params = {}
25+
if self.id:
26+
params["id"] = self.id
27+
return params
28+
29+
def get_body(self) -> dict:
30+
"""Get the request body as a dictionary."""
31+
return {}
32+
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""
2+
Clear context response model
3+
"""
4+
5+
from typing import Any, Dict, Optional
6+
7+
8+
class ClearContextResponse:
9+
"""Structured response object for clear context operation"""
10+
11+
def __init__(
12+
self,
13+
status_code: int = 0,
14+
url: str = "",
15+
headers: Optional[Dict[str, str]] = None,
16+
json_data: Optional[Dict[str, Any]] = None,
17+
request_id: Optional[str] = None,
18+
):
19+
"""
20+
Initialize ClearContextResponse
21+
22+
Args:
23+
status_code (int): HTTP status code
24+
url (str): Request URL
25+
headers (Dict[str, str]): Response headers
26+
json_data (Dict[str, Any]): JSON response data
27+
request_id (str): Request ID
28+
"""
29+
self.status_code = status_code
30+
self.url = url
31+
self.headers = headers or {}
32+
self.json_data = json_data or {}
33+
self.request_id = request_id
34+
35+
if json_data:
36+
self.api_success = json_data.get("success", False)
37+
self.code = json_data.get("code", "")
38+
self.http_status_code = json_data.get("httpStatusCode", "")
39+
self.message = json_data.get("message", "")
40+
else:
41+
self.api_success = False
42+
self.code = None
43+
self.http_status_code = None
44+
self.message = ""
45+
46+
@classmethod
47+
def from_http_response(cls, response_dict: Dict[str, Any]) -> "ClearContextResponse":
48+
"""
49+
Create ClearContextResponse from HTTP client returned dictionary
50+
51+
Args:
52+
response_dict: Dictionary returned by HTTP client
53+
54+
Returns:
55+
ClearContextResponse: Structured response object
56+
"""
57+
return cls(
58+
status_code=response_dict.get("status_code", 0),
59+
url=response_dict.get("url", ""),
60+
headers=response_dict.get("headers", {}),
61+
json_data=response_dict.get("json"),
62+
request_id=response_dict.get("request_id")
63+
or (
64+
response_dict.get("json", {}).get("requestId")
65+
if response_dict.get("json")
66+
else None
67+
),
68+
)
69+
70+
def is_successful(self) -> bool:
71+
"""Check if the operation was successful"""
72+
return self.status_code == 200 and self.api_success
73+
74+
def get_error_message(self) -> str:
75+
"""Get error message if operation failed"""
76+
if not self.is_successful():
77+
return self.message or f"HTTP {self.status_code} error"
78+
return ""
79+

0 commit comments

Comments
 (0)