This is a pnpm + Turborepo monorepo (TypeScript serving layer) plus a uv-managed
Python ingestion engine (engine/). Run pnpm install at the root and uv sync
in engine/ before starting. uv installs to ~/.local/bin; in a fresh
non-login shell run export PATH="$HOME/.local/bin:$PATH" if uv is not found.
@orca/api(Next.js 16 dev server) — the product runtime serving/v1/chat,/v1/search, and the/playgroundUI. Run withpnpm --filter @orca/api dev(pinned tohttp://localhost:3000). Boots fine with no secrets: env vars are optional and the DB client is lazy.@orca/web(Next.js 16 admin console) — better-auth dashboard for tenant settings, usage/activity, knowledge sources, and feedback. Run withpnpm --filter @orca/web dev(pinned tohttp://localhost:3001so it can run alongside@orca/api). Backed by the same Neon DB via@orca/db.- Python ingestion engine (
engine/) — not a long-running service. Run connectors viauv run engine ingest <connector> [--source-dir DIR] [--dry-run]fromengine/.--dry-run(or simply having noDATABASE_URL) uses an in-memoryDryRunWriter, so it parses/chunks docs with no DB or API key.
- External secrets gate the live answer path.
AI_GATEWAY_API_KEY(Vercel AI Gateway, routes embeddings/rerank/generation) andDATABASE_URL(Neon serving role) are required for/v1/chatand/v1/searchto return grounded answers. Without them, the server still runs and the request flows through the real request-gate → router → agent loop, then fails loud atrequireEnv(...). The deterministic safety path (advice-refusal guardrail) works with no secrets. - The Neon serving role must be non-owner + NOBYPASSRLS.
DATABASE_URLis the serving connection andADMIN_DATABASE_URLis the owner role (migrations/role setup only). Using the owner role for serving makes RLS tenant isolation a no-op;assertServingRolefails loud at boot to catch this. - The
@orca/dbNeon driver uses the WebSocket sessionPool(not the HTTP endpoint) becauseSET LOCALmust hold across the tenant transaction. docs_mdx/openapiconnectors default to a siblingboardwalk-landingrepo that is NOT in this repo. For a no-credential ingestion demo, point them at the committed fixtures, e.g.uv run engine ingest docs_mdx --source-dir tests/fixtures/docs_mdx/input --dry-run.- Tests need no external services. TS tests use
@electric-sql/pglite(in-memory Postgres); Python tests run offline.pyproject.tomlsetsfilterwarnings = ["error"], so any new warning fails the Python suite. - The Python
evals(Ragas/DeepEval) andpdf(Docling/torch) dependency groups are heavy and intentionally excluded fromuv sync; install on demand withuv sync --group evals/--group pdfonly when needed.
Standard commands (see root package.json and README.md):
- Typecheck:
pnpm -r typecheck - TS tests:
pnpm -r test - Lint + format (Biome):
pnpm lint:ciis what CI runs;pnpm lint:fix/pnpm formatto auto-fix locally. - Build (widget IIFE + both Next apps, turbo-cached):
pnpm build - Tenant-access lint (tenant tables only reachable via
withTenant):node scripts/lint-tenant-access.mjs - Python tests:
cd engine && uv run pytest; lint:uv run ruff check .anduv run ruff format --check .