gadget/AGENTS.md
Rob Colbert 5228034a5f fixes
2026-05-13 06:38:29 -04:00

5.2 KiB

AGENTS.md — Gadget Code Monorepo

Project Structure

gadget/
├── packages/
│   ├── ai/          @gadget/ai — AI API abstraction (Ollama + OpenAI)
│   ├── api/         @gadget/api — Shared TypeScript interfaces
│   └── config/     @gadget/config — Env config loader
├── gadget-code/          Web service — Express 5, React 19, browser IDE
│   └── frontend/         Frontend SPA — Vite 8 + React 19 (workspace member)
└── gadget-drone/         Worker process — Agentic workflow loop

Rules for AI Code

The ecosystem speaks one AI API language defined by @gadget/ai. All rules apply to every consumer:

  1. No direct SDK imports. Never import { Ollama } from "ollama" or import OpenAI from "openai" outside packages/ai/src/.
  2. No provider.sdk checks outside the factory. The factory in packages/ai/src/index.ts routes to the correct implementation. After createAiApi(), the caller holds an AiApi and never checks which SDK backs it.
  3. All AI interfaces live in @gadget/ai. Do not re-declare IAiProvider, IAiChatResponse, etc. in consumer packages. Import them from @gadget/ai.
  4. Adding a new provider means implementing AiApi in packages/ai/src/ and registering it in the factory. Nothing else changes.

Dev Commands

pnpm install              # Install all workspace packages
pnpm -r build             # Build all packages

# Per-package build
pnpm --filter @gadget/ai build
pnpm --filter @gadget/api build
pnpm --filter @gadget/config build
pnpm --filter gadget-code build:backend    # backend → dist/ + resolves @/* aliases
pnpm --filter gadget-drone build
pnpm --filter gadget-code-frontend build  # frontend → dist/client/

# Run dev servers
pnpm --filter gadget-code dev              # Backend on https://localhost:3443
pnpm --filter gadget-drone dev             # Drone worker
pnpm --filter gadget-code-frontend dev     # Frontend on https://localhost:5174

# Typecheck
pnpm --filter @gadget/ai typecheck  # Only package with a typecheck script

Key Conventions

  • All packages are ES modules ("type": "module").
  • @gadget/ai, @gadget/api, @gadget/config use moduleResolution: NodeNext and emit to dist/.
  • gadget-drone uses moduleResolution: NodeNext.
  • gadget-code and gadget-code/frontend use moduleResolution: bundler with @/* path aliases → src/*.
  • gadget-code build requires tsc-alias to resolve @/* path aliases in output.
  • Dependency versions are pinned in package.json — no ranges. Use the workspace protocol (workspace:*) for internal package references.
  • pnpm version enforced at the workspace root (packageManager field).
  • No lint scripts exist in any package.

TypeScript Strictness

Package Strictness
@gadget/ai strict: true
@gadget/api strict: true
@gadget/config strict: true
gadget-drone strict: true
gadget-code strict: true, noUnusedLocals, noUnusedParameters, noUncheckedIndexedAccess
gadget-code/frontend strict: true (included via workspace)

GadgetId

All entity IDs use GadgetId (a string alias) from @gadget/api. Never use ObjectId.

import { GadgetId } from "@gadget/api";

interface IMyEntity {
  _id: GadgetId;
}

Mongoose schema pattern:

_id: { type: String, default: () => nanoid() }

Never add unique: true or required: true to _id: MongoDB auto-creates a unique index on _id (causes duplicate index errors if unique is also set), and the default is assigned after validation (causes save failures if required is set).

See gadget-code/docs/gadget-id.md for full documentation.

Testing

  • gadget-code: Vitest unit tests (pnpm test). Vitest config excludes tests/e2e/.
  • E2E tests: Playwright targets https://code-dev.g4dge7.com:5174 (requires running dev servers).
  • Seed test drones: cd gadget-code && npx tsx scripts/seed-test-drones.ts
  • gadget-drone: No tests configured.

Adding Code

When adding a new feature or service, determine its scope:

  • Shared AI concern (AI logging, config schema) → goes in @gadget/ai
  • Shared types → goes in @gadget/api
  • Config loading → goes in @gadget/config
  • Drone-only (Bull queue, workspace file operations) → goes in gadget-drone
  • Web-only (Express routes, Mongoose models, session management) → goes in gadget-code

If code is needed by both consumer packages, it belongs in the appropriate shared package. Do not copy-paste shared logic across packages.

Prerequisites

  • Node.js 22+
  • pnpm (version enforced at root packageManager field)
  • MongoDB on localhost:27017
  • Redis on localhost:6379
  • SSL certificates in gadget-code/ssl/ directory (for dev servers)