Skip to content

Commit 22ef92f

Browse files
committed
copy the bundled configs from _MEIPASS to the working directory
1 parent c5780cf commit 22ef92f

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

agent_core/core/impl/mcp/client.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,28 @@
77
"""
88

99
import asyncio
10+
import sys
1011
from pathlib import Path
1112
from typing import Any, Dict, List, Optional
1213

1314
from agent_core.utils.logger import logger
1415
from agent_core.core.impl.mcp.config import MCPConfig, MCPServerConfig
1516
from agent_core.core.impl.mcp.server import MCPServerConnection, MCPTool
1617

17-
# Default config path
18-
DEFAULT_CONFIG_PATH = Path("app/config/mcp_config.json")
18+
19+
def _default_config_path() -> Path:
20+
"""Resolve MCP config path relative to the correct base directory."""
21+
rel = Path("app") / "config" / "mcp_config.json"
22+
if getattr(sys, 'frozen', False):
23+
# Prefer CWD (bootstrapped, user-editable) over _MEIPASS (bundled)
24+
cwd_path = Path.cwd() / rel
25+
if cwd_path.exists():
26+
return cwd_path
27+
return Path(sys._MEIPASS) / rel
28+
return Path(__file__).resolve().parent.parent.parent.parent.parent / rel
29+
30+
31+
DEFAULT_CONFIG_PATH = _default_config_path()
1932

2033

2134
class MCPClient:

app/tui/mcp_settings.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
from pathlib import Path
66
from typing import Dict, List, Optional, Any
77

8+
from app.config import APP_CONFIG_PATH
89
from app.logger import logger
910
from app.mcp import MCPConfig, MCPServerConfig
1011

1112
# Default MCP config path
12-
MCP_CONFIG_PATH = Path("app/config/mcp_config.json")
13+
MCP_CONFIG_PATH = APP_CONFIG_PATH / "mcp_config.json"
1314

1415

1516
def load_mcp_config() -> MCPConfig:

run.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,53 @@
4444
else:
4545
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
4646

47+
48+
def _bootstrap_frozen():
49+
"""Copy bundled config/data from _MEIPASS to CWD on first run.
50+
51+
PyInstaller extracts bundled files into a temp directory (sys._MEIPASS)
52+
which is read-only and deleted on exit. The app expects mutable config
53+
and data directories under CWD so they persist between runs.
54+
"""
55+
if not getattr(sys, 'frozen', False):
56+
return
57+
58+
import shutil as _shutil
59+
60+
meipass = sys._MEIPASS
61+
cwd = os.getcwd()
62+
63+
# Directories to bootstrap (source relative to _MEIPASS)
64+
dirs_to_copy = [
65+
"app/config",
66+
"app/data",
67+
"agents",
68+
"assets",
69+
]
70+
# Individual files to bootstrap
71+
files_to_copy = [
72+
"config.json",
73+
".env.example",
74+
]
75+
76+
for rel_dir in dirs_to_copy:
77+
src = os.path.join(meipass, rel_dir)
78+
dst = os.path.join(cwd, rel_dir)
79+
if os.path.isdir(src) and not os.path.isdir(dst):
80+
print(f" Bootstrapping {rel_dir}/...")
81+
os.makedirs(os.path.dirname(dst), exist_ok=True)
82+
_shutil.copytree(src, dst)
83+
84+
for rel_file in files_to_copy:
85+
src = os.path.join(meipass, rel_file)
86+
dst = os.path.join(cwd, rel_file)
87+
if os.path.isfile(src) and not os.path.isfile(dst):
88+
print(f" Bootstrapping {rel_file}...")
89+
_shutil.copy2(src, dst)
90+
91+
92+
_bootstrap_frozen()
93+
4794
# --- Configuration ---
4895
CONFIG_FILE = os.path.join(BASE_DIR, "config.json")
4996
MAIN_APP_SCRIPT = os.path.join(BASE_DIR, "main.py")

0 commit comments

Comments
 (0)