jl-ecms-client 0.2.5__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.
- {jl_ecms_client-0.2.5.dist-info → jl_ecms_client-0.2.19.dist-info}/METADATA +6 -1
- {jl_ecms_client-0.2.5.dist-info → jl_ecms_client-0.2.19.dist-info}/RECORD +29 -22
- mirix/__init__.py +32 -0
- mirix/client/__init__.py +5 -63
- mirix/client/client.py +6 -2195
- mirix/client/utils.py +34 -0
- mirix/constants.py +251 -0
- mirix/errors.py +238 -0
- mirix/helpers/json_helpers.py +3 -3
- mirix/log.py +163 -0
- mirix/schemas/agent.py +5 -4
- mirix/schemas/cloud_file_mapping.py +1 -1
- mirix/schemas/embedding_config.py +0 -3
- mirix/schemas/enums.py +12 -0
- mirix/schemas/episodic_memory.py +1 -1
- mirix/schemas/knowledge_vault.py +1 -1
- mirix/schemas/mirix_response.py +1 -1
- mirix/schemas/organization.py +5 -5
- mirix/schemas/procedural_memory.py +1 -1
- mirix/schemas/resource_memory.py +1 -1
- mirix/schemas/sandbox_config.py +1 -3
- mirix/schemas/semantic_memory.py +1 -1
- mirix/schemas/tool.py +241 -241
- mirix/schemas/user.py +3 -3
- mirix/settings.py +280 -0
- mirix/system.py +261 -0
- {jl_ecms_client-0.2.5.dist-info → jl_ecms_client-0.2.19.dist-info}/WHEEL +0 -0
- {jl_ecms_client-0.2.5.dist-info → jl_ecms_client-0.2.19.dist-info}/licenses/LICENSE +0 -0
- {jl_ecms_client-0.2.5.dist-info → jl_ecms_client-0.2.19.dist-info}/top_level.txt +0 -0
mirix/log.py
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from logging.handlers import RotatingFileHandler
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from mirix.settings import settings
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_log_level() -> int:
|
|
12
|
+
"""Get the configured log level."""
|
|
13
|
+
if settings.debug:
|
|
14
|
+
return logging.DEBUG
|
|
15
|
+
|
|
16
|
+
# Map string level to logging constant
|
|
17
|
+
level_map = {
|
|
18
|
+
"DEBUG": logging.DEBUG,
|
|
19
|
+
"INFO": logging.INFO,
|
|
20
|
+
"WARNING": logging.WARNING,
|
|
21
|
+
"ERROR": logging.ERROR,
|
|
22
|
+
"CRITICAL": logging.CRITICAL,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return level_map.get(settings.log_level.upper(), logging.INFO)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
selected_log_level = get_log_level()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def validate_log_file_path(log_file_path: Path) -> Path:
|
|
32
|
+
"""
|
|
33
|
+
Validate that the log file path is writable.
|
|
34
|
+
|
|
35
|
+
Checks:
|
|
36
|
+
- Path is not a directory
|
|
37
|
+
- Parent directory exists or can be created
|
|
38
|
+
- We have write permissions to the directory
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
log_file_path: Path to the log file
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Path: Validated absolute path
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
ValueError: If the path is invalid or not writable
|
|
48
|
+
"""
|
|
49
|
+
# Convert to absolute path
|
|
50
|
+
log_file_path = log_file_path.expanduser().resolve()
|
|
51
|
+
|
|
52
|
+
# Check if path exists and is a directory (not allowed)
|
|
53
|
+
if log_file_path.exists() and log_file_path.is_dir():
|
|
54
|
+
raise ValueError(
|
|
55
|
+
f"Invalid log file path: '{log_file_path}' is a directory. "
|
|
56
|
+
f"MIRIX_LOG_FILE must be a file path, not a directory."
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Get parent directory
|
|
60
|
+
parent_dir = log_file_path.parent
|
|
61
|
+
|
|
62
|
+
# Try to create parent directory if it doesn't exist
|
|
63
|
+
try:
|
|
64
|
+
parent_dir.mkdir(parents=True, exist_ok=True)
|
|
65
|
+
except (OSError, PermissionError) as e:
|
|
66
|
+
raise ValueError(
|
|
67
|
+
f"Invalid log file path: Cannot create directory '{parent_dir}'. "
|
|
68
|
+
f"Error: {e}"
|
|
69
|
+
) from e
|
|
70
|
+
|
|
71
|
+
# Check if parent directory is writable
|
|
72
|
+
if not os.access(parent_dir, os.W_OK):
|
|
73
|
+
raise ValueError(
|
|
74
|
+
f"Invalid log file path: Directory '{parent_dir}' is not writable. "
|
|
75
|
+
f"Check permissions for MIRIX_LOG_FILE."
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# If file exists, check if it's writable
|
|
79
|
+
if log_file_path.exists() and not os.access(log_file_path, os.W_OK):
|
|
80
|
+
raise ValueError(
|
|
81
|
+
f"Invalid log file path: File '{log_file_path}' exists but is not writable. "
|
|
82
|
+
f"Check file permissions for MIRIX_LOG_FILE."
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
return log_file_path
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_logger(name: Optional[str] = None) -> "logging.Logger":
|
|
89
|
+
"""
|
|
90
|
+
Get the Mirix logger with configured handlers.
|
|
91
|
+
|
|
92
|
+
Log Level Configuration:
|
|
93
|
+
- Single log level (MIRIX_LOG_LEVEL) applies to ALL handlers
|
|
94
|
+
- Controlled by: MIRIX_LOG_LEVEL or MIRIX_DEBUG environment variables
|
|
95
|
+
- Same level used for both console and file output
|
|
96
|
+
|
|
97
|
+
Handler Configuration (Default Behavior):
|
|
98
|
+
- Console: ALWAYS enabled UNLESS explicitly disabled (MIRIX_LOG_TO_CONSOLE=false)
|
|
99
|
+
- File: Automatically enabled if MIRIX_LOG_FILE is set with a valid path
|
|
100
|
+
- Handlers determine WHERE logs go, NOT what level they use
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
logging.Logger: Configured logger instance
|
|
104
|
+
|
|
105
|
+
Raises:
|
|
106
|
+
ValueError: If MIRIX_LOG_FILE is set but the path is invalid or not writable
|
|
107
|
+
"""
|
|
108
|
+
logger = logging.getLogger("Mirix")
|
|
109
|
+
|
|
110
|
+
# Set the log level ONCE for the entire logger
|
|
111
|
+
# This single level applies to all handlers (console and file)
|
|
112
|
+
logger.setLevel(selected_log_level)
|
|
113
|
+
|
|
114
|
+
# Add handlers if not already configured
|
|
115
|
+
# Handlers control WHERE logs go (console/file), not WHAT level they use
|
|
116
|
+
if not logger.handlers:
|
|
117
|
+
# Create a single formatter for consistency across all handlers
|
|
118
|
+
formatter = logging.Formatter(
|
|
119
|
+
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
120
|
+
datefmt='%Y-%m-%d %H:%M:%S'
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
handlers_added = []
|
|
124
|
+
|
|
125
|
+
# Console handler - ALWAYS enabled unless explicitly disabled
|
|
126
|
+
# Console logging is the default behavior
|
|
127
|
+
if settings.log_to_console:
|
|
128
|
+
console_handler = logging.StreamHandler(sys.stdout)
|
|
129
|
+
console_handler.setFormatter(formatter)
|
|
130
|
+
logger.addHandler(console_handler)
|
|
131
|
+
handlers_added.append("console")
|
|
132
|
+
|
|
133
|
+
# File handler - ONLY enabled if MIRIX_LOG_FILE is configured
|
|
134
|
+
# Automatically enabled when MIRIX_LOG_FILE is set
|
|
135
|
+
if settings.log_file is not None:
|
|
136
|
+
# Validate and get absolute path
|
|
137
|
+
# This will raise ValueError if path is invalid
|
|
138
|
+
log_file = validate_log_file_path(Path(settings.log_file))
|
|
139
|
+
|
|
140
|
+
# Create rotating file handler
|
|
141
|
+
file_handler = RotatingFileHandler(
|
|
142
|
+
log_file,
|
|
143
|
+
maxBytes=settings.log_max_bytes,
|
|
144
|
+
backupCount=settings.log_backup_count,
|
|
145
|
+
)
|
|
146
|
+
file_handler.setFormatter(formatter)
|
|
147
|
+
logger.addHandler(file_handler)
|
|
148
|
+
handlers_added.append(f"file ({log_file})")
|
|
149
|
+
|
|
150
|
+
# Log where logs are being written (if any handlers were added)
|
|
151
|
+
if handlers_added:
|
|
152
|
+
destinations = " and ".join(handlers_added)
|
|
153
|
+
log_level_name = logging.getLevelName(selected_log_level)
|
|
154
|
+
logger.info("Logging to: %s (level: %s)", destinations, log_level_name)
|
|
155
|
+
else:
|
|
156
|
+
# No handlers configured - add NullHandler to prevent warnings
|
|
157
|
+
# This only happens if console is explicitly disabled AND file is not configured
|
|
158
|
+
logger.addHandler(logging.NullHandler())
|
|
159
|
+
|
|
160
|
+
# Prevent propagation to root logger to avoid duplicate messages
|
|
161
|
+
logger.propagate = False
|
|
162
|
+
|
|
163
|
+
return logger
|
mirix/schemas/agent.py
CHANGED
|
@@ -14,7 +14,8 @@ from mirix.schemas.mirix_base import OrmMetadataBase
|
|
|
14
14
|
from mirix.schemas.openai.chat_completion_response import UsageStatistics
|
|
15
15
|
from mirix.schemas.tool import Tool
|
|
16
16
|
from mirix.schemas.tool_rule import ToolRule
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
# Removed create_random_username import - server generates names if not provided
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class AgentType(str, Enum):
|
|
@@ -108,9 +109,9 @@ class AgentState(OrmMetadataBase, validate_assignment=True):
|
|
|
108
109
|
|
|
109
110
|
class CreateAgent(BaseModel, validate_assignment=True): #
|
|
110
111
|
# all optional as server can generate defaults
|
|
111
|
-
name: str = Field(
|
|
112
|
-
|
|
113
|
-
description="The name of the agent.",
|
|
112
|
+
name: Optional[str] = Field(
|
|
113
|
+
None,
|
|
114
|
+
description="The name of the agent. If not provided, server will generate one.",
|
|
114
115
|
)
|
|
115
116
|
|
|
116
117
|
# memory creation
|
mirix/schemas/enums.py
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
class ToolType(str, Enum):
|
|
5
|
+
"""Types of tools in Mirix"""
|
|
6
|
+
CUSTOM = "custom"
|
|
7
|
+
MIRIX_CORE = "mirix_core"
|
|
8
|
+
MIRIX_CODER_CORE = "mirix_coder_core"
|
|
9
|
+
MIRIX_MEMORY_CORE = "mirix_memory_core"
|
|
10
|
+
MIRIX_EXTRA = "mirix_extra"
|
|
11
|
+
MIRIX_MCP = "mirix_mcp"
|
|
12
|
+
MIRIX_MULTI_AGENT_CORE = "mirix_multi_agent_core"
|
|
13
|
+
USER_DEFINED = "user_defined"
|
|
14
|
+
|
|
15
|
+
|
|
4
16
|
class ProviderType(str, Enum):
|
|
5
17
|
anthropic = "anthropic"
|
|
6
18
|
|
mirix/schemas/episodic_memory.py
CHANGED
|
@@ -3,10 +3,10 @@ from typing import Any, Dict, List, Optional
|
|
|
3
3
|
|
|
4
4
|
from pydantic import Field, field_validator
|
|
5
5
|
|
|
6
|
+
from mirix.client.utils import get_utc_time
|
|
6
7
|
from mirix.constants import MAX_EMBEDDING_DIM
|
|
7
8
|
from mirix.schemas.embedding_config import EmbeddingConfig
|
|
8
9
|
from mirix.schemas.mirix_base import MirixBase
|
|
9
|
-
from mirix.utils import get_utc_time
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class EpisodicEventBase(MirixBase):
|
mirix/schemas/knowledge_vault.py
CHANGED
|
@@ -3,10 +3,10 @@ from typing import Any, Dict, List, Optional
|
|
|
3
3
|
|
|
4
4
|
from pydantic import Field, field_validator
|
|
5
5
|
|
|
6
|
+
from mirix.client.utils import get_utc_time
|
|
6
7
|
from mirix.constants import MAX_EMBEDDING_DIM
|
|
7
8
|
from mirix.schemas.embedding_config import EmbeddingConfig
|
|
8
9
|
from mirix.schemas.mirix_base import MirixBase
|
|
9
|
-
from mirix.utils import get_utc_time
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class KnowledgeVaultItemBase(MirixBase):
|
mirix/schemas/mirix_response.py
CHANGED
|
@@ -5,10 +5,10 @@ from typing import List, Union
|
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel, Field
|
|
7
7
|
|
|
8
|
+
from mirix.client.utils import json_dumps
|
|
8
9
|
from mirix.schemas.enums import MessageStreamStatus
|
|
9
10
|
from mirix.schemas.mirix_message import MirixMessage, MirixMessageUnion
|
|
10
11
|
from mirix.schemas.usage import MirixUsageStatistics
|
|
11
|
-
from mirix.utils import json_dumps
|
|
12
12
|
|
|
13
13
|
# TODO: consider moving into own file
|
|
14
14
|
|
mirix/schemas/organization.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import uuid
|
|
1
2
|
from datetime import datetime
|
|
2
3
|
from typing import Optional
|
|
3
|
-
import uuid
|
|
4
4
|
|
|
5
5
|
from pydantic import Field
|
|
6
6
|
|
|
7
|
+
from mirix.client.utils import get_utc_time
|
|
7
8
|
from mirix.schemas.mirix_base import MirixBase
|
|
8
|
-
from mirix.utils import create_random_username, get_utc_time
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class OrganizationBase(MirixBase):
|
|
@@ -22,9 +22,9 @@ class Organization(OrganizationBase):
|
|
|
22
22
|
default_factory=_generate_org_id,
|
|
23
23
|
description="The unique identifier of the organization.",
|
|
24
24
|
)
|
|
25
|
-
name: str = Field(
|
|
26
|
-
|
|
27
|
-
description="The name of the organization.",
|
|
25
|
+
name: Optional[str] = Field(
|
|
26
|
+
None,
|
|
27
|
+
description="The name of the organization. Server will generate if not provided.",
|
|
28
28
|
json_schema_extra={"default": "SincereYogurt"},
|
|
29
29
|
)
|
|
30
30
|
created_at: Optional[datetime] = Field(
|
|
@@ -3,10 +3,10 @@ from typing import Any, Dict, List, Optional
|
|
|
3
3
|
|
|
4
4
|
from pydantic import Field, field_validator
|
|
5
5
|
|
|
6
|
+
from mirix.client.utils import get_utc_time
|
|
6
7
|
from mirix.constants import MAX_EMBEDDING_DIM
|
|
7
8
|
from mirix.schemas.embedding_config import EmbeddingConfig
|
|
8
9
|
from mirix.schemas.mirix_base import MirixBase
|
|
9
|
-
from mirix.utils import get_utc_time
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class ProceduralMemoryItemBase(MirixBase):
|
mirix/schemas/resource_memory.py
CHANGED
|
@@ -6,7 +6,7 @@ from pydantic import Field, field_validator
|
|
|
6
6
|
from mirix.constants import MAX_EMBEDDING_DIM
|
|
7
7
|
from mirix.schemas.embedding_config import EmbeddingConfig
|
|
8
8
|
from mirix.schemas.mirix_base import MirixBase
|
|
9
|
-
from mirix.utils import get_utc_time
|
|
9
|
+
from mirix.client.utils import get_utc_time
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class ResourceMemoryItemBase(MirixBase):
|
mirix/schemas/sandbox_config.py
CHANGED
|
@@ -8,12 +8,9 @@ from pydantic import BaseModel, Field, model_validator
|
|
|
8
8
|
from mirix.schemas.agent import AgentState
|
|
9
9
|
from mirix.schemas.mirix_base import MirixBase, OrmMetadataBase
|
|
10
10
|
from mirix.settings import tool_settings
|
|
11
|
-
from mirix.log import get_logger
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
# Sandbox Config
|
|
15
|
-
|
|
16
|
-
logger = get_logger(__name__)
|
|
17
14
|
class SandboxType(str, Enum):
|
|
18
15
|
E2B = "e2b"
|
|
19
16
|
LOCAL = "local"
|
|
@@ -73,6 +70,7 @@ class E2BSandboxConfig(BaseModel):
|
|
|
73
70
|
Assign a default template value if the template field is not provided.
|
|
74
71
|
"""
|
|
75
72
|
if data.get("template") is None:
|
|
73
|
+
# Use configured template if available
|
|
76
74
|
data["template"] = tool_settings.e2b_sandbox_template_id
|
|
77
75
|
return data
|
|
78
76
|
|
mirix/schemas/semantic_memory.py
CHANGED
|
@@ -6,7 +6,7 @@ from pydantic import Field, field_validator
|
|
|
6
6
|
from mirix.constants import MAX_EMBEDDING_DIM
|
|
7
7
|
from mirix.schemas.embedding_config import EmbeddingConfig
|
|
8
8
|
from mirix.schemas.mirix_base import MirixBase
|
|
9
|
-
from mirix.utils import get_utc_time
|
|
9
|
+
from mirix.client.utils import get_utc_time
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class SemanticMemoryItemBase(MirixBase):
|