Skip to content

Commit 3a2df48

Browse files
author
zhansheng.lzs
committed
merge: origin/main into dev/v2
Resolve the samples/test_agentstudio.py modify/delete conflict by keeping it deleted; its memory-stores flow is ported into examples/legacy_1x/agentstudio.py.
2 parents b635966 + 85a08cf commit 3a2df48

11 files changed

Lines changed: 1710 additions & 5 deletions

File tree

‎dashscope/agentstudio/__init__.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
CursorPage,
5252
)
5353
from .types import (
54+
Memory,
55+
MemoryStore,
56+
MemoryVersion,
5457
Message,
5558
PermissionPolicy,
5659
SecurityAlert,
@@ -117,6 +120,9 @@
117120
"CursorPage",
118121
"AsyncCursorPage",
119122
# unified message type
123+
"Memory",
124+
"MemoryStore",
125+
"MemoryVersion",
120126
"Message",
121127
"PermissionPolicy",
122128
"SecurityAlert",

‎dashscope/agentstudio/client.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
AsyncEnvironments,
2222
)
2323
from dashscope.agentstudio.resources.files import Files, AsyncFiles
24+
from dashscope.agentstudio.resources.memory_stores import (
25+
MemoryStores,
26+
AsyncMemoryStores,
27+
)
2428
from dashscope.agentstudio.resources.security import Security, AsyncSecurity
2529
from dashscope.agentstudio.resources.sessions import Sessions, AsyncSessions
2630
from dashscope.agentstudio.resources.skills import Skills, AsyncSkills
@@ -144,6 +148,7 @@ def __init__(
144148
self.files = Files(self)
145149
self.skills = Skills(self)
146150
self.vaults = Vaults(self)
151+
self.memory_stores = MemoryStores(self)
147152
self.webhook_endpoints = WebhookEndpoints(self)
148153
self.security = Security(self)
149154

@@ -218,6 +223,7 @@ def __init__(
218223
self.files = AsyncFiles(self)
219224
self.skills = AsyncSkills(self)
220225
self.vaults = AsyncVaults(self)
226+
self.memory_stores = AsyncMemoryStores(self)
221227
self.webhook_endpoints = AsyncWebhookEndpoints(self)
222228
self.security = AsyncSecurity(self)
223229

‎dashscope/agentstudio/pagination.py‎

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@
2525

2626

2727
class CursorPage(Generic[T]):
28-
"""Synchronous page over an opaque ``page`` cursor."""
28+
"""Synchronous page over an opaque ``page`` cursor.
29+
30+
``extra`` preserves any additional top-level fields the list
31+
envelope carried beyond ``data`` / ``next_page`` (forward
32+
compatibility when the server adds fields); ``extra`` is per page
33+
and does not participate in auto-pagination.
34+
"""
2935

3036
def __init__(
3137
self,
@@ -34,11 +40,13 @@ def __init__(
3440
next_page: Optional[str],
3541
request_id: Optional[str],
3642
fetch_next: Optional[Callable[[str], "CursorPage[T]"]] = None,
43+
extra: Optional[Dict[str, Any]] = None,
3744
) -> None:
3845
self.data = data
3946
self.next_page = next_page
4047
self.request_id = request_id
4148
self._fetch_next = fetch_next
49+
self.extra: Dict[str, Any] = dict(extra or {})
4250

4351
def has_next(self) -> bool:
4452
return bool(self.next_page) and self._fetch_next is not None
@@ -66,9 +74,20 @@ def __len__(self) -> int:
6674
"""
6775
return len(self.data)
6876

77+
@property
78+
def prefixes(self) -> List[str]:
79+
"""Directory prefixes of a tree-style listing (memory only)."""
80+
81+
raw = self.extra.get("prefixes") or []
82+
return list(raw) if isinstance(raw, (list, tuple)) else []
83+
6984

7085
class AsyncCursorPage(Generic[T]):
71-
"""Asynchronous page over an opaque ``page`` cursor."""
86+
"""Asynchronous page over an opaque ``page`` cursor.
87+
88+
See :class:`CursorPage` for the ``extra`` forward-compatibility
89+
bag.
90+
"""
7291

7392
def __init__(
7493
self,
@@ -77,11 +96,13 @@ def __init__(
7796
next_page: Optional[str],
7897
request_id: Optional[str],
7998
fetch_next: Optional[Callable[[str], "AsyncCursorPage[T]"]] = None,
99+
extra: Optional[Dict[str, Any]] = None,
80100
) -> None:
81101
self.data = data
82102
self.next_page = next_page
83103
self.request_id = request_id
84104
self._fetch_next = fetch_next
105+
self.extra: Dict[str, Any] = dict(extra or {})
85106

86107
def has_next(self) -> bool:
87108
return bool(self.next_page) and self._fetch_next is not None
@@ -115,6 +136,13 @@ def __len__(self) -> int:
115136
"""
116137
return len(self.data)
117138

139+
@property
140+
def prefixes(self) -> List[str]:
141+
"""Directory prefixes of a tree-style listing (memory only)."""
142+
143+
raw = self.extra.get("prefixes") or []
144+
return list(raw) if isinstance(raw, (list, tuple)) else []
145+
118146

119147
def build_page(
120148
*,
@@ -124,16 +152,25 @@ def build_page(
124152
request_id: Optional[str] = None,
125153
page_cls: type = CursorPage,
126154
) -> Any:
127-
"""Hydrate a page object from a normalized payload."""
155+
"""Hydrate a page object from a normalized payload.
156+
157+
Envelope fields beyond ``data`` / ``next_page`` are preserved on
158+
the page's ``extra`` forward-compatibility bag (mirrors
159+
``BaseModel.extra``).
160+
"""
128161

129162
items_raw = payload.get("data") or []
130163
items: List[T] = [
131164
item_factory(it) for it in items_raw if isinstance(it, dict)
132165
]
133166
next_page = payload.get("next_page")
167+
extra = {
168+
k: v for k, v in payload.items() if k not in ("data", "next_page")
169+
}
134170
return page_cls(
135171
data=items,
136172
next_page=next_page,
137173
request_id=request_id,
138174
fetch_next=fetch_next,
175+
extra=extra,
139176
)

‎dashscope/agentstudio/resources/__init__.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@
2727
AsyncEnvironments,
2828
)
2929
from dashscope.agentstudio.resources.files import Files, AsyncFiles
30+
from dashscope.agentstudio.resources.memory_stores import (
31+
AsyncMemories,
32+
AsyncMemoryStores,
33+
AsyncMemoryVersions,
34+
Memories,
35+
MemoryStores,
36+
MemoryVersions,
37+
)
3038
from dashscope.agentstudio.resources.session_events import (
3139
AsyncSessionEvents,
3240
SessionEvents,
@@ -74,6 +82,12 @@
7482
"AsyncSessionEvents",
7583
"Vaults",
7684
"AsyncVaults",
85+
"MemoryStores",
86+
"AsyncMemoryStores",
87+
"Memories",
88+
"AsyncMemories",
89+
"MemoryVersions",
90+
"AsyncMemoryVersions",
7791
"WebhookEndpoints",
7892
"AsyncWebhookEndpoints",
7993
"_TypedEventStream",

‎dashscope/agentstudio/resources/_helpers.py‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
DeploymentRun,
1515
Environment,
1616
File,
17+
Memory,
18+
MemoryStore,
19+
MemoryVersion,
1720
ServerEvent,
1821
Session,
1922
SessionResource,
@@ -103,6 +106,18 @@ def _coerce_deployment_run(payload: Mapping[str, Any]) -> DeploymentRun:
103106
return DeploymentRun(**dict(payload))
104107

105108

109+
def _coerce_memory_store(payload: Mapping[str, Any]) -> MemoryStore:
110+
return MemoryStore(**dict(payload))
111+
112+
113+
def _coerce_memory(payload: Mapping[str, Any]) -> Memory:
114+
return Memory(**dict(payload))
115+
116+
117+
def _coerce_memory_version(payload: Mapping[str, Any]) -> MemoryVersion:
118+
return MemoryVersion(**dict(payload))
119+
120+
106121
# ---------------------------------------------------------------------------
107122
# Path helpers
108123
# ---------------------------------------------------------------------------
@@ -138,3 +153,35 @@ def _session_thread_events_path(session_id: str, thread_id: str) -> str:
138153

139154
def _session_thread_archive_path(session_id: str, thread_id: str) -> str:
140155
return f"/sessions/{session_id}/threads/{thread_id}/archive"
156+
157+
158+
def _memory_stores_path() -> str:
159+
return "/memory_stores"
160+
161+
162+
def _memory_store_item_path(store_id: str) -> str:
163+
return f"/memory_stores/{store_id}"
164+
165+
166+
def _memory_store_archive_path(store_id: str) -> str:
167+
return f"/memory_stores/{store_id}/archive"
168+
169+
170+
def _memories_path(store_id: str) -> str:
171+
return f"/memory_stores/{store_id}/memories"
172+
173+
174+
def _memory_item_path(store_id: str, memory_id: str) -> str:
175+
return f"/memory_stores/{store_id}/memories/{memory_id}"
176+
177+
178+
def _memory_versions_path(store_id: str) -> str:
179+
return f"/memory_stores/{store_id}/memory_versions"
180+
181+
182+
def _memory_version_item_path(store_id: str, version_id: str) -> str:
183+
return f"/memory_stores/{store_id}/memory_versions/{version_id}"
184+
185+
186+
def _memory_version_redact_path(store_id: str, version_id: str) -> str:
187+
return f"/memory_stores/{store_id}/memory_versions/{version_id}/redact"

0 commit comments

Comments
 (0)