Skip to content

Commit 9a2d085

Browse files
committed
Server fixes
1 parent 2b52072 commit 9a2d085

File tree

4 files changed

+59
-20
lines changed

4 files changed

+59
-20
lines changed

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ FROM python:3.11.8
88
# Set environment variables
99
# ENV OPENAI_API_KEY ...
1010

11-
ENV HOST 0.0.0.0
11+
ENV HOST 0.0.0.0
1212
# ^ Sets the server host to 0.0.0.0, Required for the server to be accessible outside the container
1313

1414
# Copy required files into container

interpreter/core/async_core.py

+53-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import asyncio
22
import json
33
import os
4+
import socket
45
import threading
6+
import time
57
import traceback
68
from datetime import datetime
79
from 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

280297
host = 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
283300
port = int(os.getenv("PORT", 8000)) # Default port is 8000
284301

302+
# FOR TESTING ONLY
303+
# host = "0.0.0.0"
304+
285305

286306
class 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)

interpreter/core/llm/utils/convert_to_openai_messages.py

+2
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ def convert_to_openai_messages(
8080
if function_calling:
8181
new_message["role"] = "function"
8282
new_message["name"] = "execute"
83+
if "content" not in message:
84+
print("What is this??", content)
8385
if message["content"].strip() == "":
8486
new_message[
8587
"content"

interpreter/core/respond.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,9 @@ def respond(interpreter):
238238
break
239239

240240
# They may have edited the code! Grab it again
241-
code = interpreter.messages[-1]["content"]
241+
code = [m for m in interpreter.messages if m["type"] == "code"][-1][
242+
"content"
243+
]
242244

243245
# don't let it import computer — we handle that!
244246
if interpreter.computer.import_computer_api and language == "python":

0 commit comments

Comments
 (0)