feat: wire real service agents into chat with LLM tool dispatch + Rivet proxy fix (#3)
# Wire All 4 Microservice Agents Into Chat
Wires all 4 microservice-backed agents into the chat so the LLM can call real services and return session URLs.
---
## Changes
### New
* `src/routes/chat.ts`
* Added a direct HTTP chat endpoint.
* When the LLM calls:
* `start_interview_session`
* `analyze_resume`
* `start_roleplay_session`
* `compute_qscore`
* The route executes real service probes and returns live session URLs.
---
### Fixed
* `src/index.ts`
* Rivet proxy now forwards requests to the engine at `localhost:6420`
instead of using `registry.handler()`.
* Prevents the:
```txt
Runtime already started as runner
```
conflict.
* `src/actors/user-actor.ts`
* `receiveMessage()` now returns:
```ts
{
reply,
sessions: []
}
```
* Includes per-module session URLs in responses.
* `docker-compose.yml`
* Fixed:
* Gitea health check port
* Port mapping
* `A2A_ALLOWED_KEY` default value
* `src/config.ts`
* Added:
```ts
resumeServiceUrl
```
* Configured to use port `8002`.
---
### Rewritten
* `prompts/system.txt`
* Reworked into a conversational step-by-step flow.
* Added explicit rule:
> CALL THE TOOL IMMEDIATELY
---
### Updated
* `agents/*.md` (6 files)
* Updated:
* Domain descriptions
* Trigger phrases
* Agent boundaries
---
## Verified
| Agent | Service | Result |
| ------------- | ------------------------ | --------------------------- |
| Resume (Mira) | `resume-builder:8002` | Real analysis |
| Sara | `interview-service:8007` | Real Gemini session + URL |
| Emily | `roleplay-service:8008` | Real roleplay session + URL |
| Quinn | `qscore-service:8000` | Real Q-Score (~84) |
---
## Outcome
The chat system can now:
* Trigger real backend agent services directly from LLM tool calls
* Return live session URLs
* Maintain structured multi-agent responses
* Avoid Rivet runtime conflicts
* Support end-to-end conversational workflows across all 4 agents
Reviewed-on: puter/growqr-backend#3
Co-authored-by: NinjasPyajamas <divyansh242805@gmail.com>
Co-committed-by: NinjasPyajamas <divyansh242805@gmail.com>
This commit is contained in:
@@ -19,8 +19,33 @@ services:
|
||||
retries: 10
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Central Gitea (one org-wide instance, changes.md §2A) ──
|
||||
# Every user gets a repo inside the GrowQR organization on this instance.
|
||||
# Per-user Gitea containers are REMOVED — the backend no longer spawns them.
|
||||
gitea:
|
||||
image: gitea/gitea:1.22
|
||||
container_name: growqr-gitea
|
||||
environment:
|
||||
USER_UID: "1000"
|
||||
USER_GID: "1000"
|
||||
GITEA__server__ROOT_URL: http://localhost:3001
|
||||
GITEA__server__SSH_PORT: "2222"
|
||||
GITEA__security__INSTALL_LOCK: "true"
|
||||
GITEA__service__DISABLE_REGISTRATION: "true"
|
||||
ports:
|
||||
- "3001:3000" # HTTP (Gitea listens on 3000 internally)
|
||||
- "2222:2222" # SSH
|
||||
volumes:
|
||||
- gitea-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://localhost:3000/api/v1/version || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
restart: unless-stopped
|
||||
|
||||
# Self-hosted Rivet engine. The backend's Rivet Kit client connects here.
|
||||
# Per the PRD, the Grow Agent + sub-agents are durable actors running on Rivet.
|
||||
# The unified user agent runs as a durable Rivet actor (changes.md §5).
|
||||
rivet-engine:
|
||||
image: rivetgg/engine:latest
|
||||
container_name: growqr-rivet
|
||||
@@ -34,7 +59,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
# The HTTP backend (Hono + Rivet Kit client + Docker manager).
|
||||
# Mounts the host Docker socket so it can spawn per-user containers.
|
||||
# Mounts the host Docker socket so it can spawn per-user OpenCode containers.
|
||||
backend:
|
||||
build:
|
||||
context: .
|
||||
@@ -43,6 +68,8 @@ services:
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
gitea:
|
||||
condition: service_healthy
|
||||
rivet-engine:
|
||||
condition: service_started
|
||||
ports:
|
||||
@@ -51,22 +78,45 @@ services:
|
||||
PORT: 4000
|
||||
NODE_ENV: ${NODE_ENV:-production}
|
||||
DATABASE_URL: postgres://${POSTGRES_USER:-growqr}:${POSTGRES_PASSWORD:-growqr}@postgres:5432/${POSTGRES_DB:-growqr}
|
||||
# Central Gitea (shared org-wide instance)
|
||||
GITEA_URL: http://gitea:3001
|
||||
GITEA_ADMIN_USER: ${GITEA_ADMIN_USER:-growqr-admin}
|
||||
GITEA_ADMIN_PASSWORD: ${GITEA_ADMIN_PASSWORD:-growqr-admin-dev}
|
||||
GITEA_ADMIN_TOKEN: ${GITEA_ADMIN_TOKEN:-}
|
||||
GITEA_ORG_NAME: ${GITEA_ORG_NAME:-growqr}
|
||||
# Version tracking for image rollouts (changes.md §9)
|
||||
OPENCODE_IMAGE_VERSION: ${OPENCODE_IMAGE_VERSION:-1.0.0}
|
||||
MIGRATION_VERSION: ${MIGRATION_VERSION:-1}
|
||||
PROMPT_VERSION: ${PROMPT_VERSION:-1}
|
||||
# Rivet
|
||||
RIVET_ENDPOINT: http://rivet-engine:6420
|
||||
RIVET_CLIENT_ENDPOINT: ${RIVET_CLIENT_ENDPOINT:-http://127.0.0.1:4000/api/rivet}
|
||||
# Auth
|
||||
CLERK_SECRET_KEY: ${CLERK_SECRET_KEY}
|
||||
CLERK_PUBLISHABLE_KEY: ${CLERK_PUBLISHABLE_KEY}
|
||||
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
||||
GROW_AGENT_MODEL: ${GROW_AGENT_MODEL:-claude-opus-4-7}
|
||||
SUB_AGENT_MODEL: ${SUB_AGENT_MODEL:-claude-sonnet-4-6}
|
||||
SERVICE_TOKEN: ${SERVICE_TOKEN:-dev-service-token}
|
||||
GITEA_IMAGE: ${GITEA_IMAGE:-gitea/gitea:1.22}
|
||||
OPENCODE_IMAGE: ${OPENCODE_IMAGE:-ghcr.io/sst/opencode:latest}
|
||||
A2A_ALLOWED_KEY: ${A2A_ALLOWED_KEY:-dev-a2a-key}
|
||||
# LLM
|
||||
OPENCODE_API_KEY: ${OPENCODE_API_KEY}
|
||||
LLM_PROVIDER: ${LLM_PROVIDER:-opencode}
|
||||
LLM_BASE_URL: ${LLM_BASE_URL:-https://opencode.ai/zen/v1}
|
||||
LLM_MODEL: ${LLM_MODEL:-kimi-k2.6}
|
||||
GROW_AGENT_MODEL: ${GROW_AGENT_MODEL:-kimi-k2.6}
|
||||
# Per-user OpenCode containers
|
||||
OPENCODE_IMAGE: ${OPENCODE_IMAGE:-ghcr.io/anomalyco/opencode:latest}
|
||||
USER_CONTAINER_HOST: ${USER_CONTAINER_HOST:-host.docker.internal}
|
||||
USER_DATA_ROOT: /data/users
|
||||
USER_PORT_RANGE_START: 20000
|
||||
USER_PORT_RANGE_END: 29999
|
||||
# Microservices
|
||||
INTERVIEW_SERVICE_URL: ${INTERVIEW_SERVICE_URL:-http://host.docker.internal:8007}
|
||||
ROLEPLAY_SERVICE_URL: ${ROLEPLAY_SERVICE_URL:-http://host.docker.internal:8008}
|
||||
QSCORE_SERVICE_URL: ${QSCORE_SERVICE_URL:-http://host.docker.internal:8000}
|
||||
RESUME_SERVICE_URL: ${RESUME_SERVICE_URL:-http://host.docker.internal:8002}
|
||||
# Frontend
|
||||
FRONTEND_ORIGIN: ${FRONTEND_ORIGIN:-http://localhost:3000}
|
||||
volumes:
|
||||
# Docker-out-of-Docker: backend uses host Docker to spawn user containers.
|
||||
# Docker-out-of-Docker: backend uses host Docker to spawn per-user OpenCode containers.
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
# Shared host dir that per-user containers will also bind-mount their
|
||||
# workspace from (so backend and spawned containers see the same files).
|
||||
@@ -78,10 +128,11 @@ services:
|
||||
retries: 6
|
||||
restart: unless-stopped
|
||||
|
||||
# Note: per-user OpenCode + Gitea containers are NOT defined here.
|
||||
# The backend spawns them dynamically via dockerode on /actors/provision.
|
||||
# See src/docker/manager.ts.
|
||||
# Only per-user OpenCode containers are spawned dynamically now.
|
||||
# Gitea is a central shared service defined above.
|
||||
# See src/docker/manager.ts for the per-user OpenCode lifecycle.
|
||||
|
||||
volumes:
|
||||
rivet-data:
|
||||
postgres-data:
|
||||
gitea-data:
|
||||
|
||||
Reference in New Issue
Block a user