1
1
import asyncio
2
2
import json
3
3
import os
4
+ import socket
4
5
import threading
6
+ import time
5
7
import traceback
6
8
from datetime import datetime
7
9
from typing import Any , Dict
@@ -35,6 +37,8 @@ async def input(self, chunk):
35
37
When it hits an "end" flag, calls interpreter.respond().
36
38
"""
37
39
40
+ print ("Received:" , chunk )
41
+
38
42
if "start" in chunk :
39
43
# If the user is starting something, the interpreter should stop.
40
44
if self .respond_thread is not None and self .respond_thread .is_alive ():
@@ -79,13 +83,17 @@ def respond(self, run_code=None):
79
83
if run_code == None :
80
84
run_code = self .auto_run
81
85
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
89
97
90
98
if self .stop_event .is_set ():
91
99
return
@@ -102,20 +110,20 @@ def respond(self, run_code=None):
102
110
103
111
self .output_queue .sync_q .put (chunk )
104
112
105
- if chunk ["type" ] == "confirmation" :
106
- if not run_code :
107
- break
108
-
109
113
self .output_queue .sync_q .put (
110
114
{"role" : "server" , "type" : "status" , "content" : "complete" }
111
115
)
112
116
except Exception as e :
117
+ error = traceback .format_exc () + "\n " + str (e )
113
118
error_message = {
114
119
"role" : "server" ,
115
120
"type" : "error" ,
116
121
"content" : traceback .format_exc () + "\n " + str (e ),
117
122
}
118
123
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 " )
119
127
120
128
def accumulate (self , chunk ):
121
129
"""
@@ -163,52 +171,61 @@ async def receive_input():
163
171
if data .get ("type" ) == "websocket.receive" and "text" in data :
164
172
data = json .loads (data ["text" ])
165
173
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" :
170
175
print ("Disconnecting." )
171
176
return
172
177
else :
173
178
print ("Invalid data:" , data )
174
179
continue
175
180
176
181
except Exception as e :
182
+ error = traceback .format_exc () + "\n " + str (e )
177
183
error_message = {
178
184
"role" : "server" ,
179
185
"type" : "error" ,
180
186
"content" : traceback .format_exc () + "\n " + str (e ),
181
187
}
182
188
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 " )
183
192
184
193
async def send_output ():
185
194
while True :
186
195
try :
187
196
output = await async_interpreter .output ()
188
197
198
+ print ("SENDING" , output )
199
+
189
200
if isinstance (output , bytes ):
190
201
await websocket .send_bytes (output )
191
202
else :
192
203
await websocket .send_text (json .dumps (output ))
193
204
except Exception as e :
194
- traceback .print_exc ( )
205
+ error = traceback .format_exc () + " \n " + str ( e )
195
206
error_message = {
196
207
"role" : "server" ,
197
208
"type" : "error" ,
198
209
"content" : traceback .format_exc () + "\n " + str (e ),
199
210
}
200
211
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 " )
201
215
202
216
await asyncio .gather (receive_input (), send_output ())
203
217
except Exception as e :
204
- traceback .print_exc ()
205
218
try :
219
+ error = traceback .format_exc () + "\n " + str (e )
206
220
error_message = {
207
221
"role" : "server" ,
208
222
"type" : "error" ,
209
223
"content" : traceback .format_exc () + "\n " + str (e ),
210
224
}
211
225
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 " )
212
229
except :
213
230
# If we can't send it, that's fine.
214
231
pass
@@ -279,9 +296,12 @@ async def get_setting(setting: str):
279
296
280
297
host = os .getenv (
281
298
"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
283
300
port = int (os .getenv ("PORT" , 8000 )) # Default port is 8000
284
301
302
+ # FOR TESTING ONLY
303
+ # host = "0.0.0.0"
304
+
285
305
286
306
class Server :
287
307
def __init__ (self , async_interpreter , host = host , port = port ):
@@ -296,6 +316,21 @@ def __init__(self, async_interpreter, host=host, port=port):
296
316
297
317
def run (self , retries = 5 , * args , ** kwargs ):
298
318
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
+
299
334
for _ in range (retries ):
300
335
try :
301
336
self .uvicorn_server .run (* args , ** kwargs )
0 commit comments