memcode-sdk 2.3.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.
- memcode_sdk/__init__.py +104 -0
- memcode_sdk/_http.py +162 -0
- memcode_sdk/async_client.py +277 -0
- memcode_sdk/async_v2_client.py +147 -0
- memcode_sdk/client.py +576 -0
- memcode_sdk/errors.py +64 -0
- memcode_sdk/py.typed +1 -0
- memcode_sdk/types.py +172 -0
- memcode_sdk/v2_client.py +214 -0
- memcode_sdk/v2_types.py +116 -0
- memcode_sdk-2.3.1.dist-info/METADATA +387 -0
- memcode_sdk-2.3.1.dist-info/RECORD +14 -0
- memcode_sdk-2.3.1.dist-info/WHEEL +5 -0
- memcode_sdk-2.3.1.dist-info/top_level.txt +1 -0
memcode_sdk/types.py
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Public data types returned by the Memcode SDK.
|
|
3
|
+
|
|
4
|
+
These are plain dataclasses / Pydantic models that mirror the API's
|
|
5
|
+
JSON responses but are fully typed for IDE auto-complete and safety.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from enum import Enum
|
|
12
|
+
from typing import Any, Dict, List, Optional
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# ── Shared envelope ────────────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
class Status(str, Enum):
|
|
18
|
+
OK = "ok"
|
|
19
|
+
ERROR = "error"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True)
|
|
23
|
+
class APIEnvelope:
|
|
24
|
+
"""Raw API envelope — internal use only."""
|
|
25
|
+
status: Status
|
|
26
|
+
data: Optional[Dict[str, Any]] = None
|
|
27
|
+
error: Optional[str] = None
|
|
28
|
+
request_id: Optional[str] = None
|
|
29
|
+
elapsed_ms: Optional[float] = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# ── Health ─────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True)
|
|
35
|
+
class HealthStatus:
|
|
36
|
+
status: str
|
|
37
|
+
pipelines_ready: bool
|
|
38
|
+
version: str = ""
|
|
39
|
+
uptime_seconds: Optional[float] = None
|
|
40
|
+
error: Optional[str] = None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# ── Ingest ─────────────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class OperationDetail:
|
|
47
|
+
type: str
|
|
48
|
+
content: str
|
|
49
|
+
reason: str
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass(frozen=True)
|
|
53
|
+
class WeaverSummary:
|
|
54
|
+
succeeded: int = 0
|
|
55
|
+
skipped: int = 0
|
|
56
|
+
failed: int = 0
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass(frozen=True)
|
|
60
|
+
class DomainResult:
|
|
61
|
+
confidence: float = 0.0
|
|
62
|
+
operations: List[OperationDetail] = field(default_factory=list)
|
|
63
|
+
weaver: Optional[WeaverSummary] = None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass(frozen=True)
|
|
67
|
+
class IngestResult:
|
|
68
|
+
"""Returned by ``client.ingest()``."""
|
|
69
|
+
model: str = ""
|
|
70
|
+
classification: List[Any] = field(default_factory=list)
|
|
71
|
+
profile: Optional[DomainResult] = None
|
|
72
|
+
temporal: Optional[DomainResult] = None
|
|
73
|
+
summary: Optional[DomainResult] = None
|
|
74
|
+
image: Optional[DomainResult] = None
|
|
75
|
+
request_id: Optional[str] = None
|
|
76
|
+
elapsed_ms: Optional[float] = None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass(frozen=True)
|
|
80
|
+
class PersonalV2IngestResult:
|
|
81
|
+
"""Durable receipt returned by personal ``/v2/memory/ingest``."""
|
|
82
|
+
job_id: str
|
|
83
|
+
status: str
|
|
84
|
+
created: bool
|
|
85
|
+
status_url: str
|
|
86
|
+
plan_id: Optional[str] = None
|
|
87
|
+
queued_for_batch: Optional[bool] = None
|
|
88
|
+
estimated_available_in_seconds: Optional[float] = None
|
|
89
|
+
request_id: Optional[str] = None
|
|
90
|
+
elapsed_ms: Optional[float] = None
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@dataclass(frozen=True)
|
|
94
|
+
class PersonalV2IngestStatus:
|
|
95
|
+
job_id: str
|
|
96
|
+
status: str
|
|
97
|
+
job_type: Optional[str] = None
|
|
98
|
+
retry_count: int = 0
|
|
99
|
+
attempt_count: int = 0
|
|
100
|
+
max_attempts: int = 0
|
|
101
|
+
timeout_seconds: Optional[float] = None
|
|
102
|
+
workflow_id: Optional[str] = None
|
|
103
|
+
run_id: Optional[str] = None
|
|
104
|
+
progress: Optional[Dict[str, Any]] = None
|
|
105
|
+
error: Any = None
|
|
106
|
+
error_state: Optional[Dict[str, Any]] = None
|
|
107
|
+
result: Optional[Dict[str, Any]] = None
|
|
108
|
+
created_at: Optional[str] = None
|
|
109
|
+
updated_at: Optional[str] = None
|
|
110
|
+
started_at: Optional[str] = None
|
|
111
|
+
completed_at: Optional[str] = None
|
|
112
|
+
dead_lettered_at: Optional[str] = None
|
|
113
|
+
cancelled_at: Optional[str] = None
|
|
114
|
+
request_id: Optional[str] = None
|
|
115
|
+
elapsed_ms: Optional[float] = None
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# ── Retrieve ───────────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
@dataclass(frozen=True)
|
|
121
|
+
class SourceRecord:
|
|
122
|
+
domain: str
|
|
123
|
+
content: str
|
|
124
|
+
score: float = 0.0
|
|
125
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@dataclass(frozen=True)
|
|
129
|
+
class RetrieveResult:
|
|
130
|
+
"""Returned by ``client.retrieve()``."""
|
|
131
|
+
model: str = ""
|
|
132
|
+
answer: str = ""
|
|
133
|
+
sources: List[SourceRecord] = field(default_factory=list)
|
|
134
|
+
confidence: float = 0.0
|
|
135
|
+
request_id: Optional[str] = None
|
|
136
|
+
elapsed_ms: Optional[float] = None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass(frozen=True)
|
|
140
|
+
class PersonalV2RetrieveResult(RetrieveResult):
|
|
141
|
+
used_source_indices: List[int] = field(default_factory=list)
|
|
142
|
+
connection_learning_queued: bool = False
|
|
143
|
+
used_refs: List[str] = field(default_factory=list)
|
|
144
|
+
billing: Optional[Dict[str, Any]] = None
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
# ── Search ─────────────────────────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
@dataclass(frozen=True)
|
|
150
|
+
class SearchResult:
|
|
151
|
+
"""Returned by ``client.search()``."""
|
|
152
|
+
results: List[SourceRecord] = field(default_factory=list)
|
|
153
|
+
total: int = 0
|
|
154
|
+
request_id: Optional[str] = None
|
|
155
|
+
elapsed_ms: Optional[float] = None
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@dataclass(frozen=True)
|
|
159
|
+
class HybridSearchResult:
|
|
160
|
+
"""Returned by unified personal v2 search and its deprecated hybrid alias."""
|
|
161
|
+
memory_results: List[SourceRecord] = field(default_factory=list)
|
|
162
|
+
original_chunks: List[SourceRecord] = field(default_factory=list)
|
|
163
|
+
results: List[SourceRecord] = field(default_factory=list)
|
|
164
|
+
total: int = 0
|
|
165
|
+
original_storage_enabled: bool = False
|
|
166
|
+
billing: Optional[Dict[str, Any]] = None
|
|
167
|
+
request_id: Optional[str] = None
|
|
168
|
+
elapsed_ms: Optional[float] = None
|
|
169
|
+
# Keep additive fields last so existing positional construction remains
|
|
170
|
+
# source-compatible.
|
|
171
|
+
failed_domains: List[str] = field(default_factory=list)
|
|
172
|
+
partial: bool = False
|
memcode_sdk/v2_client.py
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"""Synchronous client for tenant-bound Memcode v2 memory operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from typing import Any, Dict, List, Optional
|
|
7
|
+
from urllib.parse import quote
|
|
8
|
+
|
|
9
|
+
from ._http import DEFAULT_TIMEOUT, SyncTransport
|
|
10
|
+
from .v2_types import (
|
|
11
|
+
V2IngestResult,
|
|
12
|
+
V2IngestStatus,
|
|
13
|
+
V2MemorySource,
|
|
14
|
+
V2OperationCounts,
|
|
15
|
+
V2OriginalStorageStatus,
|
|
16
|
+
V2RetrieveResult,
|
|
17
|
+
V2SearchResult,
|
|
18
|
+
V2SourceLineage,
|
|
19
|
+
V2SourceProvenance,
|
|
20
|
+
V2SourceSpace,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
_READ_SCOPES = {"inherited", "context_only"}
|
|
24
|
+
_SEARCH_MODES = {"default", "global"}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _required(name: str, value: str) -> str:
|
|
28
|
+
normalized = str(value or "").strip()
|
|
29
|
+
if not normalized:
|
|
30
|
+
raise ValueError(f"MemcodeV2Client: {name} is required")
|
|
31
|
+
return normalized
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _top_k(value: int) -> int:
|
|
35
|
+
if isinstance(value, bool) or not isinstance(value, int) or not 1 <= value <= 100:
|
|
36
|
+
raise ValueError("MemcodeV2Client: top_k must be an integer between 1 and 100")
|
|
37
|
+
return value
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _scope(value: str) -> str:
|
|
41
|
+
if value not in _READ_SCOPES:
|
|
42
|
+
raise ValueError("MemcodeV2Client: scope must be inherited or context_only")
|
|
43
|
+
return value
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _search_mode(value: str) -> str:
|
|
47
|
+
if value not in _SEARCH_MODES:
|
|
48
|
+
raise ValueError("MemcodeV2Client: search_mode must be default or global")
|
|
49
|
+
return value
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _metadata(data: Dict[str, Any], request_id: Optional[str], elapsed_ms: Optional[float]) -> Dict[str, Any]:
|
|
53
|
+
return {**data, "request_id": request_id, "elapsed_ms": elapsed_ms}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _parse_ingest(data: Dict[str, Any], request_id: Optional[str], elapsed_ms: Optional[float]) -> V2IngestResult:
|
|
57
|
+
return V2IngestResult(**_metadata(data, request_id, elapsed_ms))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _parse_ingest_status(data: Dict[str, Any], request_id: Optional[str], elapsed_ms: Optional[float]) -> V2IngestStatus:
|
|
61
|
+
parsed = dict(data)
|
|
62
|
+
if parsed.get("operation_counts"):
|
|
63
|
+
parsed["operation_counts"] = V2OperationCounts(**parsed["operation_counts"])
|
|
64
|
+
if parsed.get("source"):
|
|
65
|
+
parsed["source"] = V2SourceLineage(**parsed["source"])
|
|
66
|
+
if parsed.get("original_storage"):
|
|
67
|
+
parsed["original_storage"] = V2OriginalStorageStatus(**parsed["original_storage"])
|
|
68
|
+
return V2IngestStatus(**_metadata(parsed, request_id, elapsed_ms))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _parse_source(data: Dict[str, Any]) -> V2MemorySource:
|
|
72
|
+
parsed = dict(data)
|
|
73
|
+
parsed["space"] = V2SourceSpace(**parsed["space"])
|
|
74
|
+
parsed["provenance"] = V2SourceProvenance(**parsed["provenance"])
|
|
75
|
+
return V2MemorySource(**parsed)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _parse_search(data: Dict[str, Any], request_id: Optional[str], elapsed_ms: Optional[float]) -> V2SearchResult:
|
|
79
|
+
parsed = dict(data)
|
|
80
|
+
parsed["results"] = [_parse_source(item) for item in parsed.get("results", [])]
|
|
81
|
+
return V2SearchResult(**_metadata(parsed, request_id, elapsed_ms))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _parse_retrieve(data: Dict[str, Any], request_id: Optional[str], elapsed_ms: Optional[float]) -> V2RetrieveResult:
|
|
85
|
+
parsed = dict(data)
|
|
86
|
+
parsed["sources"] = [_parse_source(item) for item in parsed.get("sources", [])]
|
|
87
|
+
return V2RetrieveResult(**_metadata(parsed, request_id, elapsed_ms))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class MemcodeV2Client:
|
|
91
|
+
"""Tenant-bound v2 client. Credentials determine the organization."""
|
|
92
|
+
|
|
93
|
+
def __init__(
|
|
94
|
+
self,
|
|
95
|
+
api_url: Optional[str] = None,
|
|
96
|
+
api_key: Optional[str] = None,
|
|
97
|
+
timeout: int = DEFAULT_TIMEOUT,
|
|
98
|
+
) -> None:
|
|
99
|
+
resolved_url = api_url or os.getenv("MEMCODE_API_URL") or "http://localhost:8000"
|
|
100
|
+
resolved_key = _required("api_key", api_key or os.getenv("MEMCODE_API_KEY") or "")
|
|
101
|
+
self._transport = SyncTransport(resolved_url, resolved_key, timeout)
|
|
102
|
+
|
|
103
|
+
def ingest(
|
|
104
|
+
self,
|
|
105
|
+
*,
|
|
106
|
+
space_id: str,
|
|
107
|
+
content: str,
|
|
108
|
+
idempotency_key: str,
|
|
109
|
+
actor_id: Optional[str] = None,
|
|
110
|
+
title: Optional[str] = None,
|
|
111
|
+
occurred_at: Optional[str] = None,
|
|
112
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
113
|
+
tags: Optional[List[str]] = None,
|
|
114
|
+
) -> V2IngestResult:
|
|
115
|
+
key = _required("idempotency_key", idempotency_key)
|
|
116
|
+
if len(key) > 256:
|
|
117
|
+
raise ValueError("MemcodeV2Client: idempotency_key cannot exceed 256 characters")
|
|
118
|
+
payload: Dict[str, Any] = {
|
|
119
|
+
"space_id": _required("space_id", space_id),
|
|
120
|
+
"content": _required("content", content),
|
|
121
|
+
}
|
|
122
|
+
for name, value in (("actor_id", actor_id), ("title", title), ("occurred_at", occurred_at)):
|
|
123
|
+
if value is not None:
|
|
124
|
+
payload[name] = _required(name, value)
|
|
125
|
+
if metadata is not None:
|
|
126
|
+
payload["metadata"] = metadata
|
|
127
|
+
if tags is not None:
|
|
128
|
+
payload["tags"] = list(dict.fromkeys(_required("tag", tag) for tag in tags))
|
|
129
|
+
env = self._transport.post(
|
|
130
|
+
"/v2/memory/ingest",
|
|
131
|
+
json=payload,
|
|
132
|
+
headers={"Idempotency-Key": key},
|
|
133
|
+
)
|
|
134
|
+
return _parse_ingest(env.data or {}, env.request_id, env.elapsed_ms)
|
|
135
|
+
|
|
136
|
+
def get_ingest_status(self, job_id: str) -> V2IngestStatus:
|
|
137
|
+
encoded = quote(_required("job_id", job_id), safe="")
|
|
138
|
+
env = self._transport.get(f"/v2/memory/ingest/{encoded}")
|
|
139
|
+
return _parse_ingest_status(env.data or {}, env.request_id, env.elapsed_ms)
|
|
140
|
+
|
|
141
|
+
def search(
|
|
142
|
+
self,
|
|
143
|
+
*,
|
|
144
|
+
context_space_id: str,
|
|
145
|
+
query: str,
|
|
146
|
+
actor_id: Optional[str] = None,
|
|
147
|
+
scope: str = "inherited",
|
|
148
|
+
search_mode: str = "default",
|
|
149
|
+
top_k: int = 10,
|
|
150
|
+
minimum_score: float = 0.0,
|
|
151
|
+
domains: Optional[List[str]] = None,
|
|
152
|
+
include_original_chunks: Optional[bool] = None,
|
|
153
|
+
original_top_k: Optional[int] = None,
|
|
154
|
+
) -> V2SearchResult:
|
|
155
|
+
if isinstance(minimum_score, bool) or not 0 <= minimum_score <= 1:
|
|
156
|
+
raise ValueError("MemcodeV2Client: minimum_score must be between 0 and 1")
|
|
157
|
+
payload: Dict[str, Any] = {
|
|
158
|
+
"context_space_id": _required("context_space_id", context_space_id),
|
|
159
|
+
"query": _required("query", query),
|
|
160
|
+
"scope": _scope(scope),
|
|
161
|
+
"search_mode": _search_mode(search_mode),
|
|
162
|
+
"top_k": _top_k(top_k),
|
|
163
|
+
"minimum_score": minimum_score,
|
|
164
|
+
}
|
|
165
|
+
if actor_id is not None:
|
|
166
|
+
payload["actor_id"] = _required("actor_id", actor_id)
|
|
167
|
+
if domains is not None:
|
|
168
|
+
if not domains:
|
|
169
|
+
raise ValueError("MemcodeV2Client: domains cannot be empty")
|
|
170
|
+
payload["domains"] = list(
|
|
171
|
+
dict.fromkeys(_required("domain", domain) for domain in domains)
|
|
172
|
+
)
|
|
173
|
+
if include_original_chunks is not None:
|
|
174
|
+
if not isinstance(include_original_chunks, bool):
|
|
175
|
+
raise ValueError(
|
|
176
|
+
"MemcodeV2Client: include_original_chunks must be a boolean"
|
|
177
|
+
)
|
|
178
|
+
payload["include_original_chunks"] = include_original_chunks
|
|
179
|
+
if original_top_k is not None:
|
|
180
|
+
payload["original_top_k"] = _top_k(original_top_k)
|
|
181
|
+
env = self._transport.post("/v2/memory/search", json=payload)
|
|
182
|
+
return _parse_search(env.data or {}, env.request_id, env.elapsed_ms)
|
|
183
|
+
|
|
184
|
+
def retrieve(
|
|
185
|
+
self,
|
|
186
|
+
*,
|
|
187
|
+
context_space_id: str,
|
|
188
|
+
query: str,
|
|
189
|
+
actor_id: Optional[str] = None,
|
|
190
|
+
scope: str = "inherited",
|
|
191
|
+
top_k: int = 5,
|
|
192
|
+
) -> V2RetrieveResult:
|
|
193
|
+
payload: Dict[str, Any] = {
|
|
194
|
+
"context_space_id": _required("context_space_id", context_space_id),
|
|
195
|
+
"query": _required("query", query),
|
|
196
|
+
"scope": _scope(scope),
|
|
197
|
+
"top_k": _top_k(top_k),
|
|
198
|
+
}
|
|
199
|
+
if actor_id is not None:
|
|
200
|
+
payload["actor_id"] = _required("actor_id", actor_id)
|
|
201
|
+
env = self._transport.post("/v2/memory/retrieve", json=payload)
|
|
202
|
+
return _parse_retrieve(env.data or {}, env.request_id, env.elapsed_ms)
|
|
203
|
+
|
|
204
|
+
def close(self) -> None:
|
|
205
|
+
self._transport.close()
|
|
206
|
+
|
|
207
|
+
def __enter__(self) -> "MemcodeV2Client":
|
|
208
|
+
return self
|
|
209
|
+
|
|
210
|
+
def __exit__(self, *exc: Any) -> None:
|
|
211
|
+
self.close()
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
MemoryV2Client = MemcodeV2Client
|
memcode_sdk/v2_types.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Typed results for the tenant-bound Memcode v2 memory routes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Any, Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class V2OperationCounts:
|
|
11
|
+
total: int = 0
|
|
12
|
+
succeeded: int = 0
|
|
13
|
+
skipped: int = 0
|
|
14
|
+
failed: int = 0
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class V2SourceLineage:
|
|
19
|
+
type: str
|
|
20
|
+
id: Optional[str] = None
|
|
21
|
+
record_id: Optional[str] = None
|
|
22
|
+
version: Optional[str] = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class V2OriginalStorageStatus:
|
|
27
|
+
status: str
|
|
28
|
+
required: bool
|
|
29
|
+
indexed_chunks: int = 0
|
|
30
|
+
expected_chunks: Optional[int] = None
|
|
31
|
+
cleanup_required: bool = False
|
|
32
|
+
failure_stage: Optional[str] = None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class V2IngestResult:
|
|
37
|
+
id: str
|
|
38
|
+
space_id: str
|
|
39
|
+
status: str
|
|
40
|
+
status_url: Optional[str] = None
|
|
41
|
+
request_id: Optional[str] = None
|
|
42
|
+
elapsed_ms: Optional[float] = None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class V2IngestStatus:
|
|
47
|
+
id: str
|
|
48
|
+
space_id: str
|
|
49
|
+
status: str
|
|
50
|
+
updated_at: Optional[str] = None
|
|
51
|
+
operation_counts: Optional[V2OperationCounts] = None
|
|
52
|
+
produced_memory_ids: List[str] = field(default_factory=list)
|
|
53
|
+
affected_memory_ids: List[str] = field(default_factory=list)
|
|
54
|
+
source: Optional[V2SourceLineage] = None
|
|
55
|
+
original_storage: Optional[V2OriginalStorageStatus] = None
|
|
56
|
+
retryable: bool = False
|
|
57
|
+
error: Optional[str] = None
|
|
58
|
+
status_url: Optional[str] = None
|
|
59
|
+
request_id: Optional[str] = None
|
|
60
|
+
elapsed_ms: Optional[float] = None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass(frozen=True)
|
|
64
|
+
class V2SourceSpace:
|
|
65
|
+
id: str
|
|
66
|
+
kind: str
|
|
67
|
+
visibility: str
|
|
68
|
+
name: str
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True)
|
|
72
|
+
class V2SourceProvenance:
|
|
73
|
+
type: str
|
|
74
|
+
source_id: Optional[str] = None
|
|
75
|
+
source_url: Optional[str] = None
|
|
76
|
+
source_record_id: Optional[str] = None
|
|
77
|
+
source_version: Optional[str] = None
|
|
78
|
+
promoted_from_space_id: Optional[str] = None
|
|
79
|
+
promoted_from_memory_id: Optional[str] = None
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass(frozen=True)
|
|
83
|
+
class V2MemorySource:
|
|
84
|
+
id: str
|
|
85
|
+
content: str
|
|
86
|
+
score: float
|
|
87
|
+
metadata: Dict[str, Any]
|
|
88
|
+
space: V2SourceSpace
|
|
89
|
+
provenance: V2SourceProvenance
|
|
90
|
+
title: Optional[str] = None
|
|
91
|
+
domain: Optional[str] = None
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass(frozen=True)
|
|
95
|
+
class V2SearchResult:
|
|
96
|
+
results: List[V2MemorySource] = field(default_factory=list)
|
|
97
|
+
total: int = 0
|
|
98
|
+
searched_space_ids: List[str] = field(default_factory=list)
|
|
99
|
+
failed_space_ids: List[str] = field(default_factory=list)
|
|
100
|
+
partial: bool = False
|
|
101
|
+
routing_fallback: bool = False
|
|
102
|
+
request_id: Optional[str] = None
|
|
103
|
+
elapsed_ms: Optional[float] = None
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass(frozen=True)
|
|
107
|
+
class V2RetrieveResult:
|
|
108
|
+
answer: str = ""
|
|
109
|
+
sources: List[V2MemorySource] = field(default_factory=list)
|
|
110
|
+
confidence: float = 0.0
|
|
111
|
+
searched_space_ids: List[str] = field(default_factory=list)
|
|
112
|
+
failed_space_ids: List[str] = field(default_factory=list)
|
|
113
|
+
partial: bool = False
|
|
114
|
+
routing_fallback: bool = False
|
|
115
|
+
request_id: Optional[str] = None
|
|
116
|
+
elapsed_ms: Optional[float] = None
|