Skip to content

Commit c7bd597

Browse files
Merge branch 'main' into gl/chore/tools-ruff-linting-fixes
2 parents 0e84347 + 9c1096d commit c7bd597

File tree

2 files changed

+79
-14
lines changed

2 files changed

+79
-14
lines changed

src/crewai/cli/config.py

Lines changed: 78 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import json
2+
import tempfile
3+
from logging import getLogger
24
from pathlib import Path
35

46
from pydantic import BaseModel, Field
@@ -12,8 +14,48 @@
1214
)
1315
from crewai.cli.shared.token_manager import TokenManager
1416

17+
logger = getLogger(__name__)
18+
1519
DEFAULT_CONFIG_PATH = Path.home() / ".config" / "crewai" / "settings.json"
1620

21+
22+
def get_writable_config_path() -> Path | None:
23+
"""
24+
Find a writable location for the config file with fallback options.
25+
26+
Tries in order:
27+
1. Default: ~/.config/crewai/settings.json
28+
2. Temp directory: /tmp/crewai_settings.json (or OS equivalent)
29+
3. Current directory: ./crewai_settings.json
30+
4. In-memory only (returns None)
31+
32+
Returns:
33+
Path object for writable config location, or None if no writable location found
34+
"""
35+
fallback_paths = [
36+
DEFAULT_CONFIG_PATH, # Default location
37+
Path(tempfile.gettempdir()) / "crewai_settings.json", # Temporary directory
38+
Path.cwd() / "crewai_settings.json", # Current working directory
39+
]
40+
41+
for config_path in fallback_paths:
42+
try:
43+
config_path.parent.mkdir(parents=True, exist_ok=True)
44+
test_file = config_path.parent / ".crewai_write_test"
45+
try:
46+
test_file.write_text("test")
47+
test_file.unlink() # Clean up test file
48+
logger.info(f"Using config path: {config_path}")
49+
return config_path
50+
except Exception: # noqa: S112
51+
continue
52+
53+
except Exception: # noqa: S112
54+
continue
55+
56+
return None
57+
58+
1759
# Settings that are related to the user's account
1860
USER_SETTINGS_KEYS = [
1961
"tool_repository_username",
@@ -93,16 +135,32 @@ class Settings(BaseModel):
93135
default=DEFAULT_CLI_SETTINGS["oauth2_domain"],
94136
)
95137

96-
def __init__(self, config_path: Path = DEFAULT_CONFIG_PATH, **data):
97-
"""Load Settings from config path"""
98-
config_path.parent.mkdir(parents=True, exist_ok=True)
138+
def __init__(self, config_path: Path | None = None, **data):
139+
"""Load Settings from config path with fallback support"""
140+
if config_path is None:
141+
config_path = get_writable_config_path()
142+
143+
# If config_path is None, we're in memory-only mode
144+
if config_path is None:
145+
merged_data = {**data}
146+
# Dummy path for memory-only mode
147+
super().__init__(config_path=Path("/dev/null"), **merged_data)
148+
return
149+
150+
try:
151+
config_path.parent.mkdir(parents=True, exist_ok=True)
152+
except Exception:
153+
merged_data = {**data}
154+
# Dummy path for memory-only mode
155+
super().__init__(config_path=Path("/dev/null"), **merged_data)
156+
return
99157

100158
file_data = {}
101159
if config_path.is_file():
102160
try:
103161
with config_path.open("r") as f:
104162
file_data = json.load(f)
105-
except json.JSONDecodeError:
163+
except Exception:
106164
file_data = {}
107165

108166
merged_data = {**file_data, **data}
@@ -122,15 +180,22 @@ def reset(self) -> None:
122180

123181
def dump(self) -> None:
124182
"""Save current settings to settings.json"""
125-
if self.config_path.is_file():
126-
with self.config_path.open("r") as f:
127-
existing_data = json.load(f)
128-
else:
129-
existing_data = {}
130-
131-
updated_data = {**existing_data, **self.model_dump(exclude_unset=True)}
132-
with self.config_path.open("w") as f:
133-
json.dump(updated_data, f, indent=4)
183+
if str(self.config_path) == "/dev/null":
184+
return
185+
186+
try:
187+
if self.config_path.is_file():
188+
with self.config_path.open("r") as f:
189+
existing_data = json.load(f)
190+
else:
191+
existing_data = {}
192+
193+
updated_data = {**existing_data, **self.model_dump(exclude_unset=True)}
194+
with self.config_path.open("w") as f:
195+
json.dump(updated_data, f, indent=4)
196+
197+
except Exception: # noqa: S110
198+
pass
134199

135200
def _reset_user_settings(self) -> None:
136201
"""Reset all user settings to default values"""

src/crewai/utilities/reasoning_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ def __call_with_function(self, prompt: str, prompt_type: str) -> Tuple[str, bool
259259
)
260260

261261
# Prepare a simple callable that just returns the tool arguments as JSON
262-
def _create_reasoning_plan(plan: str, ready: bool): # noqa: N802
262+
def _create_reasoning_plan(plan: str, ready: bool = True): # noqa: N802
263263
"""Return the reasoning plan result in JSON string form."""
264264
return json.dumps({"plan": plan, "ready": ready})
265265

0 commit comments

Comments
 (0)