Skip to content

Commit e3e6a8f

Browse files
committed
feat: adjust deprecated input parameters in Add/Search Request
1 parent e2fd213 commit e3e6a8f

File tree

3 files changed

+118
-43
lines changed

3 files changed

+118
-43
lines changed

src/memos/api/handlers/add_handler.py

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
using dependency injection for better modularity and testability.
66
"""
77

8-
from datetime import datetime
9-
108
from memos.api.handlers.base_handler import BaseHandler, HandlerDependencies
119
from memos.api.product_models import APIADDRequest, MemoryResponse
1210
from memos.multi_mem_cube.composite_cube import CompositeCubeView
@@ -39,17 +37,13 @@ def handle_add_memories(self, add_req: APIADDRequest) -> MemoryResponse:
3937
supporting concurrent processing.
4038
4139
Args:
42-
add_req: Add memory request
40+
add_req: Add memory request (deprecated fields are converted in model validator)
4341
4442
Returns:
4543
MemoryResponse with added memory information
4644
"""
4745
self.logger.info(f"[AddHandler] Add Req is: {add_req}")
4846

49-
if (not add_req.messages) and getattr(add_req, "memory_content", None):
50-
add_req.messages = self._convert_content_messsage(add_req.memory_content)
51-
self.logger.info(f"[AddHandler] Converted content to messages: {add_req.messages}")
52-
5347
cube_view = self._build_cube_view(add_req)
5448

5549
results = cube_view.add_memories(add_req)
@@ -65,16 +59,12 @@ def _resolve_cube_ids(self, add_req: APIADDRequest) -> list[str]:
6559
"""
6660
Normalize target cube ids from add_req.
6761
Priority:
68-
1) writable_cube_ids
69-
2) mem_cube_id
70-
3) fallback to user_id
62+
1) writable_cube_ids (deprecated mem_cube_id is converted to this in model validator)
63+
2) fallback to user_id
7164
"""
72-
if getattr(add_req, "writable_cube_ids", None):
65+
if add_req.writable_cube_ids:
7366
return list(dict.fromkeys(add_req.writable_cube_ids))
7467

75-
if add_req.mem_cube_id:
76-
return [add_req.mem_cube_id]
77-
7868
return [add_req.user_id]
7969

8070
def _build_cube_view(self, add_req: APIADDRequest) -> MemCubeView:
@@ -106,23 +96,3 @@ def _build_cube_view(self, add_req: APIADDRequest) -> MemCubeView:
10696
cube_views=single_views,
10797
logger=self.logger,
10898
)
109-
110-
def _convert_content_messsage(self, memory_content: str) -> list[dict[str, str]]:
111-
"""
112-
Convert content string to list of message dictionaries.
113-
114-
Args:
115-
content: add content string
116-
117-
Returns:
118-
List of message dictionaries
119-
"""
120-
messages_list = [
121-
{
122-
"role": "user",
123-
"content": memory_content,
124-
"chat_time": str(datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
125-
}
126-
]
127-
# for only user-str input and convert message
128-
return messages_list

src/memos/api/handlers/search_handler.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,12 @@ def _resolve_cube_ids(self, search_req: APISearchRequest) -> list[str]:
6363
"""
6464
Normalize target cube ids from search_req.
6565
Priority:
66-
1) readable_cube_ids
67-
2) mem_cube_id
68-
3) fallback to user_id
66+
1) readable_cube_ids (deprecated mem_cube_id is converted to this in model validator)
67+
2) fallback to user_id
6968
"""
70-
if getattr(search_req, "readable_cube_ids", None):
69+
if search_req.readable_cube_ids:
7170
return list(dict.fromkeys(search_req.readable_cube_ids))
7271

73-
if search_req.mem_cube_id:
74-
return [search_req.mem_cube_id]
75-
7672
return [search_req.user_id]
7773

7874
def _build_cube_view(self, search_req: APISearchRequest) -> MemCubeView:

src/memos/api/product_models.py

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
from typing import Any, Generic, Literal, TypeVar
44

5-
from pydantic import BaseModel, Field
5+
from pydantic import BaseModel, Field, model_validator
66

77
# Import message types from core types module
8+
from memos.log import get_logger
89
from memos.mem_scheduler.schemas.general_schemas import SearchMode
910
from memos.types import MessageDict, MessagesType, PermissionDict
1011

1112

13+
logger = get_logger(__name__)
1214
T = TypeVar("T")
1315

1416

@@ -215,7 +217,7 @@ class APISearchRequest(BaseRequest):
215217
# ==== Basic inputs ====
216218
query: str = Field(
217219
...,
218-
description=("User search query"),
220+
description="User search query",
219221
)
220222
user_id: str = Field(..., description="User ID")
221223

@@ -318,6 +320,41 @@ class APISearchRequest(BaseRequest):
318320
description="(Internal) Operation definitions for multi-cube read permissions.",
319321
)
320322

323+
@model_validator(mode="after")
324+
def _convert_deprecated_fields(self) -> "APISearchRequest":
325+
"""
326+
Convert deprecated fields to new fields for backward compatibility.
327+
Ensures full backward compatibility:
328+
- mem_cube_id → readable_cube_ids
329+
- moscube is ignored with warning
330+
- operation ignored
331+
"""
332+
# Convert mem_cube_id to readable_cube_ids (new field takes priority)
333+
if self.mem_cube_id is not None:
334+
if not self.readable_cube_ids:
335+
self.readable_cube_ids = [self.mem_cube_id]
336+
logger.warning(
337+
"Deprecated field `mem_cube_id` is used in APISearchRequest. "
338+
"It will be removed in a future version. "
339+
"Please migrate to `readable_cube_ids`."
340+
)
341+
342+
# Reject moscube if set to True (no longer supported)
343+
if self.moscube:
344+
logger.warning(
345+
"Deprecated field `moscube` is used in APISearchRequest. "
346+
"Legacy MemOSCube pipeline will be removed soon."
347+
)
348+
349+
# Warn about operation (internal)
350+
if self.operation:
351+
logger.warning(
352+
"Internal field `operation` is provided in APISearchRequest. "
353+
"This field is deprecated and ignored."
354+
)
355+
356+
return self
357+
321358

322359
class APIADDRequest(BaseRequest):
323360
"""Request model for creating memories."""
@@ -426,6 +463,78 @@ class APIADDRequest(BaseRequest):
426463
description="(Internal) Operation definitions for multi-cube write permissions.",
427464
)
428465

466+
@model_validator(mode="after")
467+
def _convert_deprecated_fields(self) -> "APIADDRequest":
468+
"""
469+
Convert deprecated fields to new fields for backward compatibility.
470+
This keeps the API fully backward-compatible while allowing
471+
internal logic to use only the new fields.
472+
473+
Rules:
474+
- mem_cube_id → writable_cube_ids
475+
- memory_content → messages
476+
- doc_path → messages (input_file)
477+
- source → info["source"]
478+
- operation → merged into writable_cube_ids (ignored otherwise)
479+
"""
480+
# Convert mem_cube_id to writable_cube_ids (new field takes priority)
481+
if self.mem_cube_id:
482+
logger.warning(
483+
"APIADDRequest.mem_cube_id is deprecated and will be removed in a future version. "
484+
"Please use `writable_cube_ids` instead."
485+
)
486+
if not self.writable_cube_ids:
487+
self.writable_cube_ids = [self.mem_cube_id]
488+
489+
# Handle deprecated operation field
490+
if self.operation:
491+
logger.warning(
492+
"APIADDRequest.operation is deprecated and will be removed. "
493+
"Use `writable_cube_ids` for multi-cube writes."
494+
)
495+
496+
# Convert memory_content to messages (new field takes priority)
497+
if self.memory_content:
498+
logger.warning(
499+
"APIADDRequest.memory_content is deprecated. "
500+
"Use `messages` with a structured message instead."
501+
)
502+
if self.messages is None:
503+
self.messages = []
504+
self.messages.append(
505+
{
506+
"type": "text",
507+
"text": self.memory_content,
508+
}
509+
)
510+
511+
# Handle deprecated doc_path
512+
if self.doc_path:
513+
logger.warning(
514+
"APIADDRequest.doc_path is deprecated. "
515+
"Use `messages` with an input_file item instead."
516+
)
517+
if self.messages is None:
518+
self.messages = []
519+
self.messages.append(
520+
{
521+
"type": "file",
522+
"file": {"path": self.doc_path},
523+
}
524+
)
525+
526+
# Convert source to info.source_type (new field takes priority)
527+
if self.source:
528+
logger.warning(
529+
"APIADDRequest.source is deprecated. "
530+
"Use `info['source_type']` / `info['source_url']` instead."
531+
)
532+
if self.info is None:
533+
self.info = {}
534+
self.info.setdefault("source", self.source)
535+
536+
return self
537+
429538

430539
class APIChatCompleteRequest(BaseRequest):
431540
"""Request model for chat operations."""

0 commit comments

Comments
 (0)