Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 19 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Shared by frontend (./Dockerfile) and deepsql-agent (agent/Dockerfile),
# both of which use the repo root as build context.
.git
.github
**/.venv
**/venv
**/node_modules
**/__pycache__
backend/target
backend/.mvn/wrapper/maven-wrapper.jar
*.log
.env
.env.*
!.env.example
dist
coverage
tmp
.cursor
.hermes
51 changes: 23 additions & 28 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,23 @@ DEEPSQL_EMBEDDING_MODEL=text-embedding-3-large
# profile which defaults to false.
EMBEDDING_FAIL_OPEN=false

# ── Hermes agent (Agent tab + AI dashboards) ────────────────────────────────
# Backend → Hermes for dashboards / Slack / CLI. Compose defaults this; only
# override if Hermes listens elsewhere. Requires scripts/self-host/setup-agent.sh
# (also run by install.sh unless DEEPSQL_SKIP_AGENT_SETUP=1).
#AGENT_WEBUI_URL=http://host.docker.internal:8787
#DEEPSQL_SKIP_AGENT_SETUP=0
# ── DeepSQL Agent (Agent tab + AI dashboards) ───────────────────────────────
# The fifth Compose service (`deepsql-agent`) serves the Agent tab, AI
# dashboards, and Slack/CLI agent turns. install.sh auto-generates
# AGENT_PROVISION_SECRET; Compose wires the rest. Override only for native
# (non-Compose) development or a custom agent hostname.
#
# AGENT_WEBUI_URL Agent HTTP API. Compose default: http://deepsql-agent:8787
# AGENT_PROVISIONER_URL Per-user profile provisioner. Compose default:
# http://deepsql-agent:8788/provision
# AGENT_PROVISION_SECRET Shared secret between backend and agent (required).
# DEEPSQL_AGENT_PORT / DEEPSQL_AGENT_PROVISIONER_PORT — host port mappings.
#
#AGENT_WEBUI_URL=http://deepsql-agent:8787
#AGENT_PROVISIONER_URL=http://deepsql-agent:8788/provision
AGENT_PROVISION_SECRET=change-me-agent-provision-secret
#DEEPSQL_AGENT_PORT=8787
#DEEPSQL_AGENT_PROVISIONER_PORT=8788
#DEEPSQL_SMOKE_AGENT=1

# ── Demo Data Seeding ───────────────────────────────────────────────────────
Expand All @@ -156,31 +167,15 @@ EMBEDDING_FAIL_OPEN=false
# code reads any azure.openai.* property any more, so setting them changes nothing.

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# OPTIONAL — DeepSQL Agent runtime (chat TUI + the web Agent tab)
# OPTIONAL — Native (non-Compose) DeepSQL Agent
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# The agent surfaces — `deepsql agent` and the Agent tab — are served by a separate
# runtime, not by the backend. There is no deepsql-agent container in this stack:
# setup-agent.sh installs Hermes on the *host*, listening on :8787. That is why the
# chat default reaches out of the container instead of across the Compose network.
# Everything else in DeepSQL works without any of this.
#
# AGENT_WEBUI_URL where the agent runtime serves its API. Default
# http://host.docker.internal:8787 (AgentChatClient.java:58),
# which is right under Compose — but a native backend run has no
# such host, so there it must be set to http://127.0.0.1:8787.
# AGENT_PROVISIONER_URL per-user profile provisioning endpoint. Default
# http://deepsql-agent:8788/provision (AgentBridgeService.java:65)
# still names the container that does not exist here, so this one
# must be set explicitly — under Compose and natively alike.
# AGENT_PROVISION_SECRET shared secret for the above. Unset, the backend logs
# "agent.provision-secret is unset — skipping" and never creates
# the u-<user> profile, so the agent has no identity to run as.
#
# Native runs: start the provisioner with `python3 scripts/local-agent-provisioner.py`.
# See AGENTS.md for the full sequence, and agent/README.md for the runtime itself.
# Only needed when you run the backend with `mvn spring-boot:run` instead of
# Compose. Point at a local agent process and start the provisioner:
# python3 scripts/local-agent-provisioner.py
# Or use the legacy host installer: ./scripts/self-host/setup-agent.sh
# (set DEEPSQL_HOST_AGENT_SETUP=1). Prefer Compose for self-host / enterprise.
#AGENT_WEBUI_URL=http://127.0.0.1:8787
#AGENT_PROVISIONER_URL=http://127.0.0.1:8788/provision
#AGENT_PROVISION_SECRET=

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# VECTOR STORE — choose one mode
Expand Down
13 changes: 12 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ docker compose down # Stop

**Vault DB**: `jdbc:postgresql://localhost:5432/dba_agent` (postgres/postgres)

### Self-host Compose (5 services)

```bash
./scripts/self-host/install.sh # builds + starts everything
docker compose ps # postgres, valkey, backend, deepsql-agent, frontend
```

The **DeepSQL Agent** is the fifth container (`agent/Dockerfile`): Agent tab, AI
dashboards, Slack/CLI agent turns, and per-user profile provisioning on :8787/:8788.
No host-side agent install is required for Compose deployments.

## Architecture

```
Expand Down Expand Up @@ -90,7 +101,7 @@ src/ # Frontend (React)

docs/ # Documentation
mcp/ # DeepSQL Phase 1 MCP server (Node stdio wrapper around backend APIs)
agent/ # DeepSQL Agent customization (persona, skills, skins; customized Hermes runtime)
agent/ # DeepSQL Agent (persona, skills, skins, Dockerfile for the Compose service)
```

## MCP Server
Expand Down
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,15 @@ is rejected. Changing width means migrating the column.
./scripts/self-host/install.sh
```

The installer generates your JWT secret, the credential-vault encryption key and the vault
DB password, prompts for the first admin account, builds both images, starts the stack, and
verifies pgvector is live. Unless you set `DEEPSQL_SKIP_AGENT_SETUP=1`, it also runs
[`scripts/self-host/setup-agent.sh`](scripts/self-host/setup-agent.sh) to install Hermes under
`~/.hermes/`, wire DeepSQL MCP, and start the webui on `0.0.0.0:8787` (required for the
**Agent** tab and AI dashboard generation).
The installer generates your JWT secret, the credential-vault encryption key, the vault
DB password, and the DeepSQL Agent provision secret; prompts for the first admin account;
builds the backend, frontend, and DeepSQL Agent images; starts the stack; and verifies
pgvector is live. The **Agent** tab and AI dashboard generation are served by the
`deepsql-agent` Compose service — no host-side agent install is required.

**The first build takes several minutes** — it compiles the Spring Boot backend with Maven
inside the container and bundles the frontend with Vite. It has not hung. Later builds reuse
the Docker layer cache.
inside the container, bundles the frontend with Vite, and builds the DeepSQL Agent image.
It has not hung. Later builds reuse the Docker layer cache.

Then open **http://localhost:3000** and log in with the admin email and password you entered.

Expand Down
92 changes: 92 additions & 0 deletions agent/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# DeepSQL Agent — self-contained container for the Agent tab, AI dashboards,
# Slack/CLI agent turns, and per-user profile provisioning.
#
# Built from this checkout. The runtime engine is an upstream dependency
# installed at image-build time; the product surface (persona, skills, MCP,
# branding) is owned by DeepSQL and is what operators interact with.

FROM python:3.12-slim-bookworm

ENV DEBIAN_FRONTEND=noninteractive \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
# Product home — operators never need to know the upstream layout.
DEEPSQL_AGENT_HOME=/var/lib/deepsql-agent \
DEEPSQL_AGENT_ROOT=/opt/deepsql-agent \
PATH="/opt/deepsql-agent/runtime/venv/bin:/usr/local/bin:${PATH}"

RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
git \
nodejs \
npm \
build-essential \
&& rm -rf /var/lib/apt/lists/*

# Node 20+ is required by the DeepSQL MCP server. Debian bookworm ships
# Node 18; replace with NodeSource 20.
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/* \
&& node --version && npm --version

# Install uv for fast Python env management.
RUN curl -fsSL https://astral.sh/uv/install.sh | sh \
&& ln -sf /root/.local/bin/uv /usr/local/bin/uv

WORKDIR /opt/deepsql-agent

# Upstream runtime clones. Refs are overridable at build time; defaults track
# what scripts/self-host/setup-agent.sh installs for host-based installs.
ARG AGENT_RUNTIME_REPO=https://github.com/NousResearch/hermes-agent.git
ARG AGENT_RUNTIME_REF=main
ARG AGENT_API_REPO=https://github.com/nesquena/hermes-webui.git
ARG AGENT_API_REF=master

# Runtime engine (Python agent)
RUN git clone --depth 1 --branch "${AGENT_RUNTIME_REF}" "${AGENT_RUNTIME_REPO}" runtime \
&& cd runtime \
&& UV_NO_CONFIG=1 uv sync \
&& if [ -d .venv ] && [ ! -d venv ]; then ln -sfn .venv venv; fi \
&& if [ -d venv ] && [ ! -d .venv ]; then ln -sfn venv .venv; fi \
# Pin MCP SDK below 2.0 — SDK 2.x renamed CallToolResult.isError → is_error
# and breaks every DeepSQL tool call until the runtime catches up.
&& UV_NO_CONFIG=1 uv pip install --python venv/bin/python 'mcp>=1.0,<2' 'pyyaml>=6'

# HTTP API surface the frontend / backend talk to (:8787).
# Default branch is master (not main). Fall back to HEAD if the ref moves.
RUN (git clone --depth 1 --branch "${AGENT_API_REF}" "${AGENT_API_REPO}" api \
|| git clone --depth 1 "${AGENT_API_REPO}" api) \
&& cd api \
&& if [ -f requirements.txt ]; then \
UV_NO_CONFIG=1 uv pip install --python /opt/deepsql-agent/runtime/venv/bin/python -r requirements.txt; \
fi

# DeepSQL product surface — persona, skills, branding, MCP, provisioner.
COPY agent/SOUL.md /opt/deepsql-agent/SOUL.md
COPY agent/skills /opt/deepsql-agent/skills
COPY agent/webui /opt/deepsql-agent/webui-overlay
COPY agent/skins /opt/deepsql-agent/skins
COPY agent/distribution.yaml /opt/deepsql-agent/distribution.yaml
COPY mcp /opt/deepsql-agent/mcp
COPY scripts/local-agent-provisioner.py /opt/deepsql-agent/provisioner.py
COPY agent/docker-entrypoint.sh /opt/deepsql-agent/docker-entrypoint.sh

RUN chmod +x /opt/deepsql-agent/docker-entrypoint.sh \
&& cd /opt/deepsql-agent/mcp && npm install --omit=dev --ignore-scripts \
&& mkdir -p /var/lib/deepsql-agent/logs /var/lib/deepsql-agent/profiles \
# Apply DeepSQL Agent branding to the API UI (idempotent overlay).
&& bash /opt/deepsql-agent/webui-overlay/apply-overlay.sh /opt/deepsql-agent/api || true

# Expose the agent API (:8787) and the secret-gated provisioner (:8788).
EXPOSE 8787 8788

VOLUME ["/var/lib/deepsql-agent"]

# Provisioner /health is unauthenticated and always 200 when the process is up.
# The API on :8787 may require a session, so we don't use it for the healthcheck.
HEALTHCHECK --interval=30s --timeout=5s --start-period=90s --retries=5 \
CMD curl -fsS http://127.0.0.1:8788/health >/dev/null || exit 1

ENTRYPOINT ["/opt/deepsql-agent/docker-entrypoint.sh"]
31 changes: 23 additions & 8 deletions agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,31 @@ agent HTTP API (`/agent-api/*`), not the Hermes webui skin.
These mirror workflows the in-house `AgentOrchestrator` performed, re-expressed as
agent persona + skills over the DeepSQL MCP tools.

## Install (local / self-host)
## Install (self-host / enterprise)

1. Install the upstream agent runtime (see [AGENTS.md](../AGENTS.md) Cursor Cloud notes
or the [Hermes install docs](https://hermes-agent.nousresearch.com/)).
2. Apply DeepSQL customization (requires `AZURE_OPENAI_KEY` in the environment or
**Preferred:** the `deepsql-agent` Compose service. `./scripts/self-host/install.sh`
builds `agent/Dockerfile` and starts the Agent API (:8787) + profile provisioner
(:8788) on the compose network. No host-side agent install is required.

```bash
./scripts/self-host/install.sh
# or
docker compose up -d --build deepsql-agent
```

### Native / local development (optional)

1. Install the upstream agent runtime (see [AGENTS.md](../AGENTS.md) Cursor Cloud notes).
2. Apply DeepSQL customization (requires `DEEPSQL_CHAT_API_KEY` in the environment or
the repo `.env`):

```bash
bash agent/install.sh
```

It configures `~/.hermes/config.yaml` from this repo:
It configures the agent home from this repo:

- **model** — Azure OpenAI via its OpenAI-compatible `…/openai/v1` endpoint (key from env/.env, never committed)
- **model** — via OpenAI-compatible endpoint (key from env/.env, never committed)
- **mcp_servers.deepsql** — this repo’s `mcp/deepsql-phase1-server.js`
- **skills.external_dirs** — this repo’s `agent/skills` (source of truth; must be a YAML list)
- **approvals.mode: smart**, **SOUL.md** persona, and disables host-affecting toolsets
Expand All @@ -66,11 +77,15 @@ It configures `~/.hermes/config.yaml` from this repo:
Verify:

```bash
cd ~/.hermes/hermes-agent && uv run hermes mcp test deepsql # → Connected, DeepSQL tools
# Compose
curl -fsS http://localhost:8788/health

# Native (after setup-agent.sh)
./scripts/self-host/setup-agent.sh
```

The DeepSQL MCP server and the Spring backend remain the DBA brain; the agent consumes them.
Optional upstream webui skin: see [`webui/`](webui/).
Optional upstream UI skin: see [`webui/`](webui/).

### Approval UX (operator note)

Expand Down
Loading
Loading