diff --git a/.gitignore b/.gitignore index cc722c2..2fd9aed 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,8 @@ docker/agents/bin/ # Generated docker-compose.yml (run 'bin/disinto init' to regenerate) # Note: This file is now committed to track volume mount configuration # docker-compose.yml + +# Python bytecode +__pycache__/ +*.pyc +*.pyo diff --git a/docker/chat/Dockerfile b/docker/chat/Dockerfile index f83f093..194cee4 100644 --- a/docker/chat/Dockerfile +++ b/docker/chat/Dockerfile @@ -1,7 +1,7 @@ -# disinto-chat — minimal HTTP+WebSocket backend for Claude chat UI +# disinto-chat — minimal HTTP backend for Claude chat UI # -# Small Debian slim base with Python runtime and websockets library. -# Chosen for simplicity and small image size (~100MB vs ~150MB for Go). +# Small Debian slim base with Python runtime. +# Chosen for simplicity and small image size (~100MB). # # Image size: ~100MB (well under the 200MB ceiling) # @@ -10,11 +10,9 @@ FROM debian:bookworm-slim -# Install Python and websockets (no build-time network access needed) +# Install Python (no build-time network access needed) RUN apt-get update && apt-get install -y --no-install-recommends \ python3 \ - python3-pip \ - && pip3 install --break-system-packages websockets \ && rm -rf /var/lib/apt/lists/* # Non-root user diff --git a/docker/chat/__pycache__/server.cpython-311.pyc b/docker/chat/__pycache__/server.cpython-311.pyc deleted file mode 100644 index 54e1b44..0000000 Binary files a/docker/chat/__pycache__/server.cpython-311.pyc and /dev/null differ diff --git a/docker/chat/server.py b/docker/chat/server.py index dbb6514..485fce9 100644 --- a/docker/chat/server.py +++ b/docker/chat/server.py @@ -165,35 +165,21 @@ class ChatHandler(BaseHTTPRequestHandler): return try: - # Spawn claude --print with streaming output - # Using stream-json format for structured parsing capability + # Spawn claude --print with text output format proc = subprocess.Popen( - [CLAUDE_BIN, "--print", message, "--output-format", "stream-json"], + [CLAUDE_BIN, "--print", message], stdout=subprocess.PIPE, stderr=subprocess.PIPE, - text=False, - bufsize=0, # Unbuffered for streaming + text=True, ) - # Read and stream response - response_parts = [] - error_parts = [] - - # Read stdout in chunks - while True: - chunk = proc.stdout.read(4096) - if not chunk: - break - try: - response_parts.append(chunk.decode("utf-8")) - except UnicodeDecodeError: - response_parts.append(chunk.decode("utf-8", errors="replace")) + # Read response as text (Claude outputs plain text when not using stream-json) + response = proc.stdout.read() # Read stderr (should be minimal, mostly for debugging) - if proc.stderr: - error_output = proc.stderr.read() - if error_output: - error_parts.append(error_output.decode("utf-8", errors="replace")) + error_output = proc.stderr.read() + if error_output: + print(f"Claude stderr: {error_output}", file=sys.stderr) # Wait for process to complete proc.wait() @@ -202,12 +188,6 @@ class ChatHandler(BaseHTTPRequestHandler): if proc.returncode != 0: self.send_error(500, f"Claude CLI failed with exit code {proc.returncode}") return - - # Combine response parts - response = "".join(response_parts) - - # If using stream-json, we could parse and reformat here. - # For now, return as-is (HTMX will display it in the UI). self.send_response(200) self.send_header("Content-Type", "text/plain; charset=utf-8") self.send_header("Content-Length", len(response.encode("utf-8"))) diff --git a/docker/chat/ui/index.html b/docker/chat/ui/index.html index 35bcc12..d3851ce 100644 --- a/docker/chat/ui/index.html +++ b/docker/chat/ui/index.html @@ -132,7 +132,7 @@