Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
9a6e1db
chore: ignore .worktrees directory
gustavokch Mar 16, 2026
12d94f9
fix: resolve proxy bugs — input filtering, session duplication, race …
gustavokch Mar 16, 2026
bbd1ac3
fix: add timeout to query(), disable tools by default on /v1/messages
gustavokch Mar 16, 2026
cef13d0
chore: update poetry.lock and test suite for pydantic 2.13 and poetry…
gustavokch Mar 16, 2026
c53cdca
feat: v2.3.0 — bug fixes, async concurrency, and SDK options wiring
gustavokch Mar 17, 2026
4bf3e2a
chore: ignore .worktrees directory
gustavokch Mar 24, 2026
9d671c7
fix: add latest models and update default model to Sonnet 4.6
gustavokch Mar 24, 2026
e91c5fe
Change repository URL to new GitHub location
gustavokch Mar 24, 2026
4b06b77
build: refactor Dockerfile to multi-stage build and non-root user
prodigy Mar 29, 2026
8c7602b
deps: upgrade claude-agent-sdk to 0.1.52 and add Claude 4.6 models
prodigy Mar 29, 2026
27357e3
security: implement redaction for sensitive information in logs and e…
prodigy Mar 29, 2026
d190d88
security: enforce limits on concurrent sessions and message history
prodigy Mar 29, 2026
d2eade5
security: improve rate limiting with trusted proxy support
prodigy Mar 29, 2026
d3207ae
security: harden API endpoints and CORS configuration
prodigy Mar 29, 2026
13baebb
security: implement file system sandboxing for working directory
prodigy Mar 29, 2026
debc8b1
feat: add warning header for unrecognized models
prodigy Mar 29, 2026
e133777
chore: regenerate poetry.lock for SDK ^0.1.52 constraint
prodigy Mar 29, 2026
e0b750f
feat: add Node.js to Docker runtime stage for Claude Agent SDK
prodigy Mar 29, 2026
81a91bc
feat: add Gemini CLI proxy support and interactive chat client
gustavokch Apr 6, 2026
c70750c
Merge pull request #1 from gustavokch/feature/gemini-proxy
gustavokch Apr 6, 2026
b203291
perf: optimize CLI latency via parallel prewarming and add process co…
gustavokch Apr 6, 2026
7db1124
Merge pull request #2 from gustavokch/feature/optimize-latency-and-co…
gustavokch Apr 6, 2026
6b38489
fix: resolve Gemini history echoing and improve session continuity
gustavokch Apr 6, 2026
07938a1
Merge pull request #3 from gustavokch/fix/gemini-history-echoing
gustavokch Apr 6, 2026
8e1c831
fix: address streaming echo for Gemini and Claude response failures
gustavokch Apr 6, 2026
5a5e7cc
Merge pull request #4 from gustavokch/fix/streaming-echo-and-claude-r…
gustavokch Apr 6, 2026
596b1f8
fix: improve Claude content extraction and streaming robustness
gustavokch Apr 6, 2026
ed73ae9
fix: refine content filtering to reduce false negatives
gustavokch Apr 6, 2026
53bfa82
Fix wrapper session handling for model switches
gustavokch Apr 6, 2026
8020032
Merge pull request #5 from gustavokch/fix/session-handling-chat-model…
gustavokch Apr 6, 2026
e21cee7
add github actions workflow to publish image to ghcr
brandonros Apr 18, 2026
cd96cde
update CLAUDE_MODELS to current GA set
brandonros Apr 18, 2026
94999a1
support CLAUDE_MODELS_OVERRIDE env var + callout the hardcoding
brandonros Apr 18, 2026
4457958
fix black formatting in DEFAULT_CLAUDE_MODELS
brandonros Apr 18, 2026
22f8fff
bump claude-agent-sdk from 0.1.18 to 0.1.63
brandonros Apr 18, 2026
b525008
Merge prodigy-sln security audit & SDK upgrade
brandonros Apr 18, 2026
039a63b
Merge gustavokch security & latency work
brandonros Apr 18, 2026
c6fd55e
rip out Gemini CLI support from gustavokch merge
brandonros Apr 18, 2026
32f738e
config knobs + extract landing page HTML to template
brandonros Apr 18, 2026
6f5fac7
FAST_MODEL
brandonros Apr 18, 2026
3dd5bd1
lint + tests
brandonros Apr 18, 2026
e3de586
no python 3.10
brandonros Apr 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ CLAUDE_CLI_PATH=claude

# Server Configuration
PORT=8000
# Maximum number of concurrent CLI processes allowed (default: 3)
# MAX_CONCURRENT_PROCESSES=3
# Host binding address - use 127.0.0.1 for local-only access, 0.0.0.0 for all interfaces
# CLAUDE_WRAPPER_HOST=0.0.0.0
# Maximum request body size in bytes (default: 10MB)
Expand All @@ -21,12 +23,18 @@ PORT=8000
# Timeout Configuration (milliseconds)
MAX_TIMEOUT=600000

# Prewarming Configuration
# Prompt to use during startup for prewarming the CLI backends (default: Hello)
# PREWARM_PROMPT=Hello

# CORS Configuration
CORS_ORIGINS=["*"]

# Model Configuration
# Default Claude model to use when none specified in request
DEFAULT_MODEL=claude-sonnet-4-5-20250929
DEFAULT_MODEL=claude-sonnet-4-6
# Fast Claude model for speed/cost-optimized paths
FAST_MODEL=claude-haiku-4-5-20251001

# Rate Limiting Configuration
RATE_LIMIT_ENABLED=true
Expand All @@ -35,4 +43,14 @@ RATE_LIMIT_CHAT_PER_MINUTE=10
RATE_LIMIT_DEBUG_PER_MINUTE=2
RATE_LIMIT_AUTH_PER_MINUTE=10
RATE_LIMIT_SESSION_PER_MINUTE=15
RATE_LIMIT_HEALTH_PER_MINUTE=30
RATE_LIMIT_HEALTH_PER_MINUTE=30

# Security Configuration
# Comma-separated list of trusted proxy IPs (for X-Forwarded-For rate limiting)
# TRUSTED_PROXIES=10.0.0.1,10.0.0.2
# Base directory for CLAUDE_CWD sandboxing (default: system temp dir)
# CLAUDE_CWD_ALLOWED_BASE=/tmp
# Maximum concurrent sessions (default: 1000)
# MAX_SESSIONS=1000
# Maximum messages per session history (default: 100)
# MAX_SESSION_MESSAGES=100
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]
python-version: ["3.12"]

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -52,14 +52,14 @@ jobs:
run: poetry run bandit -r src/ -ll -x tests

- name: Dependency vulnerability scan
run: poetry run safety check || true
run: poetry run safety scan || true
continue-on-error: true

- name: Run tests
run: poetry run pytest tests/ -v --cov=src --cov-report=xml --cov-report=term-missing

- name: Upload coverage to Codecov
if: matrix.python-version == '3.11'
if: matrix.python-version == '3.12'
uses: codecov/codecov-action@v4
with:
files: ./coverage.xml
Expand Down
50 changes: 50 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Build and push container image to GHCR

on:
push:
branches:
- main
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=sha
type=raw,value=latest

- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ logs/
# Testing
.coverage
.pytest_cache/
.hypothesis/
htmlcov/

# Claude Code
Expand All @@ -57,4 +58,5 @@ test_debug_*.py
test_performance_*.py
test_user_*.py
test_new_*.py
test_roocode_compatibility.py
test_roocode_compatibility.py
.worktrees/
58 changes: 43 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,30 +1,58 @@
FROM python:3.12-slim
# Stage 1: Builder — install Poetry and dependencies
FROM python:3.12-slim AS builder

# Install system deps (curl for Poetry installer)
RUN apt-get update && apt-get install -y \
curl \
&& rm -rf /var/lib/apt/lists/*

# Install Poetry globally
RUN curl -sSL https://install.python-poetry.org | python3 -

# Add Poetry to PATH
ENV PATH="/root/.local/bin:${PATH}"

# Note: Claude Code CLI is bundled with claude-agent-sdk >= 0.1.8
# No separate Node.js/npm installation required
WORKDIR /app

# Copy dependency files first (cache-friendly)
COPY pyproject.toml poetry.lock ./

# Copy the app code
COPY . /app
# Install dependencies into a virtualenv
RUN poetry config virtualenvs.in-project true && \
poetry install --no-root --no-interaction

# Copy application code
COPY . .

# Install the project itself
RUN poetry install --no-interaction


# Stage 2: Runtime — minimal image with non-root user
FROM python:3.12-slim

# Install Node.js (required by Claude Agent SDK bundled CLI)
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/*

# Create non-root user
RUN groupadd --gid 1000 appuser && \
useradd --uid 1000 --gid appuser --create-home appuser

# Set working directory
WORKDIR /app

# Install Python dependencies with Poetry
RUN poetry install --no-root
# Copy virtualenv and app code from builder (owned by appuser)
COPY --from=builder --chown=appuser:appuser /app/.venv /app/.venv
COPY --from=builder --chown=appuser:appuser /app/src /app/src
COPY --from=builder --chown=appuser:appuser /app/pyproject.toml /app/pyproject.toml

# Ensure virtualenv binaries are on PATH
ENV PATH="/app/.venv/bin:${PATH}"
ENV VIRTUAL_ENV="/app/.venv"

# Switch to non-root user
USER appuser

# Expose the port (default 8000)
EXPOSE 8000

# Run the app with Uvicorn (development mode with reload; switch to --no-reload for prod)
CMD ["poetry", "run", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
# Production CMD — no --reload
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
24 changes: 24 additions & 0 deletions PR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Release v2.3.0: Concurrency improvements, SDK options wiring, and critical bug fixes

This PR introduces version 2.3.0, focusing on significant reliability improvements, full support for concurrent SDK calls, wiring of new Claude API options, and resolutions for several critical proxy bugs.

## Features & Enhancements
* **SDK Options Wiring:** Full support for `reasoning_effort`, `response_format`, `thinking`, `max_budget_usd`, and `user` fields passed directly to the Claude SDK.
* **Concurrency:** Removed `os.environ` mutex (`_env_lock`) by passing auth via `options.env`, allowing fully concurrent SDK calls. `SessionManager` has been refactored to use `asyncio.Lock` with all session methods converted to async.
* **Token & Reason Mapping:** Extracts real token counts directly from the SDK's `ResultMessage` and properly maps `stop_reason` to `finish_reason` (e.g., `max_tokens` → `length`).
* **Tool Handling:** Changed `AnthropicMessagesRequest.enable_tools` default to `False` so simple message requests do not trigger unintended 10-turn loops.

## Bug Fixes
* **Session Continuity:** Fixed session continuation by correcting `continue_session` to `continue_conversation` and replaced list appending with replacement to prevent exponential duplication.
* **Timeouts & Hangs:** Wrapped async `query()` iterations with `asyncio.timeout` to prevent indefinite hangs when the SDK subprocess stalls.
* **Proxy Reliability:**
* Removed `filter_content()` from user input which was silently stripping XML-like tags.
* Secured `/v1/auth/status` endpoint with the `verify_api_key()` auth guard.
* Marked the Bash tool as `is_safe=False`.
* Replaced bare `except:` clauses with `except Exception:`.

## Maintenance & Chores
* Updated `poetry.lock` and the test suite for compatibility with `pydantic 2.13` and `poetry 2.3`.
* Replaced deprecated `datetime.utcnow()` with `datetime.now(timezone.utc)`.
* Ignored `.worktrees` directories in `.gitignore`.
* Added diagnostic print statements for `/v1/messages` and improved the `test_message.py` script.
Loading
Loading