Files
gochat/AGENTS.md
T
2026-08-22 21:20:11 +08:00

8.3 KiB

AGENTS.md — GoChat

Guidance for AI coding agents (and humans pairing with them) working in this repository.

Repository Layout

This is a monorepo with a clear separation between backend code, deployment artifacts, and documentation:

backend/      # Go backend (the Go module lives here)
  cmd/        # Entry points: gochat (server/seed), migrate, route_parity, ...
  internal/   # App logic: handler, service, repository, model, config, ws, ...
  pkg/        # Reusable packages: crypto, logger, pagination, response, ...
  configs/    # Viper config files (config.yaml + config.{env}.yaml)
  migrations/ # golang-migrate SQL files (sequential, .up.sql / .down.sql)
  docs/       # swaggo-generated Swagger Go package (imported by the router)
  scripts/    # migrate.sh, seed.sh, health_check.sh, route-parity tooling
  tests/      # e2e tests + test helpers
frontend/     # Chatwoot Vue 3 frontend (vendored for customization)
  app/javascript/   # Vue SPA source (dashboard, widget, sdk, portal, superadmin)
  package.json      # pnpm + Vite + Vue 3 toolchain
deploy/       # Deployment artifacts
  docker/     # Dockerfile, Dockerfile.dev, docker-compose.{yml,dev,prod,test}.yml
  quickstart/ # One-shot local/UAT Compose stack (PG+pgvector+Redis+Meilisearch+Mailhog)
  fluentd/    # Log shipping config
docs/         # Project documentation (architecture, requirements, plans, reports)
  chatwoot/   # Upstream Chatwoot source snapshot; primary behavioral reference

The Go module root is backend/ — run all go commands from there. Build context for Docker is the repository root (.), not backend/.

Upstream Chatwoot Reference (Required)

GoChat is a Go-language translation and port of Chatwoot. When a behavior, API contract, data model, event payload, frontend interaction, or edge case is unclear or appears incorrect, inspect the upstream implementation under docs/chatwoot/ before designing or changing the GoChat solution.

  • Trace the complete upstream path first: controller/handler → service/builder → model callback → serializer → frontend consumer.
  • Preserve Chatwoot's externally visible behavior and payload contracts when translating Rails/Ruby implementation details into GoChat's layered Go architecture.
  • Reuse the upstream fix pattern and regression cases where practical instead of inventing a parallel behavior from the current Go code alone.
  • Treat docs/chatwoot/ as read-only reference code. Production changes belong in backend/, frontend/, or other GoChat-owned directories.
  • If GoChat intentionally diverges from Chatwoot, document the reason, affected contract, and verification coverage in the change.

Build & Test Commands

All Go commands run from backend/:

cd backend

# Build
go build ./...                      # compile everything
make build                          # build ./cmd/gochat → bin/gochat

# Run
go run cmd/gochat/main.go serve     # API server (default subcommand)
go run cmd/gochat/main.go seed      # seed demo data

# Test
go test ./...                       # all tests
GOCHAT_TEST_DB=sqlite go test ./internal/... ./pkg/... ./cmd/...  # no PG needed
go test -v -race ./...              # with race detector
go test -v ./tests/e2e/...          # e2e

# Static analysis
go vet ./...

Docker (build context = repo root, Dockerfile in deploy/docker/):

# Quickstart stack from repo root
cd deploy/quickstart && cp .env.example .env && docker compose up -d --build

# Build image manually from backend/
make docker

Go Version & Tooling

  • Go: 1.24+ (go.mod declares 1.24.0). Toolchain: go1.24.4.
  • HTTP: Gin v1.10
  • ORM: GORM v2
  • DB: PostgreSQL 16 + pgvector (SQLite supported for tests via GOCHAT_TEST_DB=sqlite)
  • Config: Viper (multi-env overlay: config.yamlconfig.{env}.yaml.env)
  • Swagger: swaggo/swag — generated docs live in backend/docs/ (a Go package imported by internal/router); do not move them out of the module.

Code Style & Conventions

  • Tabs for Go/Makefile; 2-space for YAML/JSON/TOML (see .editorconfig).
  • Match existing patterns in the surrounding code — do not reformat unrelated files.
  • Layered architecture: handler → service → repository → model. Respect layer boundaries; don't call repositories directly from handlers.
  • PG-only features (pgvector search, etc.) must guard with skipIfSQLite so SQLite test mode stays green.
  • New DB schema changes go through numbered SQL migrations in backend/migrations/ (NNNNN_name.{up,down}.sql).

Configuration

  • Config files: backend/configs/config.yaml (base) + config.dev.yaml (development overlay) / backend/configs/config.production.yaml (production overlay).
  • Viper search paths: ./configs, ./, /etc/gochat/.
  • Runtime config dir is resolved from the base config's location, so env overlays load from the same dir automatically.
  • Secrets/.env are gitignored — never commit them.

Deployment Notes

  • The production Dockerfile (in deploy/docker/) uses repo root as build context and COPY backend/ for sources. When adding files the image needs, place them under backend/ or update the COPY directives.
  • docker-compose*.yml files in deploy/docker/ use context: ../.. (repo root) and dockerfile: deploy/docker/Dockerfile.

Frontend (Chatwoot Vue 3 — decoupled)

The frontend/ directory contains the Chatwoot frontend (v4.14.0) vendored and decoupled from Rails. It is now a standalone Vite + Vue 3 SPA that talks directly to the GoChat Go backend. No Ruby/Rails required.

What was removed: vite-plugin-ruby, Gemfile, config/ (Rails), bin/ (Ruby binstubs), app/views/ (ERB templates), app/helpers/, enterprise/ (Ruby-only), Procfile*, and all Rails config/lint/test infrastructure.

What was kept: app/javascript/ (all Vue SPA source), package.json, vite.config.ts, tailwind.config.js, postcss.config.js, theme/, vitest.setup.js, .prettierrc.

Key decoupling changes:

  • vite.config.ts rewritten: removed vite-plugin-ruby, added explicit rollupOptions.input for all 7 entrypoints + dev-server proxy to GoChat API.
  • index.html created at frontend root: static HTML that injects window.chatwootConfig / window.globalConfig (previously done by Rails ERB).
  • package.json: renamed to @gochat/frontend, removed vite-plugin-ruby / histoire / husky deps, scripts now use plain vite dev / vite build.
# From repo root — unified dev workflow
pnpm install              # install all workspace deps
pnpm dev:backend          # start Go backend (air hot-reload, port 3000)
pnpm dev:frontend         # start Vite dev server (port 5000, proxies API to :3000)
pnpm dev                  # start both concurrently

# Frontend-only (from frontend/)
cd frontend && pnpm dev   # vite dev server
cd frontend && pnpm build # production build → frontend/dist/

The Vite dev server proxies /api, /platform, /cable, /health to the GoChat backend (default http://127.0.0.1:3000, override with VITE_API_HOST).

For parity smoke testing, see backend/scripts/parity_frontend_smoke.sh. Default CHATWOOT_DIR points to ../frontend.

Things to Avoid

  • Do not move backend/docs/*.go — they are a compiled Go package imported by the router.
  • Do not add Go files to backend/scripts/legacy/ expecting them to be excluded — go build ./... compiles them; keep that directory for one-off scripts only.
  • Do not commit .env, coverage.out, bin/, or tmp/.
  • Do not rewrite git history or force-push without explicit instruction.

CodeGraph

In repositories indexed by CodeGraph (a .codegraph/ directory exists at the repo root), reach for it BEFORE grep/find or reading files when you need to understand or locate code:

  • MCP tool (when available): codegraph_explore answers most code questions in one call — the relevant symbols' verbatim source plus the call paths between them, including dynamic-dispatch hops grep can't follow. Name a file or symbol in the query to read its current line-numbered source. If it's listed but deferred, load it by name via tool search.
  • Shell (always works): codegraph explore "<symbol names or question>" prints the same output.

If there is no .codegraph/ directory, skip CodeGraph entirely — indexing is the user's decision.