Files
growqr-backend/README.md
NinjasPyajamas 9ddbb4a8e5 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>
2026-06-01 09:26:19 +00:00

117 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GrowQR — backend + frontend
A multi-agent platform where every user gets a private Grow Agent (Rivet Kit actor) that orchestrates sub-agents and owns a per-user OpenCode + Gitea Docker stack. See `docs/PRD.md` for the product spec.
## What's wired up
- **Auth**: Clerk (frontend + backend JWT verification).
- **DB**: Postgres + Drizzle (users, actor registry, container mappings, repos, OpenCode sessions, events).
- **Actors**: Rivet Kit — `growAgent` per user (master) and `subAgent` (worker), with a real OpenCode Zen / OpenAI-compatible tool-use loop.
- **Per-user containers**: Gitea (memory repo) + OpenCode (workflow execution), spawned via `dockerode`, with admin user + access token bootstrap, ports allocated from a managed pool, lifecycle reconciled on backend boot.
- **Frontend**: Next.js 16 with `@clerk/nextjs` for auth and `rivetkit/client` for direct actor connections + event streaming.
- **Tool surface available to the Grow Agent**: `spawn_sub_agent`, `commit_memory`, `read_memory`, `list_memory`.
## One-time setup
You need three external accounts before running:
1. **Clerk** — create an app at https://dashboard.clerk.com → copy the publishable + secret keys.
2. **OpenCode Zen** — create an API key at https://opencode.ai/auth.
3. **Docker** — Docker Desktop (or any daemon `dockerode` can reach via `/var/run/docker.sock`).
Then:
```bash
# Backend env
cp .env.example .env
# fill in CLERK_SECRET_KEY, CLERK_PUBLISHABLE_KEY, OPENCODE_API_KEY
# Frontend env
cd growqr-frontend
cp .env.example .env.local
# fill in NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY
cd ..
```
## Running
```bash
# 1. Start Postgres + Rivet engine (per-user OpenCode/Gitea containers are
# spawned dynamically by the backend when a user signs in).
docker compose up -d postgres rivet-engine
# 2. Install + migrate
npm install
npm run db:migrate
# 3. Backend
npm run dev # http://localhost:4000
# 4. Frontend (separate terminal)
cd growqr-frontend
npm install
npm run dev # http://localhost:3000
```
Open http://localhost:3000, sign up, verify your email, and the home page will:
1. Mirror your Clerk user into Postgres.
2. Spawn your dedicated Gitea + OpenCode containers (first run pulls images — ~2040s).
3. Connect the Grow Agent chat to your dedicated Rivet actor.
4. Stream agent + sub-agent events back to the UI.
## Architecture
```
Browser
│ Clerk JWT
Next.js (3000) ──fetch──▶ /users/bootstrap, /users/me (Hono on 4000)
└─Rivet client──▶ /api/rivet/* (Hono → registry.handler)
Grow Agent actor (one per user)
├─ OpenCode Zen (Kimi K2.6 + tool use)
├─ commit_memory ────▶ Gitea container (per user)
└─ spawn_sub_agent ────▶ OpenCode container (per user)
(multiplexed sessions)
```
## Useful commands
```bash
npm run typecheck # backend
npm run db:generate # diff schema → new migration
npm run db:studio # browse Postgres via Drizzle Studio
cd growqr-frontend
npx tsc --noEmit # frontend types
npm run lint
```
## Troubleshooting
- **"missing bearer token"** from `/users/bootstrap` — Clerk session not attached. Sign out and back in.
- **`Gitea did not become ready`** during provisioning — Gitea takes 1020s on first pull. Wait, then `POST /actors/provision` (the frontend retries via polling).
- **OpenCode container exits immediately** — check `OPENCODE_IMAGE`. The compose env passes `Cmd: ["serve", ...]`; if you swap to a different image, ensure it exposes the `opencode serve` HTTP surface on `:4096`.
- **`No free ports in USER_PORT_RANGE`** — bump `USER_PORT_RANGE_END` in `.env` or stop unused user stacks via `POST /actors/stop`.
## PRD status
All MVP items in `docs/PRD.md` §9 are implemented:
- [x] User auth (Clerk)
- [x] Actor registry (Postgres + Rivet)
- [x] One Grow Agent Rivet Kit actor per user
- [x] Sub-agent registration under the Grow Agent
- [x] Per-user Gitea Docker + memory repo
- [x] Memory commits into the user's Gitea
- [x] Per-user OpenCode Docker + session API
- [x] Message endpoint from frontend to Grow Agent (via Rivet)
- [x] Event stream from agent to frontend (via Rivet broadcast)
- [x] Frontend: login, master chat, sub-agent progress, channel-style logs
Payments and the full quest/pathway runner are deferred to v2 (PRD §10).