11import asyncio
22import json
33import os
4+ import socket
45import threading
6+ import time
57import traceback
68from datetime import datetime
79from typing import Any , Dict
@@ -35,6 +37,8 @@ async def input(self, chunk):
3537 When it hits an "end" flag, calls interpreter.respond().
3638 """
3739
40+ print ("Received:" , chunk )
41+
3842 if "start" in chunk :
3943 # If the user is starting something, the interpreter should stop.
4044 if self .respond_thread is not None and self .respond_thread .is_alive ():
@@ -79,13 +83,17 @@ def respond(self, run_code=None):
7983 if run_code == None :
8084 run_code = self .auto_run
8185
82- for chunk in self ._respond_and_store ():
83- # To preserve confirmation chunks, we add this to the bottom instead
84- # if chunk["type"] == "confirmation":
85- # if run_code:
86- # continue
87- # else:
88- # break
86+ for chunk_og in self ._respond_and_store ():
87+ chunk = (
88+ chunk_og .copy ()
89+ ) # This fixes weird double token chunks. Probably a deeper problem?
90+
91+ if chunk ["type" ] == "confirmation" :
92+ if run_code :
93+ run_code = False
94+ continue
95+ else :
96+ break
8997
9098 if self .stop_event .is_set ():
9199 return
@@ -102,20 +110,20 @@ def respond(self, run_code=None):
102110
103111 self .output_queue .sync_q .put (chunk )
104112
105- if chunk ["type" ] == "confirmation" :
106- if not run_code :
107- break
108-
109113 self .output_queue .sync_q .put (
110114 {"role" : "server" , "type" : "status" , "content" : "complete" }
111115 )
112116 except Exception as e :
117+ error = traceback .format_exc () + "\n " + str (e )
113118 error_message = {
114119 "role" : "server" ,
115120 "type" : "error" ,
116121 "content" : traceback .format_exc () + "\n " + str (e ),
117122 }
118123 self .output_queue .sync_q .put (error_message )
124+ print ("\n \n --- SENT ERROR: ---\n \n " )
125+ print (error )
126+ print ("\n \n --- (ERROR ABOVE WAS SENT) ---\n \n " )
119127
120128 def accumulate (self , chunk ):
121129 """
@@ -163,52 +171,61 @@ async def receive_input():
163171 if data .get ("type" ) == "websocket.receive" and "text" in data :
164172 data = json .loads (data ["text" ])
165173 await async_interpreter .input (data )
166- elif (
167- data .get ("type" ) == "websocket.disconnect"
168- and data .get ("code" ) == 1000
169- ):
174+ elif data .get ("type" ) == "websocket.disconnect" :
170175 print ("Disconnecting." )
171176 return
172177 else :
173178 print ("Invalid data:" , data )
174179 continue
175180
176181 except Exception as e :
182+ error = traceback .format_exc () + "\n " + str (e )
177183 error_message = {
178184 "role" : "server" ,
179185 "type" : "error" ,
180186 "content" : traceback .format_exc () + "\n " + str (e ),
181187 }
182188 await websocket .send_text (json .dumps (error_message ))
189+ print ("\n \n --- SENT ERROR: ---\n \n " )
190+ print (error )
191+ print ("\n \n --- (ERROR ABOVE WAS SENT) ---\n \n " )
183192
184193 async def send_output ():
185194 while True :
186195 try :
187196 output = await async_interpreter .output ()
188197
198+ print ("SENDING" , output )
199+
189200 if isinstance (output , bytes ):
190201 await websocket .send_bytes (output )
191202 else :
192203 await websocket .send_text (json .dumps (output ))
193204 except Exception as e :
194- traceback .print_exc ( )
205+ error = traceback .format_exc () + " \n " + str ( e )
195206 error_message = {
196207 "role" : "server" ,
197208 "type" : "error" ,
198209 "content" : traceback .format_exc () + "\n " + str (e ),
199210 }
200211 await websocket .send_text (json .dumps (error_message ))
212+ print ("\n \n --- SENT ERROR: ---\n \n " )
213+ print (error )
214+ print ("\n \n --- (ERROR ABOVE WAS SENT) ---\n \n " )
201215
202216 await asyncio .gather (receive_input (), send_output ())
203217 except Exception as e :
204- traceback .print_exc ()
205218 try :
219+ error = traceback .format_exc () + "\n " + str (e )
206220 error_message = {
207221 "role" : "server" ,
208222 "type" : "error" ,
209223 "content" : traceback .format_exc () + "\n " + str (e ),
210224 }
211225 await websocket .send_text (json .dumps (error_message ))
226+ print ("\n \n --- SENT ERROR: ---\n \n " )
227+ print (error )
228+ print ("\n \n --- (ERROR ABOVE WAS SENT) ---\n \n " )
212229 except :
213230 # If we can't send it, that's fine.
214231 pass
@@ -279,9 +296,12 @@ async def get_setting(setting: str):
279296
280297host = os .getenv (
281298 "HOST" , "127.0.0.1"
282- ) # IP address for localhost, used for local testing
299+ ) # IP address for localhost, used for local testing. To expose to local network, use 0.0.0.0
283300port = int (os .getenv ("PORT" , 8000 )) # Default port is 8000
284301
302+ # FOR TESTING ONLY
303+ # host = "0.0.0.0"
304+
285305
286306class Server :
287307 def __init__ (self , async_interpreter , host = host , port = port ):
@@ -296,6 +316,21 @@ def __init__(self, async_interpreter, host=host, port=port):
296316
297317 def run (self , retries = 5 , * args , ** kwargs ):
298318 print ("SERVER STARTING" )
319+
320+ if "host" in kwargs :
321+ host = kwargs ["host" ]
322+ else :
323+ host = self .host
324+
325+ if host == "0.0.0.0" :
326+ print (
327+ "Warning: Using host `0.0.0.0` will expose Open Interpreter over your local network."
328+ )
329+ s = socket .socket (socket .AF_INET , socket .SOCK_DGRAM )
330+ s .connect (("8.8.8.8" , 80 )) # Google's public DNS server
331+ print (f"Server is running at http://{ s .getsockname ()[0 ]} :{ self .port } " )
332+ s .close ()
333+
299334 for _ in range (retries ):
300335 try :
301336 self .uvicorn_server .run (* args , ** kwargs )
0 commit comments