Skip to content

Commit 14b8b99

Browse files
committed
Update UI for interactive chat
1 parent 87bacb5 commit 14b8b99

2 files changed

Lines changed: 272 additions & 271 deletions

File tree

agentic/web_ui/app.py

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111

1212
app = FastAPI()
1313

14-
AGENT_DIR = Path(__file__).parent.parent # Go up from web_ui/ to agentic/
14+
AGENT_DIR = Path(__file__).parent.parent
1515
GENERATED_SCRIPTS_DIR = AGENT_DIR / "generated_scripts"
1616

1717

1818
class Session:
1919
def __init__(self):
2020
self.output_queue = Queue()
21+
self.process = None
2122

2223
async def _send(self, ws, msg):
2324
await ws.send_text(json.dumps(msg))
@@ -35,29 +36,49 @@ async def _send_scripts(self, ws):
3536
"content": f.read_text()
3637
})
3738

39+
def send_input(self, text):
40+
"""Send text to the running process's stdin"""
41+
if self.process and self.process.stdin:
42+
try:
43+
self.process.stdin.write(text + "\n")
44+
self.process.stdin.flush()
45+
except Exception as e:
46+
self.output_queue.put(("error", f"Failed to send input: {e}"))
47+
3848
def _subprocess_thread(self, cmd, cwd):
3949
try:
40-
process = subprocess.Popen(
50+
self.process = subprocess.Popen(
4151
cmd,
4252
cwd=cwd,
53+
stdin=subprocess.PIPE,
4354
stdout=subprocess.PIPE,
4455
stderr=subprocess.STDOUT,
4556
text=True,
4657
bufsize=1,
4758
env={**os.environ, "PYTHONUNBUFFERED": "1"}
4859
)
49-
for line in process.stdout:
60+
for line in self.process.stdout:
5061
self.output_queue.put(("line", line.rstrip()))
51-
process.wait()
52-
self.output_queue.put(("exit", process.returncode))
62+
self.process.wait()
63+
self.output_queue.put(("exit", self.process.returncode))
5364
except Exception as e:
5465
self.output_queue.put(("error", str(e)))
66+
finally:
67+
self.process = None
5568

5669
async def run_agent(self, agent_script, scripts_dir, ws, agent_dir=None):
57-
await self._log(ws, f"started: {agent_script} --scripts {scripts_dir}")
58-
5970
run_dir = Path(agent_dir) if agent_dir else AGENT_DIR
60-
cmd = [sys.executable, agent_script, "--scripts", scripts_dir]
71+
cmd = [sys.executable, agent_script]
72+
73+
# Add --interactive if the script supports it
74+
if "interactive" in agent_script.lower():
75+
cmd.append("--interactive")
76+
77+
# Add --scripts only if provided
78+
if scripts_dir:
79+
cmd.extend(["--scripts", scripts_dir])
80+
81+
await self._log(ws, f"started: {' '.join(cmd)}")
6182

6283
while not self.output_queue.empty():
6384
try:
@@ -100,14 +121,26 @@ async def run_agent(self, agent_script, scripts_dir, ws, agent_dir=None):
100121
async def ws_endpoint(ws: WebSocket, session_id: str):
101122
await ws.accept()
102123
s = sessions.setdefault(session_id, Session())
124+
agent_task = None
103125
try:
104126
while True:
105127
raw = await ws.receive_text()
106128
msg = json.loads(raw)
107-
agent_script = msg.get("agent_script", "libe_agent_basic.py")
108-
scripts_dir = msg.get("scripts_dir", "")
109-
agent_dir = msg.get("agent_dir", None)
110-
if scripts_dir:
111-
await s.run_agent(agent_script, scripts_dir, ws, agent_dir=agent_dir)
129+
130+
if msg.get("type") == "input":
131+
s.send_input(msg.get("text", ""))
132+
else:
133+
# Run agent as background task so we can keep receiving input
134+
if agent_task and not agent_task.done():
135+
agent_task.cancel()
136+
agent_task = asyncio.create_task(
137+
s.run_agent(
138+
msg.get("agent_script", ""),
139+
msg.get("scripts_dir") or "",
140+
ws,
141+
agent_dir=msg.get("agent_dir")
142+
)
143+
)
112144
except WebSocketDisconnect:
113-
pass
145+
if agent_task and not agent_task.done():
146+
agent_task.cancel()

0 commit comments

Comments
 (0)