Skip to content

Latest commit

 

History

History
189 lines (146 loc) · 10.6 KB

File metadata and controls

189 lines (146 loc) · 10.6 KB

Contributing

Prerequisites

  • Node.js >=20.0.0 (see root package.json engines.node)
  • pnpm 9.15.0 (see root packageManager)
  • Docker Engine 24+ with the Compose v2 plugin

Recommended editor extensions: ESLint, Prettier.

Verify the toolchain in one pass:

pnpm install && pnpm types:check && pnpm lint

Running locally

  1. docker compose up -d
  2. cp .env.example .env
  3. Set at minimum: OPENAI_API_KEY, absolute AURIS_DATA_PATH pointing at packages/workers/seeds/inbox, AURIS_CHROMA_URL=http://127.0.0.1:8000, and ELASTICSEARCH_URL=http://127.0.0.1:9200 when AURIS_SPARSE_SEARCH uses Elasticsearch.
  4. pnpm dev — boots Express on PORT (defaults to 3000) with file watching via tsx.
  5. pnpm data:seed — scans AURIS_DATA_PATH for files matching DATA_SOURCE extensions, streams documents, and runs indexRawDocuments with hash-based skips.
  6. Confirm retrieval:
curl -s -X POST http://127.0.0.1:3000/v1/query \
  -H 'content-type: application/json' \
  -d '{"query":"What soil pH does watermelon prefer?"}'

Expect JSON shaped like { "answer": string, "citations": [...], "confidence": number, "traceId": string, "pipeline": { ... } }.

Running tests

  • pnpm test — runs Vitest unit suites (pure functions, pipelines, and adapters with mocks).
  • pnpm test:integration — runs the Vitest config reserved for *.integration.test.ts files (currently none; exits successfully with passWithNoTests).
  • pnpm docker:up && pnpm dev (in a second terminal) then curl -s http://127.0.0.1:3000/v1/health — manual smoke against real containers until automated API integration tests are added.

Evaluation package:

pnpm --filter @auris/evaluation run eval:golden

Compiles the evaluation package, loads evaluation/golden/golden-set.json from the repository root (override with GOLDEN_SET_PATH), and prints a short JSON summary.

Scripts reference (root)

Script What it does When to use it
pnpm dev API watch mode (@auris/api) Daily backend work
pnpm dev:workers Workers package CLI in dev mode Worker-only changes
pnpm build tsc build for every workspace package Before release or Docker-less runs
pnpm build:api Build @auris/api only Narrow API compile check
pnpm types:check tsc --noEmit in all packages CI and pre-push
pnpm lint ESLint across packages Style and correctness gate
pnpm lint:fix ESLint with --fix Auto-fix safe violations
pnpm fmt:write Prettier write for the repo Format everything
pnpm fmt:check Prettier check (no writes) CI formatting gate
pnpm test Vitest run once Default test entry
pnpm test:watch Vitest watch Tight feedback loop
pnpm test:coverage Vitest with coverage thresholds Before merging risky changes
pnpm docker:up docker compose up -d Start Chroma and Elasticsearch
pnpm docker:down docker compose down Stop containers
pnpm docker:down:volumes docker compose down -v Wipe named volumes
pnpm docker:logs Follow all Compose logs Debugging services
pnpm docker:logs:chroma Follow Chroma logs Vector-store issues
pnpm docker:logs:search Follow Elasticsearch logs Sparse-index issues
pnpm docker:ps docker compose ps Check container state
pnpm docker:restart Restart every Compose service Recover stuck deps
pnpm docker:restart:chroma Restart Chroma only Targeted vector recycle
pnpm docker:restart:search Restart Elasticsearch only Targeted sparse recycle
pnpm docker:pull Pull Compose images Refresh base images
pnpm docker:build docker compose build Rebuild the optional API image
pnpm docker:reset down -v then up Clean slate for local data
pnpm data:seed Build shared then run the indexing worker After .env changes
pnpm data:seed:dry-run Same as seed with --dry-run Count documents without writing
pnpm repo:clean Remove package dist/ folders and root node_modules Nuclear local reset
pnpm repo:setup install + docker:up + types:check Fresh clone bootstrap
pnpm api:health curl + jq against /v1/health Quick API readiness (needs curl and jq)

Workspace packages expose build:tsc, types:check, lint:check, lint:fix, and clean:dist (plus package-specific scripts such as dev:watch on @auris/api). Run them with pnpm --filter <name> run <script>.

How to add a new adapter

Concrete walkthrough: adding an Acme LLM provider.

  1. Locate LLMProvider in packages/core/src/ports/llm-provider.ts and copy the interface into your editor while implementing the adapter.

  2. Create packages/infra/src/llm/acme-llm-provider.ts with a class that implements the interface (mirror OpenAiLlmProvider).

import type {
  ChatMessage,
  CompletionOptions,
  CompletionResult,
  LLMProvider,
  PipelineContext,
} from "@auris/core";

export class AcmeLlmProvider implements LLMProvider {
  readonly modelId = "acme-turbo";

  constructor(private readonly apiKey: string) {}

  async complete(
    messages: readonly ChatMessage[],
    options: CompletionOptions,
    ctx: PipelineContext,
  ): Promise<CompletionResult> {
    void messages;
    void options;
    void ctx;
    void this.apiKey;
    return {
      text: "pong",
      promptTokens: 1,
      completionTokens: 1,
      model: this.modelId,
    };
  }
}
  1. Register the adapter inside createLlm in packages/infra/src/wiring/composition.ts by importing AcmeLlmProvider and inserting a branch before the existing gpt_4o handling.
import { AcmeLlmProvider } from "../llm/acme-llm-provider.js";

if (config.providers.llm === "acme_turbo") {
  return new AcmeLlmProvider(config.acmeApiKey ?? "");
}
  1. Extend packages/shared/src/config/schema.ts with any new secrets or enums (for example add "acme_turbo" to the providers.llm enum and acmeApiKey: z.string().optional() on appConfigSchema), then map them through packages/shared/src/config/load-config.ts with envString("ACME_API_KEY").

  2. Add packages/infra/src/llm/acme-llm-provider.test.ts.

import { describe, it, expect } from "vitest";
import { StubLlmProvider } from "./stub-llm-provider.js";

describe("LLM provider harness", () => {
  it("documents the reject path for unconfigured models", async () => {
    const llm = new StubLlmProvider("gpt-4o");
    await expect(llm.complete([], { maxOutputTokens: 8 }, { traceId: "t" })).rejects.toThrow(
      /not configured/,
    );
  });
});

Swap StubLlmProvider for AcmeLlmProvider once your HTTP client is mockable.

How to add a new data source

  1. Implement the DataSourceProvider port from packages/core/src/data-sources/DataSourceProvider.ts (see LocalFilesDataSourceProvider under packages/infra/src/data-sources/local-files/ for a filesystem example).

  2. Register the provider inside resolveDataSourceProvider in packages/infra/src/data-sources/registry.ts, wiring any new configuration through packages/shared/src/config/schema.ts and packages/shared/src/config/load-config.ts.

  3. Add focused unit tests next to the adapter and extend packages/infra/src/data-sources/registry.test.ts when registration rules change.

  4. Document required environment variables beside the adapter and update .env.example when new secrets or paths are introduced.

Commit conventions

Conventional Commits.

Type When to use Example
feat User-visible capability feat: add catalog feed data source
fix Bug fix fix: guard empty sparse responses
docs Documentation only docs: expand architecture overview
refactor Internal change, same behavior refactor: extract tracing helpers
test Tests only test: cover rrf tie handling
chore Tooling or maintenance chore: bump vitest
perf Measurable speedup perf: batch embedding calls

Pull request checklist

  • Linked issue or rationale is described in the PR body.
  • pnpm lint passes locally.
  • pnpm types:check passes locally.
  • pnpm test passes locally.
  • New adapters include README notes for required environment variables.
  • Configuration changes update config/default.yaml, .env.example, or both.
  • Sensitive values never appear in commits or logs.
  • Documentation reflects behavior changes in README.md or ARCHITECTURE.md.