From ddf112034d9bbee9499d99d02506d9c795c7318a Mon Sep 17 00:00:00 2001 From: "tao.chen" <93983997+taochen-ct@users.noreply.github.com> Date: Tue, 4 Aug 2026 11:29:33 +0800 Subject: [PATCH] update: jupyter api payload, wire os.environ --- backend/src/backend/runtime_client.py | 4 ++-- common/src/common/utils.py | 8 ++++++++ runtime/src/runtime/process.py | 20 ++++++++++++-------- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/backend/src/backend/runtime_client.py b/backend/src/backend/runtime_client.py index 7a13a6d..8f022cb 100644 --- a/backend/src/backend/runtime_client.py +++ b/backend/src/backend/runtime_client.py @@ -162,7 +162,7 @@ class RuntimeClient: logger.debug(ws) body = { "type": "notebook", - "name": name, + "path": name, "content": { "cells": cells if cells is not None else [], "metadata": {}, @@ -199,7 +199,7 @@ class RuntimeClient: ws = await self._ensure_workspace(workspace_id) body = { "type": "file", - "name": name, + "path": name, "content": content, "format": "text", } diff --git a/common/src/common/utils.py b/common/src/common/utils.py index 4631119..40725ec 100644 --- a/common/src/common/utils.py +++ b/common/src/common/utils.py @@ -12,6 +12,7 @@ specific concerns: from __future__ import annotations +import os import socket import subprocess import time @@ -30,6 +31,7 @@ def start_process( cmd: list[str], workspace_path: Path, log_dir: str | Path = "/tmp/process_logs", + env: dict[str, str] | None = None, ) -> tuple[subprocess.Popen, Path]: """Launch ``cmd`` as a subprocess and return ``(process, log_file)``. @@ -44,6 +46,11 @@ def start_process( start_time = time.strftime("%Y%m%d_%H%M%S") temp_log = log_dir_path / f"process_start_{start_time}.log" + # 构建合并后的环境变量 + full_env = os.environ.copy() + if env: + full_env.update(env) + with open(temp_log, "a", buffering=1) as log_file: process = subprocess.Popen( cmd, @@ -51,6 +58,7 @@ def start_process( stdout=log_file, stderr=subprocess.STDOUT, start_new_session=True, + env=full_env, ) final_log = log_dir_path / f"process_{process.pid}_{start_time}.log" diff --git a/runtime/src/runtime/process.py b/runtime/src/runtime/process.py index ccf40d9..5e73f34 100644 --- a/runtime/src/runtime/process.py +++ b/runtime/src/runtime/process.py @@ -195,7 +195,8 @@ async def start_workspace(ws_id: str) -> dict: base_path = f"/jupyter/{ws_id}/" cmd = [ - "jupyter", "notebook", + "jupyter", + "notebook", f"--port={port}", "--ip=0.0.0.0", "--no-browser", @@ -212,12 +213,14 @@ async def start_workspace(ws_id: str) -> dict: ] try: - process, log_file = start_process(cmd, workspace_path.as_posix()) + process, log_file = start_process( + cmd, + workspace_path.as_posix(), + env={"PATH": f"/app/.venv/bin:{os.environ.get('PATH', '')}"}, + ) except Exception as e: logger.error(f"Failed to start Jupyter for {ws_id}: {e}") - raise HTTPException( - status_code=500, detail=f"Failed to start Jupyter: {e}" - ) + raise HTTPException(status_code=500, detail=f"Failed to start Jupyter: {e}") full_url = f"{PUBLIC_BASE_URL}:{port}{base_path}?token={token}" meta_path = _meta_path(ws_id) @@ -341,8 +344,7 @@ async def get_workspace(ws_id: str) -> dict: raise HTTPException( status_code=404, detail=( - f"Jupyter process for workspace '{ws_id}' " - "has terminated unexpectedly." + f"Jupyter process for workspace '{ws_id}' " "has terminated unexpectedly." ), ) @@ -416,7 +418,9 @@ def reconcile_processes() -> dict[str, int]: except PermissionError: alive = True # someone else's process, leave alone if not alive: - logger.info(f"reconcile: dropping stale sidecar for {entry} (pid {pid} dead)") + logger.info( + f"reconcile: dropping stale sidecar for {entry} (pid {pid} dead)" + ) _delete_meta(entry) counters["removed_meta"] += 1 return counters