mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-12 23:12:23 -06:00
a6e929b0a0
* Add channel integrations with Discord adapter and atomic session resume (#24) Bidirectional channel adapter framework connecting external messaging platforms to turnstone workstreams via Redis MQ. Discord ships as the first adapter; the protocol supports future Slack/Teams integrations. Channel framework: - ChannelAdapter protocol and ChannelRouter for channel↔workstream mapping - AsyncRedisBroker with single dispatch loop and per-channel ordered workers - channel_routes table (migration 003) for persistent route storage - 9 new StorageBackend methods (4 channel_user + 5 channel_route CRUD) - Unified turnstone-channel gateway entry point, loads adapters by config - Message chunking, approval formatting, plan review formatting Discord adapter: - discord.py v2.4+ bot with thread-per-@mention model - Slash commands: /link (modal), /unlink, /ask, /status, /close - Persistent button views for tool approval and plan review - Streaming responses via edit-in-place (1.5s interval) - Stale route detection and atomic session resume via resume_session field - SessionResumedEvent confirmation back to channel - Auto-approve support (blanket + per-tool list) Atomic session resume: - resume_session field on CreateWorkstreamMessage for single-request resume - Server resumes session during POST /v1/api/workstreams/new atomically - Bridge emits SessionResumedEvent to per-workstream channel - WorkstreamCreatedEvent extended with resumed/session_id/message_count - Server UI dashboardResumeSession simplified to single request - Pruned sessions fall back gracefully to fresh start Service auth: - Bridge and console auto-mint service JWTs from TURNSTONE_JWT_SECRET - Bridge: approve scope (1 week). Console collector: read. Proxy: write. Console admin: - Channels tab with per-user view, force-link modal, unlink - 3 admin API endpoints for channel user management - Styled confirm modals replacing browser confirm() dialogs Bug fixes: - AsyncRedisBroker: replaced per-channel listener tasks with single dispatch loop + per-channel queue workers (fixes message stealing race) - Bridge: approval/plan review dedup guard prevents SSE reconnect duplicates - Bridge: _active_sends tracked for initial messages (fixes missing TurnCompleteEvent and unfinalized streaming messages) - Bridge: HTTP calls moved outside lock scope in approval handlers - Bridge: _handle_send cleans up _active_sends on HTTP/server errors - Formatter: reads server SSE format (func_name/preview) with fallback Docs, SDK, tests: - docs/channels.md setup guide, architecture diagram 16 - Updated api-reference.md, architecture.md, console.md, docker.md - Python SDK: resume_session param on create_workstream (async + sync) - TypeScript SDK: updated CreateWorkstreamRequest/Response interfaces - OpenAPI schema: resume_session request, resumed/message_count response - 91 new tests (19 storage, 15 broker, 22 protocol, 6 routing, 18 discord, 12 resume flow) — 1120 total passing * Fix CI lint/typecheck failures and address Copilot review feedback (#24) Lint: fix import ordering, remove unused imports, use contextlib.suppress. Mypy: explicit postgresql dialect import, add discord module overrides for optional-dependency CI environments. Copilot: fix double-escaping in admin confirm modals, return resolved session_id from server resume response, fix channel_routes diagram schema, use atomic setdefault for routing locks, add post-insert race guard in admin channel create, support SSE format in auto-approve check, update identity linking note in architecture diagram. * Fix remaining mypy call-arg errors for discord.py optional dependency Add type: ignore[call-arg] on Modal(title=) and Cog(name=) class definitions that fail when discord.py is not installed in CI.
56 lines
2.0 KiB
Docker
56 lines
2.0 KiB
Docker
# =============================================================================
|
|
# Turnstone — multi-stage Docker build
|
|
# Single image for all services: server, bridge, console, sim, eval
|
|
# =============================================================================
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# Stage 1: Builder — build the wheel
|
|
# ----------------------------------------------------------------------------
|
|
FROM python:3.13-slim AS builder
|
|
|
|
WORKDIR /build
|
|
|
|
RUN pip install --no-cache-dir hatchling
|
|
|
|
COPY pyproject.toml README.md LICENSE ./
|
|
COPY turnstone/ turnstone/
|
|
|
|
RUN pip wheel --no-deps --wheel-dir /build/wheels .
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# Stage 2: Runtime — slim image with the installed package
|
|
# ----------------------------------------------------------------------------
|
|
FROM python:3.13-slim
|
|
|
|
LABEL org.opencontainers.image.title="turnstone" \
|
|
org.opencontainers.image.description="Multi-node AI orchestration platform"
|
|
|
|
# System dependencies for psycopg (PostgreSQL client library)
|
|
RUN apt-get update && apt-get install -y --no-install-recommends libpq5 \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Non-root user
|
|
RUN useradd --create-home --shell /bin/bash turnstone
|
|
|
|
# Install the wheel with all optional extras
|
|
COPY --from=builder /build/wheels/*.whl /tmp/wheels/
|
|
RUN pip install --no-cache-dir "$(ls /tmp/wheels/*.whl)[mq,console,sim,postgres,discord]" \
|
|
&& rm -rf /tmp/wheels
|
|
|
|
# Health check script (stdlib only, no pip deps needed)
|
|
COPY docker/healthcheck.py /usr/local/bin/healthcheck.py
|
|
|
|
# Entrypoint script — runs migrations before starting
|
|
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
|
|
|
|
# Data directory — SQLite DB is created in CWD
|
|
WORKDIR /data
|
|
RUN chown turnstone:turnstone /data
|
|
|
|
USER turnstone
|
|
|
|
ENTRYPOINT ["entrypoint.sh"]
|
|
|
|
# Default command (overridden per service in compose.yaml)
|
|
CMD ["turnstone-server", "--host", "0.0.0.0", "--port", "8080"]
|