jl-ecms-client 0.2.7__py3-none-any.whl → 0.2.19__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.
mirix/client/client.py CHANGED
@@ -22,16 +22,7 @@ if TYPE_CHECKING:
22
22
  from langchain_core.tools import BaseTool as LangChainBaseTool
23
23
  except ImportError:
24
24
  LangChainBaseTool = Any # type: ignore
25
- from mirix.constants import (
26
- BASE_TOOLS,
27
- DEFAULT_HUMAN,
28
- DEFAULT_PERSONA,
29
- FUNCTION_RETURN_CHAR_LIMIT,
30
- META_MEMORY_TOOLS,
31
- )
32
- from mirix.functions.functions import parse_source_code
33
- from mirix.interface import QueuingInterface
34
- from mirix.orm.errors import NoResultFound
25
+ from mirix.constants import FUNCTION_RETURN_CHAR_LIMIT
35
26
  from mirix.schemas.agent import AgentState, AgentType, CreateAgent, CreateMetaAgent
36
27
  from mirix.schemas.block import Block, BlockUpdate, CreateBlock, Human, Persona
37
28
  from mirix.schemas.embedding_config import EmbeddingConfig
@@ -70,10 +61,6 @@ from mirix.schemas.user import User as PydanticUser
70
61
  from mirix.schemas.user import UserCreate
71
62
 
72
63
 
73
- def create_client():
74
- return LocalClient()
75
-
76
-
77
64
  class AbstractClient(object):
78
65
  def __init__(
79
66
  self,
@@ -99,10 +86,7 @@ class AbstractClient(object):
99
86
  tool_rules: Optional[List[BaseToolRule]] = None,
100
87
  include_base_tools: Optional[bool] = True,
101
88
  include_meta_memory_tools: Optional[bool] = False,
102
- metadata: Optional[Dict] = {
103
- "human:": DEFAULT_HUMAN,
104
- "persona": DEFAULT_PERSONA,
105
- },
89
+ metadata: Optional[Dict] = None,
106
90
  description: Optional[str] = None,
107
91
  initial_message_sequence: Optional[List[Message]] = None,
108
92
  tags: Optional[List[str]] = None,
@@ -419,2166 +403,3 @@ class AbstractClient(object):
419
403
  List[SandboxEnvironmentVariable]: A list of environment variables.
420
404
  """
421
405
  raise NotImplementedError
422
-
423
-
424
- class LocalClient(AbstractClient):
425
- """
426
- A local client for Mirix, which corresponds to a single user.
427
-
428
- Attributes:
429
- user_id (str): The user ID.
430
- debug (bool): Whether to print debug information.
431
- interface (QueuingInterface): The interface for the client.
432
- server (SyncServer): The server for the client.
433
- """
434
-
435
- def __init__(
436
- self,
437
- user_id: Optional[str] = None,
438
- org_id: Optional[str] = None,
439
- debug: bool = False,
440
- default_llm_config: Optional[LLMConfig] = None,
441
- default_embedding_config: Optional[EmbeddingConfig] = None,
442
- ):
443
- """
444
- Initializes a new instance of Client class.
445
-
446
- Args:
447
- user_id (str): The user ID.
448
- debug (bool): Whether to print debug information.
449
- """
450
-
451
- from mirix.server.server import SyncServer
452
-
453
- # set logging levels
454
- # DEBUG flag not needed for LocalClient (server-side only)
455
- logging.getLogger().setLevel(logging.CRITICAL)
456
-
457
- # save default model config
458
- self._default_llm_config = default_llm_config
459
- self._default_embedding_config = default_embedding_config
460
-
461
- # create server
462
- self.interface = QueuingInterface(debug=debug)
463
- self.server = SyncServer(default_interface_factory=lambda: self.interface)
464
-
465
- # initialize file manager
466
- from mirix.services.file_manager import FileManager
467
-
468
- self.file_manager = FileManager()
469
-
470
- # save org_id that `LocalClient` is associated with
471
- if org_id:
472
- self.org_id = org_id
473
- else:
474
- self.org_id = self.server.organization_manager.DEFAULT_ORG_ID
475
- # save user_id that `LocalClient` is associated with
476
- if user_id:
477
- self.user_id = user_id
478
- else:
479
- # get default user
480
- self.user_id = self.server.user_manager.DEFAULT_USER_ID
481
-
482
- self.user = self.server.user_manager.get_user_or_default(self.user_id)
483
- self.organization = self.server.get_organization_or_default(self.org_id)
484
-
485
- # get images directory from settings and ensure it exists
486
- # Can be customized via MIRIX_IMAGES_DIR environment variable
487
- from mirix.settings import settings
488
-
489
- self.images_dir = Path(settings.images_dir)
490
- self.images_dir.mkdir(parents=True, exist_ok=True)
491
-
492
- def _generate_file_hash(self, content: bytes) -> str:
493
- """Generate a unique hash for file content to avoid duplicates."""
494
- return hashlib.sha256(content).hexdigest()[:16]
495
-
496
- def _save_image_from_base64(
497
- self, base64_data: str, detail: str = "auto"
498
- ) -> FileMetadata:
499
- """Save an image from base64 data and return FileMetadata."""
500
- try:
501
- # Parse the data URL format: data:image/jpeg;base64,{data}
502
- if base64_data.startswith("data:"):
503
- header, encoded = base64_data.split(",", 1)
504
- # Extract MIME type from header
505
- mime_type = header.split(":")[1].split(";")[0]
506
- file_extension = mime_type.split("/")[-1]
507
- else:
508
- # Assume it's just base64 data without header
509
- encoded = base64_data
510
- mime_type = "image/jpeg"
511
- file_extension = "jpg"
512
-
513
- # Decode base64 data
514
- image_data = base64.b64decode(encoded)
515
-
516
- # Generate unique filename using hash
517
- file_hash = self._generate_file_hash(image_data)
518
- file_name = f"image_{file_hash}.{file_extension}"
519
- file_path = self.images_dir / file_name
520
-
521
- # Check if file already exists
522
- if not file_path.exists():
523
- # Save the image data
524
- with open(file_path, "wb") as f:
525
- f.write(image_data)
526
-
527
- # Create FileMetadata
528
- file_metadata = self.file_manager.create_file_metadata_from_path(
529
- file_path=str(file_path), organization_id=self.org_id
530
- )
531
-
532
- return file_metadata
533
-
534
- except Exception as e:
535
- raise ValueError(f"Failed to save base64 image: {str(e)}")
536
-
537
- def _save_image_from_url(self, url: str, detail: str = "auto") -> FileMetadata:
538
- """Download and save an image from URL and return FileMetadata."""
539
- try:
540
- # Download the image
541
- response = requests.get(url, stream=True, timeout=30)
542
- response.raise_for_status()
543
-
544
- # Get content type and determine file extension
545
- content_type = response.headers.get("content-type", "image/jpeg")
546
- file_extension = content_type.split("/")[-1]
547
- if file_extension not in ["jpg", "jpeg", "png", "gif", "webp"]:
548
- file_extension = "jpg"
549
-
550
- # Get the image content
551
- image_data = response.content
552
-
553
- # Generate unique filename using hash
554
- file_hash = self._generate_file_hash(image_data)
555
- file_name = f"image_{file_hash}.{file_extension}"
556
- file_path = self.images_dir / file_name
557
-
558
- # Check if file already exists
559
- if not file_path.exists():
560
- # Save the image data
561
- with open(file_path, "wb") as f:
562
- f.write(image_data)
563
-
564
- # Create FileMetadata
565
- file_metadata = self.file_manager.create_file_metadata_from_path(
566
- file_path=str(file_path), organization_id=self.org_id
567
- )
568
-
569
- return file_metadata
570
-
571
- except Exception as e:
572
- raise ValueError(
573
- f"Failed to download and save image from URL {url}: {str(e)}"
574
- )
575
-
576
- def _save_image_from_file_uri(self, file_uri: str) -> FileMetadata:
577
- """Copy an image from file URI and return FileMetadata."""
578
- try:
579
- # Parse file URI (could be file:// or just a local path)
580
- if file_uri.startswith("file://"):
581
- source_path = file_uri[7:] # Remove 'file://' prefix
582
- else:
583
- source_path = file_uri
584
-
585
- source_path = Path(source_path)
586
-
587
- if not source_path.exists():
588
- raise FileNotFoundError(f"Source file not found: {source_path}")
589
-
590
- # Read the file content
591
- with open(source_path, "rb") as f:
592
- image_data = f.read()
593
-
594
- # Generate unique filename using hash
595
- file_hash = self._generate_file_hash(image_data)
596
- file_extension = source_path.suffix.lstrip(".") or "jpg"
597
- file_name = f"image_{file_hash}.{file_extension}"
598
- file_path = self.images_dir / file_name
599
-
600
- # Check if file already exists
601
- if not file_path.exists():
602
- # Copy the file
603
- shutil.copy2(source_path, file_path)
604
-
605
- # Create FileMetadata
606
- file_metadata = self.file_manager.create_file_metadata_from_path(
607
- file_path=str(file_path), organization_id=self.org_id
608
- )
609
-
610
- return file_metadata
611
-
612
- except Exception as e:
613
- raise ValueError(f"Failed to copy image from file URI {file_uri}: {str(e)}")
614
-
615
- def _save_image_from_google_cloud_uri(self, cloud_uri: str) -> FileMetadata:
616
- """Create FileMetadata from Google Cloud URI without downloading the image.
617
-
618
- Google Cloud URIs are not directly downloadable and should be stored as remote references
619
- in the source_url field, similar to how regular HTTP URLs are handled.
620
- """
621
- # Parse URI to get file name - Google Cloud URIs typically come in the format:
622
- # https://generativelanguage.googleapis.com/v1beta/files/{file_id}
623
-
624
- parsed_uri = urlparse(cloud_uri)
625
-
626
- # Extract file ID from path if available, otherwise use generic name
627
- file_id = os.path.basename(parsed_uri.path) or "google_cloud_file"
628
- file_name = f"google_cloud_{file_id}"
629
-
630
- # Ensure file name has an extension
631
- if not os.path.splitext(file_name)[1]:
632
- file_name += ".jpg" # Default to jpg for images without extension
633
-
634
- # Determine MIME type from extension or default to image/jpeg
635
- file_extension = os.path.splitext(file_name)[1].lower()
636
- file_type_map = {
637
- ".jpg": "image/jpeg",
638
- ".jpeg": "image/jpeg",
639
- ".png": "image/png",
640
- ".gif": "image/gif",
641
- ".webp": "image/webp",
642
- ".bmp": "image/bmp",
643
- ".svg": "image/svg+xml",
644
- }
645
- file_type = file_type_map.get(file_extension, "image/jpeg")
646
-
647
- # Create FileMetadata with Google Cloud URI in google_cloud_url field
648
- file_metadata = self.file_manager.create_file_metadata(
649
- PydanticFileMetadata(
650
- organization_id=self.org_id,
651
- file_name=file_name,
652
- file_path=None, # No local path for Google Cloud URIs
653
- source_url=None, # No regular source URL for Google Cloud files
654
- google_cloud_url=cloud_uri, # Store Google Cloud URI in the dedicated field
655
- file_type=file_type,
656
- file_size=None, # Unknown size for remote Google Cloud files
657
- file_creation_date=None,
658
- file_last_modified_date=None,
659
- )
660
- )
661
-
662
- return file_metadata
663
-
664
- def _save_file_from_path(self, file_path: str) -> FileMetadata:
665
- """Save a file from local path and return FileMetadata."""
666
- try:
667
- file_path = Path(file_path)
668
-
669
- if not file_path.exists():
670
- raise FileNotFoundError(f"File not found: {file_path}")
671
-
672
- # Create FileMetadata using the file manager
673
- file_metadata = self.file_manager.create_file_metadata_from_path(
674
- file_path=str(file_path), organization_id=self.org_id
675
- )
676
-
677
- return file_metadata
678
-
679
- except Exception as e:
680
- raise ValueError(f"Failed to save file from path {file_path}: {str(e)}")
681
-
682
- def _determine_file_type(self, file_path: str) -> str:
683
- """Determine file type from file extension."""
684
- file_extension = os.path.splitext(file_path)[1].lower()
685
- file_type_map = {
686
- # Images
687
- ".jpg": "image/jpeg",
688
- ".jpeg": "image/jpeg",
689
- ".png": "image/png",
690
- ".gif": "image/gif",
691
- ".webp": "image/webp",
692
- ".bmp": "image/bmp",
693
- ".svg": "image/svg+xml",
694
- # Documents
695
- ".pdf": "application/pdf",
696
- ".doc": "application/msword",
697
- ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
698
- ".txt": "text/plain",
699
- ".rtf": "application/rtf",
700
- ".html": "text/html",
701
- ".htm": "text/html",
702
- # Spreadsheets
703
- ".xls": "application/vnd.ms-excel",
704
- ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
705
- ".csv": "text/csv",
706
- # Presentations
707
- ".ppt": "application/vnd.ms-powerpoint",
708
- ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
709
- # Other common formats
710
- ".json": "application/json",
711
- ".xml": "application/xml",
712
- ".zip": "application/zip",
713
- }
714
- return file_type_map.get(file_extension, "application/octet-stream")
715
-
716
- def _create_file_metadata_from_url(
717
- self, url: str, detail: str = "auto"
718
- ) -> FileMetadata:
719
- """Create FileMetadata from URL without downloading the image.
720
-
721
- The URL is stored in the source_url field, not file_path, to clearly
722
- distinguish between local files and remote resources.
723
- """
724
- try:
725
- # Parse URL to get file name
726
- from urllib.parse import urlparse
727
-
728
- parsed_url = urlparse(url)
729
- file_name = os.path.basename(parsed_url.path) or "remote_image"
730
-
731
- # Ensure file name has an extension
732
- if not os.path.splitext(file_name)[1]:
733
- file_name += ".jpg" # Default to jpg for images without extension
734
-
735
- # Determine MIME type from extension or default to image/jpeg
736
- file_extension = os.path.splitext(file_name)[1].lower()
737
- file_type_map = {
738
- ".jpg": "image/jpeg",
739
- ".jpeg": "image/jpeg",
740
- ".png": "image/png",
741
- ".gif": "image/gif",
742
- ".webp": "image/webp",
743
- ".bmp": "image/bmp",
744
- ".svg": "image/svg+xml",
745
- }
746
- file_type = file_type_map.get(file_extension, "image/jpeg")
747
-
748
- # Create FileMetadata with URL in source_url field
749
- file_metadata = self.file_manager.create_file_metadata(
750
- PydanticFileMetadata(
751
- organization_id=self.org_id,
752
- file_name=file_name,
753
- file_path=None, # No local path for remote URLs
754
- source_url=url, # Store URL in the dedicated field
755
- file_type=file_type,
756
- file_size=None, # Unknown size for remote URLs
757
- file_creation_date=None,
758
- file_last_modified_date=None,
759
- )
760
- )
761
-
762
- return file_metadata
763
-
764
- except Exception as e:
765
- raise ValueError(f"Failed to create file metadata from URL {url}: {str(e)}")
766
-
767
- # agents
768
- def list_agents(
769
- self,
770
- query_text: Optional[str] = None,
771
- tags: Optional[List[str]] = None,
772
- limit: int = 100,
773
- cursor: Optional[str] = None,
774
- parent_id: Optional[str] = None,
775
- ) -> List[AgentState]:
776
- self.interface.clear()
777
-
778
- return self.server.agent_manager.list_agents(
779
- actor=self.server.user_manager.get_user_by_id(self.user.id),
780
- tags=tags,
781
- query_text=query_text,
782
- limit=limit,
783
- cursor=cursor,
784
- parent_id=parent_id,
785
- )
786
-
787
- def agent_exists(
788
- self, agent_id: Optional[str] = None, agent_name: Optional[str] = None
789
- ) -> bool:
790
- """
791
- Check if an agent exists
792
-
793
- Args:
794
- agent_id (str): ID of the agent
795
- agent_name (str): Name of the agent
796
-
797
- Returns:
798
- exists (bool): `True` if the agent exists, `False` otherwise
799
- """
800
-
801
- if not (agent_id or agent_name):
802
- raise ValueError("Either agent_id or agent_name must be provided")
803
- if agent_id and agent_name:
804
- raise ValueError("Only one of agent_id or agent_name can be provided")
805
- existing = self.list_agents()
806
- if agent_id:
807
- return str(agent_id) in [str(agent.id) for agent in existing]
808
- else:
809
- return agent_name in [str(agent.name) for agent in existing]
810
-
811
- def create_agent(
812
- self,
813
- name: Optional[str] = None,
814
- # agent config
815
- agent_type: Optional[AgentType] = AgentType.chat_agent,
816
- # model configs
817
- embedding_config: Optional[EmbeddingConfig] = None,
818
- llm_config: Optional[LLMConfig] = None,
819
- # memory
820
- memory: Optional[Memory] = None,
821
- block_ids: Optional[List[str]] = None,
822
- system: Optional[str] = None,
823
- # tools
824
- tool_ids: Optional[List[str]] = None,
825
- tool_rules: Optional[List[BaseToolRule]] = None,
826
- include_base_tools: Optional[bool] = True,
827
- include_meta_memory_tools: Optional[bool] = False,
828
- # metadata
829
- metadata: Optional[Dict] = {
830
- "human:": DEFAULT_HUMAN,
831
- "persona": DEFAULT_PERSONA,
832
- },
833
- description: Optional[str] = None,
834
- initial_message_sequence: Optional[List[Message]] = None,
835
- tags: Optional[List[str]] = None,
836
- ) -> AgentState:
837
- """Create an agent
838
-
839
- Args:
840
- name (str): Name of the agent
841
- embedding_config (EmbeddingConfig): Embedding configuration
842
- llm_config (LLMConfig): LLM configuration
843
- memory_blocks (List[Dict]): List of configurations for the memory blocks (placed in core-memory)
844
- system (str): System configuration
845
- tools (List[str]): List of tools
846
- tool_rules (Optional[List[BaseToolRule]]): List of tool rules
847
- include_base_tools (bool): Include base tools
848
- metadata (Dict): Metadata
849
- description (str): Description
850
- tags (List[str]): Tags for filtering agents
851
-
852
- Returns:
853
- agent_state (AgentState): State of the created agent
854
- """
855
- # construct list of tools
856
- tool_ids = tool_ids or []
857
- tool_names = []
858
- if include_base_tools:
859
- tool_names += BASE_TOOLS
860
- if include_meta_memory_tools:
861
- tool_names += META_MEMORY_TOOLS
862
- tool_ids += [
863
- self.server.tool_manager.get_tool_by_name(
864
- tool_name=name,
865
- actor=self.server.user_manager.get_user_by_id(self.user.id),
866
- ).id
867
- for name in tool_names
868
- ]
869
-
870
- # check if default configs are provided
871
- assert embedding_config or self._default_embedding_config, (
872
- "Embedding config must be provided"
873
- )
874
- assert llm_config or self._default_llm_config, "LLM config must be provided"
875
-
876
- # TODO: This should not happen here, we need to have clear separation between create/add blocks
877
- for block in memory.get_blocks():
878
- self.server.block_manager.create_or_update_block(
879
- block, actor=self.server.user_manager.get_user_by_id(self.user.id)
880
- )
881
-
882
- # Also get any existing block_ids passed in
883
- block_ids = block_ids or []
884
-
885
- # create agent
886
- # Create the base parameters
887
- create_params = {
888
- "description": description,
889
- "metadata_": metadata,
890
- "memory_blocks": [],
891
- "block_ids": [b.id for b in memory.get_blocks()] + block_ids,
892
- "tool_ids": tool_ids,
893
- "tool_rules": tool_rules,
894
- "include_base_tools": include_base_tools,
895
- "system": system,
896
- "agent_type": agent_type,
897
- "llm_config": llm_config if llm_config else self._default_llm_config,
898
- "embedding_config": embedding_config
899
- if embedding_config
900
- else self._default_embedding_config,
901
- "initial_message_sequence": initial_message_sequence,
902
- "tags": tags,
903
- }
904
-
905
- # Only add name if it's not None
906
- if name is not None:
907
- create_params["name"] = name
908
-
909
- agent_state = self.server.create_agent(
910
- CreateAgent(**create_params),
911
- actor=self.server.user_manager.get_user_by_id(self.user.id),
912
- )
913
-
914
- # TODO: get full agent state
915
- return self.server.agent_manager.get_agent_by_id(
916
- agent_state.id, actor=self.server.user_manager.get_user_by_id(self.user.id)
917
- )
918
-
919
- def create_user(self, user_id: str, user_name: str) -> PydanticUser:
920
- return self.server.user_manager.create_user(UserCreate(id=user_id, name=user_name))
921
-
922
- def create_meta_agent(self, config: dict):
923
- """Create a MetaAgent for memory management operations.
924
-
925
- Args:
926
- config (dict): Configuration dictionary for creating the MetaAgent.
927
- Can include: name, agents, system_prompts_folder, system_prompts,
928
- llm_config, embedding_config, memory_blocks, description.
929
-
930
- Returns:
931
- MetaAgent: The initialized MetaAgent instance
932
- """
933
- # Create MetaAgent through server
934
- return self.server.create_meta_agent(
935
- request=CreateMetaAgent(**config),
936
- actor=self.server.user_manager.get_user_by_id(self.user.id),
937
- )
938
-
939
- def get_tools_from_agent(self, agent_id: str) -> List[Tool]:
940
- """
941
- Get tools from an existing agent.
942
-
943
- Args:
944
- agent_id (str): ID of the agent
945
-
946
- Returns:
947
- List[Tool]: A list of Tool objs
948
- """
949
- self.interface.clear()
950
- return self.server.agent_manager.get_agent_by_id(
951
- agent_id=agent_id,
952
- actor=self.server.user_manager.get_user_by_id(self.user.id),
953
- ).tools
954
-
955
- def add_tool_to_agent(self, agent_id: str, tool_id: str):
956
- """
957
- Add tool to an existing agent
958
-
959
- Args:
960
- agent_id (str): ID of the agent
961
- tool_id (str): A tool id
962
-
963
- Returns:
964
- agent_state (AgentState): State of the updated agent
965
- """
966
- self.interface.clear()
967
- agent_state = self.server.agent_manager.attach_tool(
968
- agent_id=agent_id,
969
- tool_id=tool_id,
970
- actor=self.server.user_manager.get_user_by_id(self.user.id),
971
- )
972
- return agent_state
973
-
974
- def remove_tool_from_agent(self, agent_id: str, tool_id: str):
975
- """
976
- Removes tools from an existing agent
977
-
978
- Args:
979
- agent_id (str): ID of the agent
980
- tool_id (str): The tool id
981
-
982
- Returns:
983
- agent_state (AgentState): State of the updated agent
984
- """
985
- self.interface.clear()
986
- agent_state = self.server.agent_manager.detach_tool(
987
- agent_id=agent_id,
988
- tool_id=tool_id,
989
- actor=self.server.user_manager.get_user_by_id(self.user.id),
990
- )
991
- return agent_state
992
-
993
- def rename_agent(self, agent_id: str, new_name: str):
994
- """
995
- Rename an agent
996
-
997
- Args:
998
- agent_id (str): ID of the agent
999
- new_name (str): New name for the agent
1000
- """
1001
- self.update_agent(agent_id, name=new_name)
1002
-
1003
- def delete_agent(self, agent_id: str):
1004
- """
1005
- Delete an agent
1006
-
1007
- Args:
1008
- agent_id (str): ID of the agent to delete
1009
- """
1010
- self.server.agent_manager.delete_agent(
1011
- agent_id=agent_id,
1012
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1013
- )
1014
-
1015
- def get_agent_by_name(self, agent_name: str) -> AgentState:
1016
- """
1017
- Get an agent by its name
1018
-
1019
- Args:
1020
- agent_name (str): Name of the agent
1021
-
1022
- Returns:
1023
- agent_state (AgentState): State of the agent
1024
- """
1025
- self.interface.clear()
1026
- return self.server.agent_manager.get_agent_by_name(
1027
- agent_name=agent_name,
1028
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1029
- )
1030
-
1031
- def get_agent(self, agent_id: str) -> AgentState:
1032
- """
1033
- Get an agent's state by its ID.
1034
-
1035
- Args:
1036
- agent_id (str): ID of the agent
1037
-
1038
- Returns:
1039
- agent_state (AgentState): State representation of the agent
1040
- """
1041
- self.interface.clear()
1042
- return self.server.agent_manager.get_agent_by_id(
1043
- agent_id=agent_id,
1044
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1045
- )
1046
-
1047
- def get_agent_id(self, agent_name: str) -> Optional[str]:
1048
- """
1049
- Get the ID of an agent by name (names are unique per user)
1050
-
1051
- Args:
1052
- agent_name (str): Name of the agent
1053
-
1054
- Returns:
1055
- agent_id (str): ID of the agent
1056
- """
1057
-
1058
- self.interface.clear()
1059
- assert agent_name, "Agent name must be provided"
1060
-
1061
- # TODO: Refactor this futher to not have downstream users expect Optionals - this should just error
1062
- try:
1063
- return self.server.agent_manager.get_agent_by_name(
1064
- agent_name=agent_name,
1065
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1066
- ).id
1067
- except NoResultFound:
1068
- return None
1069
-
1070
- # memory
1071
- def get_in_context_memory(self, agent_id: str) -> Memory:
1072
- """
1073
- Get the in-context (i.e. core) memory of an agent
1074
-
1075
- Args:
1076
- agent_id (str): ID of the agent
1077
-
1078
- Returns:
1079
- memory (Memory): In-context memory of the agent
1080
- """
1081
- memory = self.server.get_agent_memory(
1082
- agent_id=agent_id,
1083
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1084
- )
1085
- return memory
1086
-
1087
- def get_core_memory(self, agent_id: str) -> Memory:
1088
- return self.get_in_context_memory(agent_id)
1089
-
1090
- def update_in_context_memory(
1091
- self, agent_id: str, section: str, value: Union[List[str], str]
1092
- ) -> Memory:
1093
- """
1094
- Update the in-context memory of an agent
1095
-
1096
- Args:
1097
- agent_id (str): ID of the agent
1098
-
1099
- Returns:
1100
- memory (Memory): The updated in-context memory of the agent
1101
-
1102
- """
1103
- # TODO: implement this (not sure what it should look like)
1104
- memory = self.server.update_agent_core_memory(
1105
- agent_id=agent_id,
1106
- label=section,
1107
- value=value,
1108
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1109
- )
1110
- return memory
1111
-
1112
- def get_archival_memory_summary(self, agent_id: str) -> ArchivalMemorySummary:
1113
- """
1114
- Get a summary of the archival memory of an agent
1115
-
1116
- Args:
1117
- agent_id (str): ID of the agent
1118
-
1119
- Returns:
1120
- summary (ArchivalMemorySummary): Summary of the archival memory
1121
-
1122
- """
1123
- return self.server.get_archival_memory_summary(
1124
- agent_id=agent_id,
1125
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1126
- )
1127
-
1128
- def get_recall_memory_summary(self, agent_id: str) -> RecallMemorySummary:
1129
- """
1130
- Get a summary of the recall memory of an agent
1131
-
1132
- Args:
1133
- agent_id (str): ID of the agent
1134
-
1135
- Returns:
1136
- summary (RecallMemorySummary): Summary of the recall memory
1137
- """
1138
- return self.server.get_recall_memory_summary(
1139
- agent_id=agent_id,
1140
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1141
- )
1142
-
1143
- def get_in_context_messages(self, agent_id: str) -> List[Message]:
1144
- """
1145
- Get in-context messages of an agent
1146
-
1147
- Args:
1148
- agent_id (str): ID of the agent
1149
-
1150
- Returns:
1151
- messages (List[Message]): List of in-context messages
1152
- """
1153
- return self.server.agent_manager.get_in_context_messages(
1154
- agent_id=agent_id,
1155
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1156
- )
1157
-
1158
- # agent interactions
1159
-
1160
- def construct_system_message(
1161
- self, agent_id: str, message: str, user_id: str
1162
- ) -> str:
1163
- """
1164
- Construct a system message from a message.
1165
- """
1166
- return self.server.construct_system_message(
1167
- agent_id=agent_id,
1168
- message=message,
1169
- actor=self.server.user_manager.get_user_by_id(user_id),
1170
- )
1171
-
1172
- def extract_memory_for_system_prompt(
1173
- self, agent_id: str, message: str, user_id: str
1174
- ) -> str:
1175
- """
1176
- Extract memory for system prompt from a message.
1177
- """
1178
- return self.server.extract_memory_for_system_prompt(
1179
- agent_id=agent_id,
1180
- message=message,
1181
- actor=self.server.user_manager.get_user_by_id(user_id),
1182
- )
1183
-
1184
- def send_messages(
1185
- self,
1186
- agent_id: str,
1187
- messages: List[Union[Message | MessageCreate]],
1188
- ):
1189
- """
1190
- Send pre-packed messages to an agent.
1191
-
1192
- Args:
1193
- agent_id (str): ID of the agent
1194
- messages (List[Union[Message | MessageCreate]]): List of messages to send
1195
-
1196
- Returns:
1197
- response (MirixResponse): Response from the agent
1198
- """
1199
- self.interface.clear()
1200
- usage = self.server.send_messages(
1201
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1202
- agent_id=agent_id,
1203
- input_messages=messages,
1204
- )
1205
-
1206
- # format messages
1207
- return MirixResponse(messages=messages, usage=usage)
1208
-
1209
- def send_message(
1210
- self,
1211
- message: str | list[dict],
1212
- role: str,
1213
- name: Optional[str] = None,
1214
- agent_id: Optional[str] = None,
1215
- agent_name: Optional[str] = None,
1216
- stream_steps: bool = False,
1217
- stream_tokens: bool = False,
1218
- chaining: Optional[bool] = None,
1219
- verbose: Optional[bool] = None,
1220
- ) -> MirixResponse:
1221
- """
1222
- Send a message to an agent
1223
-
1224
- Args:
1225
- message (str): Message to send
1226
- role (str): Role of the message
1227
- agent_id (str): ID of the agent
1228
- name(str): Name of the sender
1229
- stream_steps (bool): Stream the steps (default: `False`)
1230
- stream_tokens (bool): Stream the tokens (default: `False`)
1231
- chaining (bool): Whether to enable chaining for this message
1232
- verbose (bool): Whether to print verbose logging (default: `None`, which inherits from MIRIX_VERBOSE env var)
1233
-
1234
- Returns:
1235
- response (MirixResponse): Response from the agent
1236
- """
1237
-
1238
- if not agent_id:
1239
- # lookup agent by name
1240
- assert agent_name, "Either agent_id or agent_name must be provided"
1241
- agent_id = self.get_agent_id(agent_name=agent_name)
1242
- assert agent_id, f"Agent with name {agent_name} not found"
1243
-
1244
- if stream_steps or stream_tokens:
1245
- # TODO: implement streaming with stream=True/False
1246
- raise NotImplementedError
1247
- self.interface.clear()
1248
-
1249
- if isinstance(message, str):
1250
- content = [TextContent(text=message)]
1251
- input_messages = [
1252
- MessageCreate(role=MessageRole(role), content=content, name=name)
1253
- ]
1254
- elif isinstance(message, list):
1255
-
1256
- def convert_message(m):
1257
- if m["type"] == "text":
1258
- return TextContent(**m)
1259
- elif m["type"] == "image_url":
1260
- url = m["image_url"]["url"]
1261
- detail = m["image_url"].get("detail", "auto")
1262
-
1263
- # Handle the image based on URL type
1264
- if url.startswith("data:"):
1265
- # Base64 encoded image - save locally
1266
- file_metadata = self._save_image_from_base64(url, detail)
1267
- else:
1268
- # HTTP URL - just create FileMetadata without downloading
1269
- file_metadata = self._create_file_metadata_from_url(url, detail)
1270
-
1271
- return ImageContent(
1272
- type=MessageContentType.image_url,
1273
- image_id=file_metadata.id,
1274
- detail=detail,
1275
- )
1276
-
1277
- elif m["type"] == "image_data":
1278
- # Base64 image data (new format)
1279
- data = m["image_data"]["data"]
1280
- detail = m["image_data"].get("detail", "auto")
1281
-
1282
- # Save the base64 image to file_manager
1283
- file_metadata = self._save_image_from_base64(data, detail)
1284
-
1285
- return ImageContent(
1286
- type=MessageContentType.image_url,
1287
- image_id=file_metadata.id,
1288
- detail=detail,
1289
- )
1290
- elif m["type"] == "file_uri":
1291
- # File URI (local file path)
1292
- file_path = m["file_uri"]
1293
-
1294
- # Check if it's an image or other file type
1295
- file_type = self._determine_file_type(file_path)
1296
-
1297
- if file_type.startswith("image/"):
1298
- # Handle as image
1299
- file_metadata = self._save_image_from_file_uri(file_path)
1300
- return ImageContent(
1301
- type=MessageContentType.image_url,
1302
- image_id=file_metadata.id,
1303
- detail="auto",
1304
- )
1305
- else:
1306
- # Handle as general file (e.g., PDF, DOC, etc.)
1307
- file_metadata = self._save_file_from_path(file_path)
1308
- return FileContent(
1309
- type=MessageContentType.file_uri, file_id=file_metadata.id
1310
- )
1311
-
1312
- elif m["type"] == "google_cloud_file_uri":
1313
- # Google Cloud file URI
1314
- # Handle both the typo version and the correct version from the test file
1315
- file_uri = m.get("google_cloud_file_uri") or m.get("file_uri")
1316
-
1317
- file_metadata = self._save_image_from_google_cloud_uri(file_uri)
1318
- return CloudFileContent(
1319
- type=MessageContentType.google_cloud_file_uri,
1320
- cloud_file_uri=file_metadata.id,
1321
- )
1322
-
1323
- elif m["type"] == "database_image_id":
1324
- return ImageContent(
1325
- type=MessageContentType.image_url,
1326
- image_id=m["image_id"],
1327
- detail="auto",
1328
- )
1329
-
1330
- elif m["type"] == "database_file_id":
1331
- return FileContent(
1332
- type=MessageContentType.file_uri,
1333
- file_id=m["file_id"],
1334
- )
1335
-
1336
- elif m["type"] == "database_google_cloud_file_uri":
1337
- return CloudFileContent(
1338
- type=MessageContentType.google_cloud_file_uri,
1339
- cloud_file_uri=m["cloud_file_uri"],
1340
- )
1341
-
1342
- else:
1343
- raise ValueError(f"Unknown message type: {m['type']}")
1344
-
1345
- content = [convert_message(m) for m in message]
1346
- input_messages = [
1347
- MessageCreate(role=MessageRole(role), content=content, name=name)
1348
- ]
1349
- if extra_messages is not None:
1350
- extra_messages = [
1351
- MessageCreate(
1352
- role=MessageRole(role),
1353
- content=[convert_message(m) for m in extra_messages],
1354
- name=name,
1355
- )
1356
- ]
1357
-
1358
- else:
1359
- raise ValueError(f"Invalid message type: {type(message)}")
1360
-
1361
- usage = self.server.send_messages(
1362
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1363
- agent_id=agent_id,
1364
- input_messages=input_messages,
1365
- chaining=chaining,
1366
- verbose=verbose,
1367
- )
1368
-
1369
- # format messages
1370
- messages = self.interface.to_list()
1371
-
1372
- mirix_messages = []
1373
- for m in messages:
1374
- mirix_messages += m.to_mirix_message()
1375
-
1376
- return MirixResponse(messages=mirix_messages, usage=usage)
1377
-
1378
- def user_message(self, agent_id: str, message: str) -> MirixResponse:
1379
- """
1380
- Send a message to an agent as a user
1381
-
1382
- Args:
1383
- agent_id (str): ID of the agent
1384
- message (str): Message to send
1385
-
1386
- Returns:
1387
- response (MirixResponse): Response from the agent
1388
- """
1389
- self.interface.clear()
1390
- return self.send_message(role="user", agent_id=agent_id, message=message)
1391
-
1392
- def run_command(self, agent_id: str, command: str) -> MirixResponse:
1393
- """
1394
- Run a command on the agent
1395
-
1396
- Args:
1397
- agent_id (str): The agent ID
1398
- command (str): The command to run
1399
-
1400
- Returns:
1401
- MirixResponse: The response from the agent
1402
-
1403
- """
1404
- self.interface.clear()
1405
- usage = self.server.run_command(
1406
- user_id=self.user_id, agent_id=agent_id, command=command
1407
- )
1408
-
1409
- # NOTE: messages/usage may be empty, depending on the command
1410
- return MirixResponse(messages=self.interface.to_list(), usage=usage)
1411
-
1412
- # archival memory
1413
-
1414
- # humans / personas
1415
-
1416
- def get_block_id(self, name: str, label: str) -> str:
1417
- block = self.server.block_manager.get_blocks(
1418
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1419
- label=label,
1420
- )
1421
- if not block:
1422
- return None
1423
- return block[0].id
1424
-
1425
- def create_human(self, name: str, text: str):
1426
- """
1427
- Create a human block template (saved human string to pre-fill `ChatMemory`)
1428
-
1429
- Args:
1430
- name (str): Name of the human block
1431
- text (str): Text of the human block
1432
-
1433
- Returns:
1434
- human (Human): Human block
1435
- """
1436
- return self.server.block_manager.create_or_update_block(
1437
- Human(value=text),
1438
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1439
- )
1440
-
1441
- def create_persona(self, name: str, text: str):
1442
- """
1443
- Create a persona block template (saved persona string to pre-fill `ChatMemory`)
1444
-
1445
- Args:
1446
- name (str): Name of the persona block
1447
- text (str): Text of the persona block
1448
-
1449
- Returns:
1450
- persona (Persona): Persona block
1451
- """
1452
- return self.server.block_manager.create_or_update_block(
1453
- Persona(value=text),
1454
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1455
- )
1456
-
1457
- def list_humans(self):
1458
- """
1459
- List available human block templates
1460
-
1461
- Returns:
1462
- humans (List[Human]): List of human blocks
1463
- """
1464
- return self.server.block_manager.get_blocks(
1465
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1466
- label="human",
1467
- )
1468
-
1469
- def list_personas(self) -> List[Persona]:
1470
- """
1471
- List available persona block templates
1472
-
1473
- Returns:
1474
- personas (List[Persona]): List of persona blocks
1475
- """
1476
- return self.server.block_manager.get_blocks(
1477
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1478
- label="persona",
1479
- )
1480
-
1481
- def update_human(self, human_id: str, text: str):
1482
- """
1483
- Update a human block template
1484
-
1485
- Args:
1486
- human_id (str): ID of the human block
1487
- text (str): Text of the human block
1488
-
1489
- Returns:
1490
- human (Human): Updated human block
1491
- """
1492
-
1493
- return self.server.block_manager.update_block(
1494
- block_id=human_id,
1495
- block_update=BlockUpdate(value=text),
1496
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1497
- )
1498
-
1499
- def update_persona(self, persona_id: str, text: str):
1500
- """
1501
- Update a persona block template
1502
-
1503
- Args:
1504
- persona_id (str): ID of the persona block
1505
- text (str): Text of the persona block
1506
-
1507
- Returns:
1508
- persona (Persona): Updated persona block
1509
- """
1510
- blocks = self.server.block_manager.get_blocks(self.user)
1511
- persona_block = [block for block in blocks if block.label == "persona"][0]
1512
- return self.server.block_manager.update_block(
1513
- block_id=persona_block.id,
1514
- block_update=BlockUpdate(value=text),
1515
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1516
- )
1517
-
1518
- def update_persona_text(self, persona_name: str, text: str):
1519
- """
1520
- Update a persona block template by template name
1521
-
1522
- Args:
1523
- persona_name (str): Name of the persona template
1524
- text (str): Text of the persona block
1525
-
1526
- Returns:
1527
- persona (Persona): Updated persona block
1528
- """
1529
- persona_id = self.get_persona_id(persona_name)
1530
- if persona_id:
1531
- # Update existing persona
1532
- return self.server.block_manager.update_block(
1533
- block_id=persona_id,
1534
- block_update=BlockUpdate(value=text),
1535
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1536
- )
1537
- else:
1538
- # Create new persona if it doesn't exist
1539
- return self.create_persona(persona_name, text)
1540
-
1541
- def get_persona(self, id: str) -> Persona:
1542
- """
1543
- Get a persona block template
1544
-
1545
- Args:
1546
- id (str): ID of the persona block
1547
-
1548
- Returns:
1549
- persona (Persona): Persona block
1550
- """
1551
- assert id, "Persona ID must be provided"
1552
- return Persona(
1553
- **self.server.block_manager.get_block_by_id(
1554
- id, actor=self.server.user_manager.get_user_by_id(self.user.id)
1555
- ).model_dump()
1556
- )
1557
-
1558
- def get_human(self, id: str) -> Human:
1559
- """
1560
- Get a human block template
1561
-
1562
- Args:
1563
- id (str): ID of the human block
1564
-
1565
- Returns:
1566
- human (Human): Human block
1567
- """
1568
- assert id, "Human ID must be provided"
1569
- return Human(
1570
- **self.server.block_manager.get_block_by_id(
1571
- id, actor=self.server.user_manager.get_user_by_id(self.user.id)
1572
- ).model_dump()
1573
- )
1574
-
1575
- def get_persona_id(self, name: str) -> str:
1576
- """
1577
- Get the ID of a persona block template
1578
-
1579
- Args:
1580
- name (str): Name of the persona block
1581
-
1582
- Returns:
1583
- id (str): ID of the persona block
1584
- """
1585
- persona = self.server.block_manager.get_blocks(
1586
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1587
- label="persona",
1588
- )
1589
- if not persona:
1590
- return None
1591
- return persona[0].id
1592
-
1593
- def get_human_id(self, name: str) -> str:
1594
- """
1595
- Get the ID of a human block template
1596
-
1597
- Args:
1598
- name (str): Name of the human block
1599
-
1600
- Returns:
1601
- id (str): ID of the human block
1602
- """
1603
- human = self.server.block_manager.get_blocks(
1604
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1605
- label="human",
1606
- )
1607
- if not human:
1608
- return None
1609
- return human[0].id
1610
-
1611
- def delete_persona(self, id: str):
1612
- """
1613
- Delete a persona block template
1614
-
1615
- Args:
1616
- id (str): ID of the persona block
1617
- """
1618
- self.delete_block(id)
1619
-
1620
- def delete_human(self, id: str):
1621
- """
1622
- Delete a human block template
1623
-
1624
- Args:
1625
- id (str): ID of the human block
1626
- """
1627
- self.delete_block(id)
1628
-
1629
- # tools
1630
- def load_langchain_tool(
1631
- self,
1632
- langchain_tool: "LangChainBaseTool",
1633
- additional_imports_module_attr_map: dict[str, str] = None,
1634
- ) -> Tool:
1635
- tool_create = ToolCreate.from_langchain(
1636
- langchain_tool=langchain_tool,
1637
- additional_imports_module_attr_map=additional_imports_module_attr_map,
1638
- )
1639
- return self.server.tool_manager.create_or_update_tool(
1640
- pydantic_tool=Tool(**tool_create.model_dump()),
1641
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1642
- )
1643
-
1644
- def load_crewai_tool(
1645
- self,
1646
- crewai_tool: "CrewAIBaseTool",
1647
- additional_imports_module_attr_map: dict[str, str] = None,
1648
- ) -> Tool:
1649
- tool_create = ToolCreate.from_crewai(
1650
- crewai_tool=crewai_tool,
1651
- additional_imports_module_attr_map=additional_imports_module_attr_map,
1652
- )
1653
- return self.server.tool_manager.create_or_update_tool(
1654
- pydantic_tool=Tool(**tool_create.model_dump()),
1655
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1656
- )
1657
-
1658
- def load_composio_tool(self, action: "ActionType") -> Tool:
1659
- tool_create = ToolCreate.from_composio(action_name=action.name)
1660
- return self.server.tool_manager.create_or_update_tool(
1661
- pydantic_tool=Tool(**tool_create.model_dump()),
1662
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1663
- )
1664
-
1665
- def create_tool(
1666
- self,
1667
- func,
1668
- name: Optional[str] = None,
1669
- tags: Optional[List[str]] = None,
1670
- description: Optional[str] = None,
1671
- return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT,
1672
- ) -> Tool:
1673
- """
1674
- Create a tool. This stores the source code of function on the server, so that the server can execute the function and generate an OpenAI JSON schemas for it when using with an agent.
1675
-
1676
- Args:
1677
- func (callable): The function to create a tool for.
1678
- name: (str): Name of the tool (must be unique per-user.)
1679
- tags (Optional[List[str]], optional): Tags for the tool. Defaults to None.
1680
- description (str, optional): The description.
1681
- return_char_limit (int): The character limit for the tool's return value. Defaults to FUNCTION_RETURN_CHAR_LIMIT.
1682
-
1683
- Returns:
1684
- tool (Tool): The created tool.
1685
- """
1686
- # TODO: check if tool already exists
1687
- # TODO: how to load modules?
1688
- # parse source code/schema
1689
- source_code = parse_source_code(func)
1690
- source_type = "python"
1691
- if not tags:
1692
- tags = []
1693
-
1694
- # call server function
1695
- return self.server.tool_manager.create_tool(
1696
- Tool(
1697
- source_type=source_type,
1698
- source_code=source_code,
1699
- name=name,
1700
- tags=tags,
1701
- description=description,
1702
- return_char_limit=return_char_limit,
1703
- ),
1704
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1705
- )
1706
-
1707
- def create_or_update_tool(
1708
- self,
1709
- func,
1710
- name: Optional[str] = None,
1711
- tags: Optional[List[str]] = None,
1712
- description: Optional[str] = None,
1713
- return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT,
1714
- ) -> Tool:
1715
- """
1716
- Creates or updates a tool. This stores the source code of function on the server, so that the server can execute the function and generate an OpenAI JSON schemas for it when using with an agent.
1717
-
1718
- Args:
1719
- func (callable): The function to create a tool for.
1720
- name: (str): Name of the tool (must be unique per-user.)
1721
- tags (Optional[List[str]], optional): Tags for the tool. Defaults to None.
1722
- description (str, optional): The description.
1723
- return_char_limit (int): The character limit for the tool's return value. Defaults to FUNCTION_RETURN_CHAR_LIMIT.
1724
-
1725
- Returns:
1726
- tool (Tool): The created tool.
1727
- """
1728
- source_code = parse_source_code(func)
1729
- source_type = "python"
1730
- if not tags:
1731
- tags = []
1732
-
1733
- # call server function
1734
- return self.server.tool_manager.create_or_update_tool(
1735
- Tool(
1736
- source_type=source_type,
1737
- source_code=source_code,
1738
- name=name,
1739
- tags=tags,
1740
- description=description,
1741
- return_char_limit=return_char_limit,
1742
- ),
1743
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1744
- )
1745
-
1746
- def update_tool(
1747
- self,
1748
- id: str,
1749
- name: Optional[str] = None,
1750
- description: Optional[str] = None,
1751
- func: Optional[callable] = None,
1752
- tags: Optional[List[str]] = None,
1753
- return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT,
1754
- ) -> Tool:
1755
- """
1756
- Update a tool with provided parameters (name, func, tags)
1757
-
1758
- Args:
1759
- id (str): ID of the tool
1760
- name (str): Name of the tool
1761
- func (callable): Function to wrap in a tool
1762
- tags (List[str]): Tags for the tool
1763
- return_char_limit (int): The character limit for the tool's return value. Defaults to FUNCTION_RETURN_CHAR_LIMIT.
1764
-
1765
- Returns:
1766
- tool (Tool): Updated tool
1767
- """
1768
- update_data = {
1769
- "source_type": "python", # Always include source_type
1770
- "source_code": parse_source_code(func) if func else None,
1771
- "tags": tags,
1772
- "name": name,
1773
- "description": description,
1774
- "return_char_limit": return_char_limit,
1775
- }
1776
-
1777
- # Filter out any None values from the dictionary
1778
- update_data = {
1779
- key: value for key, value in update_data.items() if value is not None
1780
- }
1781
-
1782
- return self.server.tool_manager.update_tool_by_id(
1783
- tool_id=id,
1784
- tool_update=ToolUpdate(**update_data),
1785
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1786
- )
1787
-
1788
- def list_tools(
1789
- self, cursor: Optional[str] = None, limit: Optional[int] = 50
1790
- ) -> List[Tool]:
1791
- """
1792
- List available tools for the user.
1793
-
1794
- Returns:
1795
- tools (List[Tool]): List of tools
1796
- """
1797
- return self.server.tool_manager.list_tools(
1798
- cursor=cursor,
1799
- limit=limit,
1800
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1801
- )
1802
-
1803
- def get_tool(self, id: str) -> Optional[Tool]:
1804
- """
1805
- Get a tool given its ID.
1806
-
1807
- Args:
1808
- id (str): ID of the tool
1809
-
1810
- Returns:
1811
- tool (Tool): Tool
1812
- """
1813
- return self.server.tool_manager.get_tool_by_id(
1814
- id, actor=self.server.user_manager.get_user_by_id(self.user.id)
1815
- )
1816
-
1817
- def delete_tool(self, id: str):
1818
- """
1819
- Delete a tool given the ID.
1820
-
1821
- Args:
1822
- id (str): ID of the tool
1823
- """
1824
- return self.server.tool_manager.delete_tool_by_id(
1825
- id, actor=self.server.user_manager.get_user_by_id(self.user.id)
1826
- )
1827
-
1828
- def get_tool_id(self, name: str) -> Optional[str]:
1829
- """
1830
- Get the ID of a tool from its name. The client will use the org_id it is configured with.
1831
-
1832
- Args:
1833
- name (str): Name of the tool
1834
-
1835
- Returns:
1836
- id (str): ID of the tool (`None` if not found)
1837
- """
1838
- tool = self.server.tool_manager.get_tool_by_name(
1839
- tool_name=name, actor=self.server.user_manager.get_user_by_id(self.user.id)
1840
- )
1841
- return tool.id if tool else None
1842
-
1843
- # recall memory
1844
-
1845
- def get_messages(
1846
- self, agent_id: str, cursor: Optional[str] = None, limit: Optional[int] = 1000
1847
- ) -> List[Message]:
1848
- """
1849
- Get messages from an agent with pagination.
1850
-
1851
- Args:
1852
- agent_id (str): ID of the agent
1853
- cursor (str): Get messages after a certain time
1854
- limit (int): Limit number of messages
1855
-
1856
- Returns:
1857
- messages (List[Message]): List of messages
1858
- """
1859
-
1860
- self.interface.clear()
1861
- return self.server.get_agent_recall_cursor(
1862
- user_id=self.user_id,
1863
- agent_id=agent_id,
1864
- before=cursor,
1865
- limit=limit,
1866
- reverse=True,
1867
- )
1868
-
1869
- def list_blocks(
1870
- self, label: Optional[str] = None, templates_only: Optional[bool] = True
1871
- ) -> List[Block]:
1872
- """
1873
- List available blocks
1874
-
1875
- Args:
1876
- label (str): Label of the block
1877
- templates_only (bool): List only templates
1878
-
1879
- Returns:
1880
- blocks (List[Block]): List of blocks
1881
- """
1882
- blocks = self.server.block_manager.get_blocks(
1883
- actor=self.server.user_manager.get_user_by_id(self.user.id),
1884
- label=label,
1885
- )
1886
- return blocks
1887
-
1888
- def create_block(
1889
- self,
1890
- label: str,
1891
- value: str,
1892
- limit: Optional[int] = None,
1893
- ) -> Block: #
1894
- """
1895
- Create a block
1896
-
1897
- Args:
1898
- label (str): Label of the block
1899
- text (str): Text of the block
1900
- limit (int): Character of the block
1901
-
1902
- Returns:
1903
- block (Block): Created block
1904
- """
1905
- block = Block(
1906
- label=label,
1907
- value=value,
1908
- limit=limit,
1909
- )
1910
- # if limit:
1911
- # block.limit = limit
1912
- return self.server.block_manager.create_or_update_block(
1913
- block, actor=self.server.user_manager.get_user_by_id(self.user.id)
1914
- )
1915
-
1916
- def get_block(self, block_id: str) -> Block:
1917
- """
1918
- Get a block
1919
-
1920
- Args:
1921
- block_id (str): ID of the block
1922
-
1923
- Returns:
1924
- block (Block): Block
1925
- """
1926
- return self.server.block_manager.get_block_by_id(
1927
- block_id, actor=self.server.user_manager.get_user_by_id(self.user.id)
1928
- )
1929
-
1930
- def delete_block(self, id: str) -> Block:
1931
- """
1932
- Delete a block
1933
-
1934
- Args:
1935
- id (str): ID of the block
1936
-
1937
- Returns:
1938
- block (Block): Deleted block
1939
- """
1940
- return self.server.block_manager.delete_block(
1941
- id, actor=self.server.user_manager.get_user_by_id(self.user.id)
1942
- )
1943
-
1944
- def set_default_llm_config(self, llm_config: LLMConfig):
1945
- """
1946
- Set the default LLM configuration for agents.
1947
-
1948
- Args:
1949
- llm_config (LLMConfig): LLM configuration
1950
- """
1951
- self._default_llm_config = llm_config
1952
-
1953
- def set_default_embedding_config(self, embedding_config: EmbeddingConfig):
1954
- """
1955
- Set the default embedding configuration for agents.
1956
-
1957
- Args:
1958
- embedding_config (EmbeddingConfig): Embedding configuration
1959
- """
1960
- self._default_embedding_config = embedding_config
1961
-
1962
- def list_llm_configs(self) -> List[LLMConfig]:
1963
- """
1964
- List available LLM configurations
1965
-
1966
- Returns:
1967
- configs (List[LLMConfig]): List of LLM configurations
1968
- """
1969
- return self.server.list_llm_models()
1970
-
1971
- def list_embedding_configs(self) -> List[EmbeddingConfig]:
1972
- """
1973
- List available embedding configurations
1974
-
1975
- Returns:
1976
- configs (List[EmbeddingConfig]): List of embedding configurations
1977
- """
1978
- return self.server.list_embedding_models()
1979
-
1980
- def create_org(self, name: Optional[str] = None) -> Organization:
1981
- return self.server.organization_manager.create_organization(
1982
- pydantic_org=Organization(name=name)
1983
- )
1984
-
1985
- def list_orgs(
1986
- self, cursor: Optional[str] = None, limit: Optional[int] = 50
1987
- ) -> List[Organization]:
1988
- return self.server.organization_manager.list_organizations(
1989
- cursor=cursor, limit=limit
1990
- )
1991
-
1992
- def delete_org(self, org_id: str) -> Organization:
1993
- return self.server.organization_manager.delete_organization_by_id(org_id=org_id)
1994
-
1995
- def create_sandbox_config(
1996
- self, config: Union[LocalSandboxConfig, E2BSandboxConfig]
1997
- ) -> SandboxConfig:
1998
- """
1999
- Create a new sandbox configuration.
2000
- """
2001
- config_create = SandboxConfigCreate(config=config)
2002
- return self.server.sandbox_config_manager.create_or_update_sandbox_config(
2003
- sandbox_config_create=config_create,
2004
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2005
- )
2006
-
2007
- def update_sandbox_config(
2008
- self,
2009
- sandbox_config_id: str,
2010
- config: Union[LocalSandboxConfig, E2BSandboxConfig],
2011
- ) -> SandboxConfig:
2012
- """
2013
- Update an existing sandbox configuration.
2014
- """
2015
- sandbox_update = SandboxConfigUpdate(config=config)
2016
- return self.server.sandbox_config_manager.update_sandbox_config(
2017
- sandbox_config_id=sandbox_config_id,
2018
- sandbox_update=sandbox_update,
2019
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2020
- )
2021
-
2022
- def delete_sandbox_config(self, sandbox_config_id: str) -> None:
2023
- """
2024
- Delete a sandbox configuration.
2025
- """
2026
- return self.server.sandbox_config_manager.delete_sandbox_config(
2027
- sandbox_config_id=sandbox_config_id,
2028
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2029
- )
2030
-
2031
- def list_sandbox_configs(
2032
- self, limit: int = 50, cursor: Optional[str] = None
2033
- ) -> List[SandboxConfig]:
2034
- """
2035
- List all sandbox configurations.
2036
- """
2037
- return self.server.sandbox_config_manager.list_sandbox_configs(
2038
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2039
- limit=limit,
2040
- cursor=cursor,
2041
- )
2042
-
2043
- def create_sandbox_env_var(
2044
- self,
2045
- sandbox_config_id: str,
2046
- key: str,
2047
- value: str,
2048
- description: Optional[str] = None,
2049
- ) -> SandboxEnvironmentVariable:
2050
- """
2051
- Create a new environment variable for a sandbox configuration.
2052
- """
2053
- env_var_create = SandboxEnvironmentVariableCreate(
2054
- key=key, value=value, description=description
2055
- )
2056
- return self.server.sandbox_config_manager.create_sandbox_env_var(
2057
- env_var_create=env_var_create,
2058
- sandbox_config_id=sandbox_config_id,
2059
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2060
- )
2061
-
2062
- def update_sandbox_env_var(
2063
- self,
2064
- env_var_id: str,
2065
- key: Optional[str] = None,
2066
- value: Optional[str] = None,
2067
- description: Optional[str] = None,
2068
- ) -> SandboxEnvironmentVariable:
2069
- """
2070
- Update an existing environment variable.
2071
- """
2072
- env_var_update = SandboxEnvironmentVariableUpdate(
2073
- key=key, value=value, description=description
2074
- )
2075
- return self.server.sandbox_config_manager.update_sandbox_env_var(
2076
- env_var_id=env_var_id,
2077
- env_var_update=env_var_update,
2078
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2079
- )
2080
-
2081
- def delete_sandbox_env_var(self, env_var_id: str) -> None:
2082
- """
2083
- Delete an environment variable by its ID.
2084
- """
2085
- return self.server.sandbox_config_manager.delete_sandbox_env_var(
2086
- env_var_id=env_var_id,
2087
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2088
- )
2089
-
2090
- def list_sandbox_env_vars(
2091
- self, sandbox_config_id: str, limit: int = 50, cursor: Optional[str] = None
2092
- ) -> List[SandboxEnvironmentVariable]:
2093
- """
2094
- List all environment variables associated with a sandbox configuration.
2095
- """
2096
- return self.server.sandbox_config_manager.list_sandbox_env_vars(
2097
- sandbox_config_id=sandbox_config_id,
2098
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2099
- limit=limit,
2100
- cursor=cursor,
2101
- )
2102
-
2103
- # file management methods
2104
- def save_file(
2105
- self, file_path: str, source_id: Optional[str] = None
2106
- ) -> FileMetadata:
2107
- """
2108
- Save a file to the file manager and return its metadata.
2109
-
2110
- Args:
2111
- file_path (str): Path to the file to save
2112
- source_id (Optional[str]): Optional source ID to associate with the file
2113
-
2114
- Returns:
2115
- FileMetadata: The created file metadata
2116
- """
2117
- return self.file_manager.create_file_metadata_from_path(
2118
- file_path=file_path, organization_id=self.org_id, source_id=source_id
2119
- )
2120
-
2121
- def list_files(
2122
- self, cursor: Optional[str] = None, limit: Optional[int] = 50
2123
- ) -> List[FileMetadata]:
2124
- """
2125
- List files for the current organization.
2126
-
2127
- Args:
2128
- cursor (Optional[str]): Pagination cursor
2129
- limit (Optional[int]): Maximum number of files to return
2130
-
2131
- Returns:
2132
- List[FileMetadata]: List of file metadata
2133
- """
2134
- return self.file_manager.get_files_by_organization_id(
2135
- organization_id=self.org_id, cursor=cursor, limit=limit
2136
- )
2137
-
2138
- def get_file(self, file_id: str) -> FileMetadata:
2139
- """
2140
- Get file metadata by ID.
2141
-
2142
- Args:
2143
- file_id (str): ID of the file
2144
-
2145
- Returns:
2146
- FileMetadata: The file metadata
2147
- """
2148
- return self.file_manager.get_file_metadata_by_id(file_id)
2149
-
2150
- def delete_file(self, file_id: str) -> None:
2151
- """
2152
- Delete a file by ID.
2153
-
2154
- Args:
2155
- file_id (str): ID of the file to delete
2156
- """
2157
- self.file_manager.delete_file_metadata(file_id)
2158
-
2159
- def search_files(self, name_pattern: str) -> List[FileMetadata]:
2160
- """
2161
- Search files by name pattern.
2162
-
2163
- Args:
2164
- name_pattern (str): Pattern to search for in file names
2165
-
2166
- Returns:
2167
- List[FileMetadata]: List of matching files
2168
- """
2169
- return self.file_manager.search_files_by_name(
2170
- file_name=name_pattern, organization_id=self.org_id
2171
- )
2172
-
2173
- def get_file_stats(self) -> dict:
2174
- """
2175
- Get file statistics for the current organization.
2176
-
2177
- Returns:
2178
- dict: File statistics including total files, size, and types
2179
- """
2180
- return self.file_manager.get_file_stats(organization_id=self.org_id)
2181
-
2182
- def update_agent_memory_block_label(
2183
- self, agent_id: str, current_label: str, new_label: str
2184
- ) -> Memory:
2185
- """Rename a block in the agent's core memory
2186
-
2187
- Args:
2188
- agent_id (str): The agent ID
2189
- current_label (str): The current label of the block
2190
- new_label (str): The new label of the block
2191
-
2192
- Returns:
2193
- memory (Memory): The updated memory
2194
- """
2195
- block = self.get_agent_memory_block(agent_id, current_label)
2196
- return self.update_block(block.id, label=new_label)
2197
-
2198
- # TODO: remove this
2199
- def add_agent_memory_block(
2200
- self, agent_id: str, create_block: CreateBlock
2201
- ) -> Memory:
2202
- """
2203
- Create and link a memory block to an agent's core memory
2204
-
2205
- Args:
2206
- agent_id (str): The agent ID
2207
- create_block (CreateBlock): The block to create
2208
-
2209
- Returns:
2210
- memory (Memory): The updated memory
2211
- """
2212
- block_req = Block(**create_block.model_dump())
2213
- block = self.server.block_manager.create_or_update_block(
2214
- actor=self.server.user_manager.get_user_by_id(self.user.id), block=block_req
2215
- )
2216
- # Link the block to the agent
2217
- agent = self.server.agent_manager.attach_block(
2218
- agent_id=agent_id,
2219
- block_id=block.id,
2220
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2221
- )
2222
- return agent.memory
2223
-
2224
- def link_agent_memory_block(self, agent_id: str, block_id: str) -> Memory:
2225
- """
2226
- Link a block to an agent's core memory
2227
-
2228
- Args:
2229
- agent_id (str): The agent ID
2230
- block_id (str): The block ID
2231
-
2232
- Returns:
2233
- memory (Memory): The updated memory
2234
- """
2235
- return self.server.agent_manager.attach_block(
2236
- agent_id=agent_id,
2237
- block_id=block_id,
2238
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2239
- )
2240
-
2241
- def remove_agent_memory_block(self, agent_id: str, block_label: str) -> Memory:
2242
- """
2243
- Unlike a block from the agent's core memory
2244
-
2245
- Args:
2246
- agent_id (str): The agent ID
2247
- block_label (str): The block label
2248
-
2249
- Returns:
2250
- memory (Memory): The updated memory
2251
- """
2252
- return self.server.agent_manager.detach_block_with_label(
2253
- agent_id=agent_id,
2254
- block_label=block_label,
2255
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2256
- )
2257
-
2258
- def list_agent_memory_blocks(self, agent_id: str) -> List[Block]:
2259
- """
2260
- Get all the blocks in the agent's core memory
2261
-
2262
- Args:
2263
- agent_id (str): The agent ID
2264
-
2265
- Returns:
2266
- blocks (List[Block]): The blocks in the agent's core memory
2267
- """
2268
- agent = self.server.agent_manager.get_agent_by_id(
2269
- agent_id=agent_id,
2270
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2271
- )
2272
- return agent.memory.blocks
2273
-
2274
- def get_agent_memory_block(self, agent_id: str, label: str) -> Block:
2275
- """
2276
- Get a block in the agent's core memory by its label
2277
-
2278
- Args:
2279
- agent_id (str): The agent ID
2280
- label (str): The label in the agent's core memory
2281
-
2282
- Returns:
2283
- block (Block): The block corresponding to the label
2284
- """
2285
- return self.server.agent_manager.get_block_with_label(
2286
- agent_id=agent_id,
2287
- block_label=label,
2288
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2289
- )
2290
-
2291
- def update_agent_memory_block(
2292
- self,
2293
- agent_id: str,
2294
- label: str,
2295
- value: Optional[str] = None,
2296
- limit: Optional[int] = None,
2297
- ):
2298
- """
2299
- Update a block in the agent's core memory by specifying its label
2300
-
2301
- Args:
2302
- agent_id (str): The agent ID
2303
- label (str): The label of the block
2304
- value (str): The new value of the block
2305
- limit (int): The new limit of the block
2306
-
2307
- Returns:
2308
- block (Block): The updated block
2309
- """
2310
- block = self.get_agent_memory_block(agent_id, label)
2311
- data = {}
2312
- if value:
2313
- data["value"] = value
2314
- if limit:
2315
- data["limit"] = limit
2316
- return self.server.block_manager.update_block(
2317
- block.id,
2318
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2319
- block_update=BlockUpdate(**data),
2320
- )
2321
-
2322
- def update_block(
2323
- self,
2324
- block_id: str,
2325
- label: Optional[str] = None,
2326
- value: Optional[str] = None,
2327
- limit: Optional[int] = None,
2328
- ):
2329
- """
2330
- Update a block given the ID with the provided fields
2331
-
2332
- Args:
2333
- block_id (str): ID of the block
2334
- label (str): Label to assign to the block
2335
- value (str): Value to assign to the block
2336
- limit (int): Token limit to assign to the block
2337
-
2338
- Returns:
2339
- block (Block): Updated block
2340
- """
2341
- data = {}
2342
- if value:
2343
- data["value"] = value
2344
- if limit:
2345
- data["limit"] = limit
2346
- if label:
2347
- data["label"] = label
2348
- return self.server.block_manager.update_block(
2349
- block_id,
2350
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2351
- block_update=BlockUpdate(**data),
2352
- )
2353
-
2354
- def get_tags(
2355
- self,
2356
- cursor: str = None,
2357
- limit: int = 100,
2358
- query_text: str = None,
2359
- ) -> List[str]:
2360
- """
2361
- Get all tags.
2362
-
2363
- Returns:
2364
- tags (List[str]): List of tags
2365
- """
2366
- return self.server.agent_manager.list_tags(
2367
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2368
- cursor=cursor,
2369
- limit=limit,
2370
- query_text=query_text,
2371
- )
2372
-
2373
- def retrieve_memory(
2374
- self,
2375
- agent_id: str,
2376
- query: str,
2377
- memory_type: str = "all",
2378
- search_field: str = "null",
2379
- search_method: str = "embedding",
2380
- timezone_str: str = "UTC",
2381
- limit: int = 10,
2382
- ) -> dict:
2383
- """
2384
- Retrieve memories by searching across different memory types.
2385
-
2386
- Args:
2387
- agent_id (str): ID of the agent to retrieve memories for
2388
- query (str): The keywords/query used to search in the memory
2389
- memory_type (str): The type of memory to search in. Options: "episodic", "resource", "procedural",
2390
- "knowledge_vault", "semantic", "all". Defaults to "all".
2391
- search_field (str): The field to search in the memory. For "episodic": 'summary', 'details';
2392
- for "resource": 'summary', 'content'; for "procedural": 'summary', 'steps';
2393
- for "knowledge_vault": 'secret_value', 'caption'; for "semantic": 'name', 'summary', 'details'.
2394
- Use "null" for default fields. Defaults to "null".
2395
- search_method (str): The method to search. Options: 'bm25' (keyword-based), 'embedding' (semantic).
2396
- Defaults to "embedding".
2397
- timezone_str (str): Timezone string for time-based operations. Defaults to "UTC".
2398
- limit (int): Maximum number of results to return per memory type. Defaults to 10.
2399
-
2400
- Returns:
2401
- dict: Dictionary containing 'results' (list of memories) and 'count' (total number of results)
2402
- """
2403
- # Import here to avoid circular imports
2404
-
2405
- # Validate inputs
2406
- if (
2407
- memory_type == "resource"
2408
- and search_field == "content"
2409
- and search_method == "embedding"
2410
- ):
2411
- raise ValueError(
2412
- "embedding is not supported for resource memory's 'content' field."
2413
- )
2414
- if (
2415
- memory_type == "knowledge_vault"
2416
- and search_field == "secret_value"
2417
- and search_method == "embedding"
2418
- ):
2419
- raise ValueError(
2420
- "embedding is not supported for knowledge_vault memory's 'secret_value' field."
2421
- )
2422
-
2423
- # Get the agent to access its memory managers
2424
- agent_state = self.server.agent_manager.get_agent_by_id(
2425
- agent_id=agent_id,
2426
- actor=self.server.user_manager.get_user_by_id(self.user.id),
2427
- )
2428
-
2429
- if memory_type == "all":
2430
- search_field = "null"
2431
-
2432
- # Initialize result lists
2433
- formatted_results = []
2434
-
2435
- # Search episodic memory
2436
- if memory_type == "episodic" or memory_type == "all":
2437
- episodic_memory = self.server.episodic_memory_manager.list_episodic_memory(
2438
- actor=self.user,
2439
- agent_state=agent_state,
2440
- query=query,
2441
- search_field=search_field if search_field != "null" else "summary",
2442
- search_method=search_method,
2443
- limit=limit,
2444
- timezone_str=timezone_str,
2445
- )
2446
- formatted_results_episodic = [
2447
- {
2448
- "memory_type": "episodic",
2449
- "id": x.id,
2450
- "timestamp": x.occurred_at,
2451
- "event_type": x.event_type,
2452
- "actor": x.actor,
2453
- "summary": x.summary,
2454
- "details": x.details,
2455
- }
2456
- for x in episodic_memory
2457
- ]
2458
- if memory_type == "episodic":
2459
- return {
2460
- "results": formatted_results_episodic,
2461
- "count": len(formatted_results_episodic),
2462
- }
2463
- formatted_results.extend(formatted_results_episodic)
2464
-
2465
- # Search resource memory
2466
- if memory_type == "resource" or memory_type == "all":
2467
- resource_memories = self.server.resource_memory_manager.list_resources(
2468
- actor=self.user,
2469
- agent_state=agent_state,
2470
- query=query,
2471
- search_field=search_field
2472
- if search_field != "null"
2473
- else ("summary" if search_method == "embedding" else "content"),
2474
- search_method=search_method,
2475
- limit=limit,
2476
- timezone_str=timezone_str,
2477
- )
2478
- formatted_results_resource = [
2479
- {
2480
- "memory_type": "resource",
2481
- "id": x.id,
2482
- "resource_type": x.resource_type,
2483
- "summary": x.summary,
2484
- "content": x.content,
2485
- }
2486
- for x in resource_memories
2487
- ]
2488
- if memory_type == "resource":
2489
- return {
2490
- "results": formatted_results_resource,
2491
- "count": len(formatted_results_resource),
2492
- }
2493
- formatted_results.extend(formatted_results_resource)
2494
-
2495
- # Search procedural memory
2496
- if memory_type == "procedural" or memory_type == "all":
2497
- procedural_memories = self.server.procedural_memory_manager.list_procedures(
2498
- actor=self.user,
2499
- agent_state=agent_state,
2500
- query=query,
2501
- search_field=search_field if search_field != "null" else "summary",
2502
- search_method=search_method,
2503
- limit=limit,
2504
- timezone_str=timezone_str,
2505
- )
2506
- formatted_results_procedural = [
2507
- {
2508
- "memory_type": "procedural",
2509
- "id": x.id,
2510
- "entry_type": x.entry_type,
2511
- "summary": x.summary,
2512
- "steps": x.steps,
2513
- }
2514
- for x in procedural_memories
2515
- ]
2516
- if memory_type == "procedural":
2517
- return {
2518
- "results": formatted_results_procedural,
2519
- "count": len(formatted_results_procedural),
2520
- }
2521
- formatted_results.extend(formatted_results_procedural)
2522
-
2523
- # Search knowledge vault
2524
- if memory_type == "knowledge_vault" or memory_type == "all":
2525
- knowledge_vault_memories = (
2526
- self.server.knowledge_vault_manager.list_knowledge(
2527
- actor=self.user,
2528
- agent_state=agent_state,
2529
- query=query,
2530
- search_field=search_field if search_field != "null" else "caption",
2531
- search_method=search_method,
2532
- limit=limit,
2533
- timezone_str=timezone_str,
2534
- )
2535
- )
2536
- formatted_results_knowledge_vault = [
2537
- {
2538
- "memory_type": "knowledge_vault",
2539
- "id": x.id,
2540
- "entry_type": x.entry_type,
2541
- "source": x.source,
2542
- "sensitivity": x.sensitivity,
2543
- "secret_value": x.secret_value,
2544
- "caption": x.caption,
2545
- }
2546
- for x in knowledge_vault_memories
2547
- ]
2548
- if memory_type == "knowledge_vault":
2549
- return {
2550
- "results": formatted_results_knowledge_vault,
2551
- "count": len(formatted_results_knowledge_vault),
2552
- }
2553
- formatted_results.extend(formatted_results_knowledge_vault)
2554
-
2555
- # Search semantic memory
2556
- if memory_type == "semantic" or memory_type == "all":
2557
- semantic_memories = self.server.semantic_memory_manager.list_semantic_items(
2558
- actor=self.user,
2559
- agent_state=agent_state,
2560
- query=query,
2561
- search_field=search_field if search_field != "null" else "summary",
2562
- search_method=search_method,
2563
- limit=limit,
2564
- timezone_str=timezone_str,
2565
- )
2566
- formatted_results_semantic = [
2567
- {
2568
- "memory_type": "semantic",
2569
- "id": x.id,
2570
- "name": x.name,
2571
- "summary": x.summary,
2572
- "details": x.details,
2573
- "source": x.source,
2574
- }
2575
- for x in semantic_memories
2576
- ]
2577
- if memory_type == "semantic":
2578
- return {
2579
- "results": formatted_results_semantic,
2580
- "count": len(formatted_results_semantic),
2581
- }
2582
- formatted_results.extend(formatted_results_semantic)
2583
-
2584
- return {"results": formatted_results, "count": len(formatted_results)}