Skip to content

Commit 8bc210f

Browse files
committed
Merge remote-tracking branch 'upstream/main'
2 parents 8b55b18 + e65052c commit 8bc210f

File tree

3 files changed

+83
-100
lines changed

3 files changed

+83
-100
lines changed

core/framework/storage/backend.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,13 @@ def save_run(self, run: Run) -> None:
8686
"""Save a run to storage."""
8787
# Save full run using Pydantic's model_dump_json
8888
run_path = self.base_path / "runs" / f"{run.id}.json"
89-
with open(run_path, "w") as f:
89+
with open(run_path, "w", encoding="utf-8") as f:
9090
f.write(run.model_dump_json(indent=2))
9191

9292
# Save summary
9393
summary = RunSummary.from_run(run)
9494
summary_path = self.base_path / "summaries" / f"{run.id}.json"
95-
with open(summary_path, "w") as f:
95+
with open(summary_path, "w", encoding="utf-8") as f:
9696
f.write(summary.model_dump_json(indent=2))
9797

9898
# Update indexes
@@ -106,7 +106,7 @@ def load_run(self, run_id: str) -> Run | None:
106106
run_path = self.base_path / "runs" / f"{run_id}.json"
107107
if not run_path.exists():
108108
return None
109-
with open(run_path) as f:
109+
with open(run_path, encoding="utf-8") as f:
110110
return Run.model_validate_json(f.read())
111111

112112
def load_summary(self, run_id: str) -> RunSummary | None:
@@ -119,7 +119,7 @@ def load_summary(self, run_id: str) -> RunSummary | None:
119119
return RunSummary.from_run(run)
120120
return None
121121

122-
with open(summary_path) as f:
122+
with open(summary_path, encoding="utf-8") as f:
123123
return RunSummary.model_validate_json(f.read())
124124

125125
def delete_run(self, run_id: str) -> bool:
@@ -178,7 +178,7 @@ def _get_index(self, index_type: str, key: str) -> list[str]:
178178
index_path = self.base_path / "indexes" / index_type / f"{key}.json"
179179
if not index_path.exists():
180180
return []
181-
with open(index_path) as f:
181+
with open(index_path, encoding="utf-8") as f:
182182
return json.load(f)
183183

184184
def _add_to_index(self, index_type: str, key: str, value: str) -> None:
@@ -188,7 +188,7 @@ def _add_to_index(self, index_type: str, key: str, value: str) -> None:
188188
values = self._get_index(index_type, key) # Already validated in _get_index
189189
if value not in values:
190190
values.append(value)
191-
with open(index_path, "w") as f:
191+
with open(index_path, "w", encoding="utf-8") as f:
192192
json.dump(values, f)
193193

194194
def _remove_from_index(self, index_type: str, key: str, value: str) -> None:
@@ -198,7 +198,7 @@ def _remove_from_index(self, index_type: str, key: str, value: str) -> None:
198198
values = self._get_index(index_type, key) # Already validated in _get_index
199199
if value in values:
200200
values.remove(value)
201-
with open(index_path, "w") as f:
201+
with open(index_path, "w", encoding="utf-8") as f:
202202
json.dump(values, f)
203203

204204
# === UTILITY ===

core/framework/testing/test_storage.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def save_test(self, test: Test) -> None:
6565

6666
# Save full test
6767
test_path = goal_dir / f"{test.id}.json"
68-
with open(test_path, "w") as f:
68+
with open(test_path, "w", encoding="utf-8") as f:
6969
f.write(test.model_dump_json(indent=2))
7070

7171
# Update indexes
@@ -79,7 +79,7 @@ def load_test(self, goal_id: str, test_id: str) -> Test | None:
7979
test_path = self.base_path / "tests" / goal_id / f"{test_id}.json"
8080
if not test_path.exists():
8181
return None
82-
with open(test_path) as f:
82+
with open(test_path, encoding="utf-8") as f:
8383
return Test.model_validate_json(f.read())
8484

8585
def delete_test(self, goal_id: str, test_id: str) -> bool:
@@ -175,20 +175,20 @@ def save_result(self, test_id: str, result: TestResult) -> None:
175175
# Save with timestamp
176176
timestamp = result.timestamp.strftime("%Y%m%d_%H%M%S")
177177
result_path = results_dir / f"{timestamp}.json"
178-
with open(result_path, "w") as f:
178+
with open(result_path, "w", encoding="utf-8") as f:
179179
f.write(result.model_dump_json(indent=2))
180180

181181
# Update latest
182182
latest_path = results_dir / "latest.json"
183-
with open(latest_path, "w") as f:
183+
with open(latest_path, "w", encoding="utf-8") as f:
184184
f.write(result.model_dump_json(indent=2))
185185

186186
def get_latest_result(self, test_id: str) -> TestResult | None:
187187
"""Get the most recent result for a test."""
188188
latest_path = self.base_path / "results" / test_id / "latest.json"
189189
if not latest_path.exists():
190190
return None
191-
with open(latest_path) as f:
191+
with open(latest_path, encoding="utf-8") as f:
192192
return TestResult.model_validate_json(f.read())
193193

194194
def get_result_history(self, test_id: str, limit: int = 10) -> list[TestResult]:
@@ -204,7 +204,7 @@ def get_result_history(self, test_id: str, limit: int = 10) -> list[TestResult]:
204204

205205
results = []
206206
for f in result_files:
207-
with open(f) as file:
207+
with open(f, encoding="utf-8") as file:
208208
results.append(TestResult.model_validate_json(file.read()))
209209

210210
return results
@@ -216,7 +216,7 @@ def _get_index(self, index_type: str, key: str) -> list[str]:
216216
index_path = self.base_path / "indexes" / index_type / f"{key}.json"
217217
if not index_path.exists():
218218
return []
219-
with open(index_path) as f:
219+
with open(index_path, encoding="utf-8") as f:
220220
return json.load(f)
221221

222222
def _add_to_index(self, index_type: str, key: str, value: str) -> None:
@@ -225,7 +225,7 @@ def _add_to_index(self, index_type: str, key: str, value: str) -> None:
225225
values = self._get_index(index_type, key)
226226
if value not in values:
227227
values.append(value)
228-
with open(index_path, "w") as f:
228+
with open(index_path, "w", encoding="utf-8") as f:
229229
json.dump(values, f)
230230

231231
def _remove_from_index(self, index_type: str, key: str, value: str) -> None:
@@ -234,7 +234,7 @@ def _remove_from_index(self, index_type: str, key: str, value: str) -> None:
234234
values = self._get_index(index_type, key)
235235
if value in values:
236236
values.remove(value)
237-
with open(index_path, "w") as f:
237+
with open(index_path, "w", encoding="utf-8") as f:
238238
json.dump(values, f)
239239

240240
# === UTILITY ===

scripts/setup-python.sh

Lines changed: 67 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -19,100 +19,82 @@ NC='\033[0m' # No Color
1919
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
2020
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
2121

22+
# Python Version
23+
REQUIRED_PYTHON_VERSION="3.11"
24+
25+
# Python version split into Major and Minor
26+
IFS='.' read -r PYTHON_MAJOR_VERSION PYTHON_MINOR_VERSION <<< "$REQUIRED_PYTHON_VERSION"
27+
28+
# Available python interpreter (follows sequence)
29+
POSSIBLE_PYTHONS=("python3" "python" "py")
30+
31+
# Default python interpreter (initialized)
32+
PYTHON_CMD=()
33+
34+
2235
echo ""
2336
echo "=================================================="
2437
echo " Aden Agent Framework - Python Setup"
2538
echo "=================================================="
2639
echo ""
2740

28-
# Check for Python, honoring $PYTHON even if it's not on PATH
29-
if [ -n "$PYTHON" ]; then
30-
if [ ! -x "$PYTHON" ] && ! command -v "$PYTHON" &> /dev/null; then
31-
echo -e "${RED}Error: PYTHON is set to '$PYTHON' but it was not found or not executable.${NC}"
32-
echo "Example: PYTHON=/opt/python3.12/bin/python3.12 ./scripts/setup-python.sh"
33-
exit 1
34-
fi
35-
elif ! command -v python &> /dev/null \
36-
&& ! command -v python3 &> /dev/null \
37-
&& ! command -v python3.11 &> /dev/null \
38-
&& ! command -v python3.12 &> /dev/null; then
39-
echo -e "${RED}Error: Python is not installed.${NC}"
40-
echo "Please install Python 3.11+ (recommended 3.12) from https://python.org"
41-
exit 1
42-
fi
43-
44-
# Choose Python interpreter
45-
# Priority:
46-
# 1) $PYTHON env var override (e.g., PYTHON=python3.11)
47-
# 2) python3.12 if available
48-
# 3) python3.11 if available
49-
# 4) python3
50-
# 5) python
51-
PYTHON_CMD="${PYTHON:-}"
52-
53-
if [ -n "$PYTHON_CMD" ]; then
54-
if [ -x "$PYTHON_CMD" ]; then
55-
: # absolute / explicit path provided and executable
56-
elif command -v "$PYTHON_CMD" &> /dev/null; then
57-
: # found on PATH
58-
else
59-
echo -e "${RED}Error: PYTHON is set to '$PYTHON_CMD' but it was not found in PATH or as an absolute path.${NC}"
60-
echo "Example: PYTHON=/opt/python3.12/bin/python3.12 ./scripts/setup-python.sh"
61-
exit 1
41+
# Available Python interpreter
42+
for cmd in "${POSSIBLE_PYTHONS[@]}"; do
43+
# Check for python interpreter
44+
if command -v "$cmd" >/dev/null 2>&1; then
45+
46+
# Specific check for Windows 'py' launcher
47+
if [ "$cmd" = "py" ]; then
48+
CURRENT_CMD=(py -3)
49+
else
50+
CURRENT_CMD=("$cmd")
51+
fi
52+
53+
# Check Python version
54+
if "${CURRENT_CMD[@]}" -c "import sys; sys.exit(0 if sys.version_info >= ($PYTHON_MAJOR_VERSION, $PYTHON_MINOR_VERSION) else 1)" >/dev/null 2>&1; then
55+
echo -e "${GREEN}${NC} interpreter detected: ${CURRENT_CMD[@]}"
56+
# Check for pip
57+
if "${CURRENT_CMD[@]}" -m pip --version >/dev/null 2>&1; then
58+
PYTHON_CMD=("${CURRENT_CMD[@]}")
59+
echo -e "${GREEN}${NC} pip detected"
60+
echo ""
61+
break
62+
else
63+
echo -e "${RED}${NC} pip not found"
64+
echo ""
65+
fi
66+
else
67+
echo -e "${RED}${NC} ${CURRENT_CMD[@]} not found"
68+
echo ""
69+
fi
6270
fi
63-
elif command -v python3.12 &> /dev/null; then
64-
PYTHON_CMD="python3.12"
65-
elif command -v python3.11 &> /dev/null; then
66-
PYTHON_CMD="python3.11"
67-
elif command -v python3 &> /dev/null; then
68-
PYTHON_CMD="python3"
69-
else
70-
PYTHON_CMD="python"
71-
fi
71+
done
7272

73-
# Check Python version
74-
PYTHON_VERSION=$($PYTHON_CMD -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
75-
PYTHON_MAJOR=$($PYTHON_CMD -c 'import sys; print(sys.version_info.major)')
76-
PYTHON_MINOR=$($PYTHON_CMD -c 'import sys; print(sys.version_info.minor)')
77-
78-
echo -e "${BLUE}Detected Python:${NC} $PYTHON_VERSION (binary: ${PYTHON_CMD})"
79-
80-
# Require 3.11+
81-
if [ "$PYTHON_MAJOR" -lt 3 ] || ([ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -lt 11 ]); then
82-
echo -e "${RED}Error: Python 3.11+ is required (found $PYTHON_VERSION via '$PYTHON_CMD')${NC}"
73+
# Display error message if python not found
74+
if [ "${#PYTHON_CMD[@]}" -eq 0 ]; then
75+
echo -e "${RED}Error:${NC} No suitable Python interpreter found with pip installed."
8376
echo ""
84-
echo "Fix options (Linux/macOS/WSL):"
85-
echo " • Ubuntu/Debian/Pop!_OS/WSL:"
86-
echo " sudo apt update && sudo apt install -y python3.11 python3.11-venv python3.11-dev"
87-
echo " • Fedora:"
88-
echo " sudo dnf install -y python3.11 python3.11-devel"
89-
echo " • Arch/Manjaro:"
90-
echo " sudo pacman -S python"
91-
echo " • macOS (Homebrew):"
92-
echo " brew install python@3.11"
77+
echo "Requirements:"
78+
echo " • Python $PYTHON_MAJOR_VERSION.$PYTHON_MINOR_VERSION+"
79+
echo " • pip installed"
9380
echo ""
94-
echo "Then re-run with an explicit interpreter if needed:"
95-
echo " PYTHON=python3.11 ./scripts/setup-python.sh"
81+
echo "Tried the following commands:"
82+
echo " ${POSSIBLE_PYTHONS[*]}"
9683
echo ""
84+
echo "Please install Python from:"
85+
echo " https://www.python.org/downloads/"
9786
exit 1
9887
fi
9988

89+
# Display Python version
90+
PYTHON_VERSION=$("${PYTHON_CMD[@]}" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
91+
echo -e "${BLUE}Detected Python:${NC} $PYTHON_VERSION"
10092
echo -e "${GREEN}${NC} Python version check passed"
10193
echo ""
10294

103-
# Check for pip
104-
if ! $PYTHON_CMD -m pip --version &> /dev/null; then
105-
echo -e "${RED}Error: pip is not installed${NC}"
106-
echo "Please install pip for Python $PYTHON_VERSION"
107-
exit 1
108-
fi
109-
110-
echo -e "${GREEN}${NC} pip detected"
111-
echo ""
112-
11395
# Upgrade pip, setuptools, and wheel
11496
echo "Upgrading pip, setuptools, and wheel..."
115-
if ! $PYTHON_CMD -m pip install --upgrade pip setuptools wheel; then
97+
if ! "${PYTHON_CMD[@]}" -m pip install --upgrade pip setuptools wheel; then
11698
echo "Error: Failed to upgrade pip. Please check your python/venv configuration."
11799
exit 1
118100
fi
@@ -128,7 +110,8 @@ cd "$PROJECT_ROOT/core"
128110

129111
if [ -f "pyproject.toml" ]; then
130112
echo "Installing framework from core/ (editable mode)..."
131-
$PYTHON_CMD -m pip install -e . > /dev/null 2>&1
113+
"${PYTHON_CMD[@]}" -m pip install -e . > /dev/null 2>&1
114+
132115
if [ $? -eq 0 ]; then
133116
echo -e "${GREEN}${NC} Framework package installed"
134117
else
@@ -148,7 +131,7 @@ cd "$PROJECT_ROOT/tools"
148131

149132
if [ -f "pyproject.toml" ]; then
150133
echo "Installing aden_tools from tools/ (editable mode)..."
151-
$PYTHON_CMD -m pip install -e . > /dev/null 2>&1
134+
"${PYTHON_CMD[@]}" -m pip install -e . > /dev/null 2>&1
152135
if [ $? -eq 0 ]; then
153136
echo -e "${GREEN}${NC} Tools package installed"
154137
else
@@ -168,17 +151,17 @@ echo "=================================================="
168151
echo ""
169152

170153
# Check openai version
171-
OPENAI_VERSION=$($PYTHON_CMD -c "import openai; print(openai.__version__)" 2>/dev/null || echo "not_installed")
154+
OPENAI_VERSION=$("${PYTHON_CMD[@]}" -c "import openai; print(openai.__version__)" 2>/dev/null || echo "not_installed")
172155

173156
if [ "$OPENAI_VERSION" = "not_installed" ]; then
174157
echo "Installing openai package..."
175-
$PYTHON_CMD -m pip install "openai>=1.0.0" > /dev/null 2>&1
158+
"${PYTHON_CMD[@]}" -m pip install "openai>=1.0.0" > /dev/null 2>&1
176159
echo -e "${GREEN}${NC} openai package installed"
177160
elif [[ "$OPENAI_VERSION" =~ ^0\. ]]; then
178161
echo -e "${YELLOW}Found old openai version: $OPENAI_VERSION${NC}"
179162
echo "Upgrading to openai 1.x+ for litellm compatibility..."
180-
$PYTHON_CMD -m pip install --upgrade "openai>=1.0.0" > /dev/null 2>&1
181-
OPENAI_VERSION=$($PYTHON_CMD -c "import openai; print(openai.__version__)" 2>/dev/null)
163+
"${PYTHON_CMD[@]}" -m pip install --upgrade "openai>=1.0.0" > /dev/null 2>&1
164+
OPENAI_VERSION=$("${PYTHON_CMD[@]}" -c "import openai; print(openai.__version__)" 2>/dev/null)
182165
echo -e "${GREEN}${NC} openai upgraded to $OPENAI_VERSION"
183166
else
184167
echo -e "${GREEN}${NC} openai $OPENAI_VERSION is compatible"
@@ -194,23 +177,23 @@ echo ""
194177
cd "$PROJECT_ROOT"
195178

196179
# Test framework import
197-
if $PYTHON_CMD -c "import framework; print('framework OK')" > /dev/null 2>&1; then
180+
if "${PYTHON_CMD[@]}" -c "import framework; print('framework OK')" > /dev/null 2>&1; then
198181
echo -e "${GREEN}${NC} framework package imports successfully"
199182
else
200183
echo -e "${RED}${NC} framework package import failed"
201184
echo -e "${YELLOW} Note: This may be OK if you don't need the framework${NC}"
202185
fi
203186

204187
# Test aden_tools import
205-
if $PYTHON_CMD -c "import aden_tools; print('aden_tools OK')" > /dev/null 2>&1; then
188+
if "${PYTHON_CMD[@]}" -c "import aden_tools; print('aden_tools OK')" > /dev/null 2>&1; then
206189
echo -e "${GREEN}${NC} aden_tools package imports successfully"
207190
else
208191
echo -e "${RED}${NC} aden_tools package import failed"
209192
exit 1
210193
fi
211194

212195
# Test litellm + openai compatibility
213-
if $PYTHON_CMD -c "import litellm; print('litellm OK')" > /dev/null 2>&1; then
196+
if "${PYTHON_CMD[@]}" -c "import litellm; print('litellm OK')" > /dev/null 2>&1; then
214197
echo -e "${GREEN}${NC} litellm package imports successfully"
215198
else
216199
echo -e "${YELLOW}${NC} litellm import had issues (may be OK if not using LLM features)"

0 commit comments

Comments
 (0)