Files
wehub-resource-sync a7d6d88f6f
CI / changes (push) Has been cancelled
CI / cd libs/checkpoint (push) Has been cancelled
CI / cd libs/checkpoint-conformance (push) Has been cancelled
CI / cd libs/checkpoint-postgres (push) Has been cancelled
CI / cd libs/checkpoint-sqlite (push) Has been cancelled
CI / cd libs/cli (push) Has been cancelled
CI / cd libs/prebuilt (push) Has been cancelled
CI / cd libs/sdk-py (push) Has been cancelled
CI / cd libs/langgraph (push) Has been cancelled
CI / Check SDK methods matching (push) Has been cancelled
CI / Check CLI schema hasn't changed #3.13 (push) Has been cancelled
CI / CLI integration test (push) Has been cancelled
CI / sdk-py integration test (push) Has been cancelled
CI / CI Success (push) Has been cancelled
baseline / benchmark (push) Has been cancelled
Deploy Redirects to GitHub Pages / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:37:18 +08:00

314 lines
10 KiB
Python

"""Synchronous store client for LangGraph SDK."""
from __future__ import annotations
from collections.abc import Mapping, Sequence
from typing import Any, Literal
from langgraph_sdk._shared.utilities import _provided_vals
from langgraph_sdk._sync.http import SyncHttpClient
from langgraph_sdk.schema import (
Item,
ListNamespaceResponse,
QueryParamTypes,
SearchItemsResponse,
)
class SyncStoreClient:
"""A client for synchronous operations on a key-value store.
Provides methods to interact with a remote key-value store, allowing
storage and retrieval of items within namespaced hierarchies.
???+ example "Example"
```python
client = get_sync_client(url="http://localhost:2024"))
client.store.put_item(["users", "profiles"], "user123", {"name": "Alice", "age": 30})
```
"""
def __init__(self, http: SyncHttpClient) -> None:
self.http = http
def put_item(
self,
namespace: Sequence[str],
/,
key: str,
value: Mapping[str, Any],
index: Literal[False] | list[str] | None = None,
ttl: int | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Store or update an item.
Args:
namespace: A list of strings representing the namespace path.
key: The unique identifier for the item within the namespace.
value: A dictionary containing the item's data.
index: Controls search indexing - None (use defaults), False (disable), or list of field paths to index.
ttl: Optional time-to-live in minutes for the item, or None for no expiration.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
client.store.put_item(
["documents", "user123"],
key="item456",
value={"title": "My Document", "content": "Hello World"}
)
```
"""
for label in namespace:
if "." in label:
raise ValueError(
f"Invalid namespace label '{label}'. Namespace labels cannot contain periods ('.')."
)
payload = {
"namespace": namespace,
"key": key,
"value": value,
"index": index,
"ttl": ttl,
}
self.http.put(
"/store/items", json=_provided_vals(payload), headers=headers, params=params
)
def get_item(
self,
namespace: Sequence[str],
/,
key: str,
*,
refresh_ttl: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Item:
"""Retrieve a single item.
Args:
key: The unique identifier for the item.
namespace: Optional list of strings representing the namespace path.
refresh_ttl: Whether to refresh the TTL on this read operation. If `None`, uses the store's default behavior.
headers: Optional custom headers to include with the request.
Returns:
The retrieved item.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
item = client.store.get_item(
["documents", "user123"],
key="item456",
)
print(item)
```
```shell
----------------------------------------------------------------
{
'namespace': ['documents', 'user123'],
'key': 'item456',
'value': {'title': 'My Document', 'content': 'Hello World'},
'created_at': '2024-07-30T12:00:00Z',
'updated_at': '2024-07-30T12:00:00Z'
}
```
"""
for label in namespace:
if "." in label:
raise ValueError(
f"Invalid namespace label '{label}'. Namespace labels cannot contain periods ('.')."
)
query_params: dict[str, Any] = {"key": key, "namespace": ".".join(namespace)}
if refresh_ttl is not None:
query_params["refresh_ttl"] = refresh_ttl
if params:
query_params.update(params)
return self.http.get("/store/items", params=query_params, headers=headers)
def delete_item(
self,
namespace: Sequence[str],
/,
key: str,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Delete an item.
Args:
key: The unique identifier for the item.
namespace: Optional list of strings representing the namespace path.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
client.store.delete_item(
["documents", "user123"],
key="item456",
)
```
"""
self.http.delete(
"/store/items",
json={"key": key, "namespace": namespace},
headers=headers,
params=params,
)
def search_items(
self,
namespace_prefix: Sequence[str],
/,
filter: Mapping[str, Any] | None = None,
limit: int = 10,
offset: int = 0,
query: str | None = None,
refresh_ttl: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> SearchItemsResponse:
"""Search for items within a namespace prefix.
Args:
namespace_prefix: List of strings representing the namespace prefix.
filter: Optional dictionary of key-value pairs to filter results.
limit: Maximum number of items to return (default is 10).
offset: Number of items to skip before returning results (default is 0).
query: Optional query for natural language search.
refresh_ttl: Whether to refresh the TTL on items returned by this search. If `None`, uses the store's default behavior.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
A list of items matching the search criteria.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
items = client.store.search_items(
["documents"],
filter={"author": "John Doe"},
limit=5,
offset=0
)
print(items)
```
```shell
----------------------------------------------------------------
{
"items": [
{
"namespace": ["documents", "user123"],
"key": "item789",
"value": {
"title": "Another Document",
"author": "John Doe"
},
"created_at": "2024-07-30T12:00:00Z",
"updated_at": "2024-07-30T12:00:00Z"
},
# ... additional items ...
]
}
```
"""
payload = {
"namespace_prefix": namespace_prefix,
"filter": filter,
"limit": limit,
"offset": offset,
"query": query,
"refresh_ttl": refresh_ttl,
}
return self.http.post(
"/store/items/search",
json=_provided_vals(payload),
headers=headers,
params=params,
)
def list_namespaces(
self,
prefix: list[str] | None = None,
suffix: list[str] | None = None,
max_depth: int | None = None,
limit: int = 100,
offset: int = 0,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> ListNamespaceResponse:
"""List namespaces with optional match conditions.
Args:
prefix: Optional list of strings representing the prefix to filter namespaces.
suffix: Optional list of strings representing the suffix to filter namespaces.
max_depth: Optional integer specifying the maximum depth of namespaces to return.
limit: Maximum number of namespaces to return (default is 100).
offset: Number of namespaces to skip before returning results (default is 0).
headers: Optional custom headers to include with the request.
Returns:
A list of namespaces matching the criteria.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
namespaces = client.store.list_namespaces(
prefix=["documents"],
max_depth=3,
limit=10,
offset=0
)
print(namespaces)
```
```shell
----------------------------------------------------------------
[
["documents", "user123", "reports"],
["documents", "user456", "invoices"],
...
]
```
"""
payload = {
"prefix": prefix,
"suffix": suffix,
"max_depth": max_depth,
"limit": limit,
"offset": offset,
}
return self.http.post(
"/store/namespaces",
json=_provided_vals(payload),
headers=headers,
params=params,
)