mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-07-15 08:56:07 +00:00
chore(agent-runner): align split runtime files with base
This commit is contained in:
@@ -204,14 +204,14 @@ def wrap_python_command_with_env(command: str, *, mount_path: str = '/workspace'
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$_LB_NEEDS_BOOTSTRAP" -eq 1 ]; then
|
if [ "$_LB_NEEDS_BOOTSTRAP" -eq 1 ]; then
|
||||||
if [ -d "$_LB_LOCK_DIR" ] && [ ! -f "$_LB_LOCK_DIR/pid" ]; then
|
|
||||||
echo "Clearing stale Python environment lock without owner: $_LB_LOCK_DIR" >&2
|
|
||||||
rm -rf "$_LB_LOCK_DIR" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
_LB_LOCK_WAIT=0
|
_LB_LOCK_WAIT=0
|
||||||
while ! mkdir "$_LB_LOCK_DIR" 2>/dev/null; do
|
while ! mkdir "$_LB_LOCK_DIR" 2>/dev/null; do
|
||||||
if [ "$_LB_LOCK_WAIT" -ge 120 ]; then
|
if [ "$_LB_LOCK_WAIT" -ge 120 ]; then
|
||||||
|
_LB_LOCK_OWNER="$(cat "$_LB_LOCK_DIR/pid" 2>/dev/null || true)"
|
||||||
|
if [ -n "$_LB_LOCK_OWNER" ] && kill -0 "$_LB_LOCK_OWNER" 2>/dev/null; then
|
||||||
|
echo "Timed out waiting for active Python environment lock: $_LB_LOCK_DIR" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
echo "Timed out waiting for Python environment lock, clearing stale lock: $_LB_LOCK_DIR" >&2
|
echo "Timed out waiting for Python environment lock, clearing stale lock: $_LB_LOCK_DIR" >&2
|
||||||
rm -rf "$_LB_LOCK_DIR" 2>/dev/null || true
|
rm -rf "$_LB_LOCK_DIR" 2>/dev/null || true
|
||||||
if mkdir "$_LB_LOCK_DIR" 2>/dev/null; then
|
if mkdir "$_LB_LOCK_DIR" 2>/dev/null; then
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ class BoxStdioSessionRuntime:
|
|||||||
# to delete them, so refresh source files in place and preserve runtime
|
# to delete them, so refresh source files in place and preserve runtime
|
||||||
# directories instead of rmtree'ing the whole staging root.
|
# directories instead of rmtree'ing the whole staging root.
|
||||||
with _workspace_copy_lock(process_host_root):
|
with _workspace_copy_lock(process_host_root):
|
||||||
preserved_names = {'.venv', 'venv', 'env', '.env', '.cache', '.tmp', '.langbot'}
|
preserved_names = {'.venv', 'venv', 'env', '.cache', '.tmp', '.langbot'}
|
||||||
os.makedirs(process_host_workspace, exist_ok=True)
|
os.makedirs(process_host_workspace, exist_ok=True)
|
||||||
for name in os.listdir(process_host_workspace):
|
for name in os.listdir(process_host_workspace):
|
||||||
if name in preserved_names:
|
if name in preserved_names:
|
||||||
@@ -288,6 +288,7 @@ class BoxStdioSessionRuntime:
|
|||||||
try:
|
try:
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
|
# The entry may disappear between listdir and unlink if cleanup races us.
|
||||||
pass
|
pass
|
||||||
shutil.copytree(
|
shutil.copytree(
|
||||||
source_path,
|
source_path,
|
||||||
@@ -303,7 +304,6 @@ class BoxStdioSessionRuntime:
|
|||||||
'.venv',
|
'.venv',
|
||||||
'venv',
|
'venv',
|
||||||
'env',
|
'env',
|
||||||
'.env',
|
|
||||||
'.cache',
|
'.cache',
|
||||||
'.tmp',
|
'.tmp',
|
||||||
'.langbot',
|
'.langbot',
|
||||||
@@ -401,18 +401,12 @@ class BoxStdioSessionRuntime:
|
|||||||
workspace_root = workspace_path.rstrip('/') or '/workspace'
|
workspace_root = workspace_path.rstrip('/') or '/workspace'
|
||||||
venv_dir = f'{workspace_root}/.venv'
|
venv_dir = f'{workspace_root}/.venv'
|
||||||
venv_bin = f'{venv_dir}/bin'
|
venv_bin = f'{venv_dir}/bin'
|
||||||
command = ' '.join(
|
command = ' '.join([shlex.quote(payload['command']), *[shlex.quote(arg) for arg in payload.get('args', [])]])
|
||||||
[shlex.quote(payload['command']), *[shlex.quote(arg) for arg in payload.get('args', [])]]
|
|
||||||
)
|
|
||||||
wrapped = dict(payload)
|
wrapped = dict(payload)
|
||||||
wrapped['command'] = 'sh'
|
wrapped['command'] = 'sh'
|
||||||
wrapped['args'] = [
|
wrapped['args'] = [
|
||||||
'-lc',
|
'-lc',
|
||||||
(
|
(f'export VIRTUAL_ENV={shlex.quote(venv_dir)}; export PATH={shlex.quote(venv_bin)}:$PATH; exec {command}'),
|
||||||
f'export VIRTUAL_ENV={shlex.quote(venv_dir)}; '
|
|
||||||
f'export PATH={shlex.quote(venv_bin)}:$PATH; '
|
|
||||||
f'exec {command}'
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
return wrapped
|
return wrapped
|
||||||
|
|
||||||
|
|||||||
@@ -56,10 +56,7 @@ def test_wrap_python_command_with_env_contains_bootstrap_and_command():
|
|||||||
|
|
||||||
assert '_LB_SYSTEM_PYTHON="$(command -v python3 || command -v python || true)"' in command
|
assert '_LB_SYSTEM_PYTHON="$(command -v python3 || command -v python || true)"' in command
|
||||||
assert '"$_LB_SYSTEM_PYTHON" -m venv "$_LB_VENV_DIR"' in command
|
assert '"$_LB_SYSTEM_PYTHON" -m venv "$_LB_VENV_DIR"' in command
|
||||||
assert 'Clearing stale Python environment lock without owner: $_LB_LOCK_DIR' in command
|
assert 'kill -0 "$_LB_LOCK_OWNER"' in command
|
||||||
assert 'clearing stale lock: $_LB_LOCK_DIR' in command
|
|
||||||
assert 'printf \'%s\\n\' "$$" > "$_LB_LOCK_DIR/pid"' in command
|
|
||||||
assert 'rm -rf "$_LB_LOCK_DIR"' in command
|
|
||||||
assert 'export VIRTUAL_ENV="$_LB_VENV_DIR"' in command
|
assert 'export VIRTUAL_ENV="$_LB_VENV_DIR"' in command
|
||||||
assert command.rstrip().endswith('python script.py')
|
assert command.rstrip().endswith('python script.py')
|
||||||
|
|
||||||
|
|||||||
@@ -519,6 +519,7 @@ class TestPythonWorkspacePreparation:
|
|||||||
source.mkdir()
|
source.mkdir()
|
||||||
(source / 'server.py').write_text('print("new")\n', encoding='utf-8')
|
(source / 'server.py').write_text('print("new")\n', encoding='utf-8')
|
||||||
(source / 'requirements.txt').write_text('mcp==1.26.0\n', encoding='utf-8')
|
(source / 'requirements.txt').write_text('mcp==1.26.0\n', encoding='utf-8')
|
||||||
|
(source / '.env').write_text('TOKEN=new\n', encoding='utf-8')
|
||||||
|
|
||||||
process_root = tmp_path / 'shared' / '.mcp' / 'u1'
|
process_root = tmp_path / 'shared' / '.mcp' / 'u1'
|
||||||
workspace = process_root / 'workspace'
|
workspace = process_root / 'workspace'
|
||||||
@@ -526,6 +527,7 @@ class TestPythonWorkspacePreparation:
|
|||||||
(workspace / '.venv' / 'bin' / 'python').write_text('', encoding='utf-8')
|
(workspace / '.venv' / 'bin' / 'python').write_text('', encoding='utf-8')
|
||||||
(workspace / '.langbot').mkdir()
|
(workspace / '.langbot').mkdir()
|
||||||
(workspace / '.langbot' / 'python-env.lock').mkdir()
|
(workspace / '.langbot' / 'python-env.lock').mkdir()
|
||||||
|
(workspace / '.env').write_text('TOKEN=old\n', encoding='utf-8')
|
||||||
(workspace / 'server.py').write_text('print("old")\n', encoding='utf-8')
|
(workspace / 'server.py').write_text('print("old")\n', encoding='utf-8')
|
||||||
(workspace / 'removed.py').write_text('stale\n', encoding='utf-8')
|
(workspace / 'removed.py').write_text('stale\n', encoding='utf-8')
|
||||||
(workspace / 'removed_dir').mkdir()
|
(workspace / 'removed_dir').mkdir()
|
||||||
@@ -535,6 +537,7 @@ class TestPythonWorkspacePreparation:
|
|||||||
|
|
||||||
assert (workspace / 'server.py').read_text(encoding='utf-8') == 'print("new")\n'
|
assert (workspace / 'server.py').read_text(encoding='utf-8') == 'print("new")\n'
|
||||||
assert (workspace / 'requirements.txt').read_text(encoding='utf-8') == 'mcp==1.26.0\n'
|
assert (workspace / 'requirements.txt').read_text(encoding='utf-8') == 'mcp==1.26.0\n'
|
||||||
|
assert (workspace / '.env').read_text(encoding='utf-8') == 'TOKEN=new\n'
|
||||||
assert not (workspace / 'removed.py').exists()
|
assert not (workspace / 'removed.py').exists()
|
||||||
assert not (workspace / 'removed_dir').exists()
|
assert not (workspace / 'removed_dir').exists()
|
||||||
assert (workspace / '.venv' / 'bin' / 'python').exists()
|
assert (workspace / '.venv' / 'bin' / 'python').exists()
|
||||||
|
|||||||
Reference in New Issue
Block a user