96 lines
3.7 KiB
Markdown
96 lines
3.7 KiB
Markdown
# AGENTS.md — Gadget Code Monorepo
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
gadget/
|
|
├── packages/ai/ @gadget/ai — AI API abstraction (source of truth)
|
|
├── gadget-code/ Web service + browser IDE
|
|
├── gadget-drone/ Worker process (agentic workflow loop)
|
|
└── pnpm-workspace.yaml Monorepo workspace definition
|
|
```
|
|
|
|
## 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
|
|
|
|
```bash
|
|
pnpm install # Install all workspace packages
|
|
pnpm -r build # Build all packages
|
|
pnpm --filter @gadget/ai build
|
|
pnpm --filter gadget-drone build
|
|
pnpm --filter gadget-code build:backend
|
|
pnpm --filter gadget-code dev
|
|
pnpm --filter gadget-drone dev
|
|
```
|
|
|
|
## Key Conventions
|
|
|
|
- All packages are **ES modules** (`"type": "module"`).
|
|
- `@gadget/ai` uses `moduleResolution: NodeNext` and emits to `dist/`.
|
|
- gadget-drone uses `moduleResolution: NodeNext`.
|
|
- gadget-code uses `moduleResolution: bundler` with `@/*` path aliases.
|
|
- Dependency versions are pinned in `package.json` — no ranges. Use the workspace protocol (`workspace:*`) for internal package references.
|
|
- pnpm version is enforced at the workspace root (`packageManager` field).
|
|
|
|
## TypeScript Strictness
|
|
|
|
| Package | Strictness |
|
|
| ------------ | ---------------------------------------------------------------------------------- |
|
|
| `@gadget/ai` | `strict: true` |
|
|
| gadget-drone | `strict: true` |
|
|
| gadget-code | `strict: true`, `noUnusedLocals`, `noUnusedParameters`, `noUncheckedIndexedAccess` |
|
|
|
|
## Adding Code
|
|
|
|
When adding a new feature or service, determine its scope:
|
|
|
|
- **Shared AI concern** (AI logging, config schema) → goes in `@gadget/ai`
|
|
- **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 `@gadget/ai`. Do not copy-paste shared logic across packages.
|
|
|
|
## GadgetId
|
|
|
|
All entity IDs use the `GadgetId` type (a string alias) defined in `@gadget/api`. This eliminates MongoDB `ObjectId` conversion throughout the codebase.
|
|
|
|
### Interfaces
|
|
|
|
Always specify `{ _id: GadgetId }` in interfaces:
|
|
|
|
```ts
|
|
import { GadgetId } from "@gadget/api";
|
|
|
|
interface IMyEntity {
|
|
_id: GadgetId;
|
|
// ... other fields
|
|
}
|
|
```
|
|
|
|
### Mongoose Schemas
|
|
|
|
Always use this pattern for `_id`:
|
|
|
|
```ts
|
|
_id: { type: String, default: () => nanoid() }
|
|
```
|
|
|
|
**Never add `unique: true` or `required: true` to `_id`**:
|
|
- `unique: true` causes duplicate index errors at startup (MongoDB auto-creates a unique index on `_id`)
|
|
- `required: true` causes save failures because the default is assigned AFTER validation
|
|
|
|
### Rules
|
|
|
|
1. All `_id` fields are `GadgetId` (string)
|
|
2. No `ObjectId` usage in application code
|
|
3. No `createFromHexString()` or `toHexString()` conversions
|
|
4. Never `unique` or `required` on `_id` in schemas
|