MCPcopy
hub / github.com/lightningpixel/modly / _start

Method _start

electron/main/python-bridge.ts:36–102  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

34 }
35
36 private async _start(): Promise<void> {
37 if (this.process) {
38 await this.waitUntilReady()
39 return
40 }
41
42 const pythonExecutable = this.resolvePythonExecutable()
43 const apiDir = this.resolveApiDir()
44
45 console.log('[PythonBridge] Starting FastAPI at', apiDir)
46 console.log('[PythonBridge] Python executable:', pythonExecutable)
47
48 await this.killProcessOnPort()
49
50 this.process = spawn(pythonExecutable, ['-m', 'uvicorn', 'main:app', '--host', API_HOST, '--port', String(API_PORT)], {
51 cwd: apiDir,
52 env: {
53 ...cleanPythonEnv(),
54 PYTHONUNBUFFERED: '1',
55 // No PYTHONPATH needed - the venv's Python has its own isolated site-packages
56 MODELS_DIR: this.resolveModelsDir(),
57 WORKSPACE_DIR: this.resolveWorkspaceDir(),
58 EXTENSIONS_DIR: this.resolveExtensionsDir(),
59 SELECTED_MODEL_ID: process.env['SELECTED_MODEL_ID'] ?? '',
60 HUGGING_FACE_HUB_TOKEN: this.resolveHfToken(),
61 HF_TOKEN: this.resolveHfToken(),
62 },
63 // On Unix, put the bridge in its own process group so every subprocess
64 // it spawns (extension runners, etc.) inherits that group. On shutdown
65 // we SIGKILL the whole group (negative PID) to take them all out
66 // together — otherwise children get reparented to launchd and keep
67 // holding MPS-wired memory until the user kills them manually.
68 detached: process.platform !== 'win32',
69 })
70
71 this.process.stdout?.on('data', (data) => {
72 const msg = data.toString().trim()
73 console.log('[FastAPI]', msg)
74 logger.python(msg)
75 this.emitTqdmLog(msg)
76 })
77
78 this.process.stderr?.on('data', (data) => {
79 const msg = data.toString().trim()
80 console.error('[FastAPI]', msg)
81 logger.python(`[stderr] ${msg}`)
82 this.emitTqdmLog(msg)
83 })
84
85 this.process.on('exit', (code) => {
86 const wasReady = this.ready
87 console.log('[PythonBridge] Process exited with code', code)
88 this.ready = false
89 this.process = null
90 if (wasReady && !this.intentionalStop) {
91 const getWindow = this.getWindow
92 if (!getWindow) return
93 const win = getWindow()

Callers 1

startMethod · 0.95

Calls 12

waitUntilReadyMethod · 0.95
resolveApiDirMethod · 0.95
killProcessOnPortMethod · 0.95
resolveModelsDirMethod · 0.95
resolveWorkspaceDirMethod · 0.95
resolveExtensionsDirMethod · 0.95
resolveHfTokenMethod · 0.95
emitTqdmLogMethod · 0.95
cleanPythonEnvFunction · 0.90
onMethod · 0.80
sendMethod · 0.80

Tested by

no test coverage detected