From f1b5a560a38447e0f18ec972387def34bfdfea90 Mon Sep 17 00:00:00 2001 From: Rob Colbert Date: Tue, 28 Apr 2026 11:49:21 -0400 Subject: [PATCH] documentation updates; AI classes renamed We now have AiApi, OllamaAiApi, and OpenAiApi. Documentation updates to provide a bit more high-level clarity that was originally generated by the agent. --- AGENTS.md | 14 +++++++------- README.md | 32 ++++++++++++++++++++++++++------ packages/ai/README.md | 8 ++++---- packages/ai/src/index.ts | 14 +++++++------- packages/ai/src/ollama.ts | 10 +++++----- packages/ai/src/openai.ts | 6 +++--- 6 files changed, 52 insertions(+), 32 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 9c922ef..7fe655a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -42,18 +42,18 @@ pnpm --filter gadget-drone dev ## TypeScript Strictness -| Package | Strictness | -|---|---| -| `@gadget/ai` | `strict: true` | -| gadget-drone | `strict: true` | -| gadget-code | `strict: true`, `noUnusedLocals`, `noUnusedParameters`, `noUncheckedIndexedAccess` | +| 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 concern** (AI, logging, config schema) → goes in `@gadget/ai` +- **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. \ No newline at end of file +If code is needed by both consumer packages, it belongs in `@gadget/ai`. Do not copy-paste shared logic across packages. diff --git a/README.md b/README.md index 98eb99e..a433d95 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ A self-hosted **Agentic Engineering Platform (AEP)** — an IDE that drives auto ## Projects -| Package | Role | -|---|---| -| `gadget-code` | Web service — agentic IDE, browser UI, API server | +| Package | Role | +| -------------- | ------------------------------------------------------------------------ | +| `gadget-code` | Web service — agentic IDE, browser UI, API server | | `gadget-drone` | Worker process — runs the agentic workflow loop in workspace directories | -| `@gadget/ai` | Shared AI API abstraction — Ollama and OpenAI, called by both | +| `@gadget/ai` | Shared AI API abstraction — Ollama and OpenAI, called by both | ## AI API Abstraction (`@gadget/ai`) @@ -43,6 +43,26 @@ pnpm --filter gadget-drone dev ## Architecture -gadget-code runs on server infrastructure (MongoDB, Redis, etc.) and serves the browser-based IDE. gadget-drone runs on end-user machines, connecting via WebSocket to gadget-code, and executes the agentic workflow loop against local project directories via remote control. gadget-drone never connects directly to MongoDB or Redis — it communicates entirely through the Gadget Code API. +### @gadget/ai -AI calls are handled by `@gadget/ai`, which both projects depend on. This keeps all AI SDK knowledge in one place. \ No newline at end of file +AI API calls are handled by `@gadget/ai`, which both projects depend on. This keeps all AI SDK knowledge in one place, and currently implements: + +- [AiApi](./packages/ai/src/api.ts) - abstract base class for all AI APIs/SDKs +- [OllamaAiApi](./packages/ai/src/ollama.ts) - Ollama API implementation +- [OpenAiApi](./packages/ai/src/openai.ts) - OpenAI API implementation + +### gadget-drone + +gadget-drone is a headless process runs on end-user machines, connecting via Socket.IO to gadget-code, to receive and execute work orders for the agentic workflow loop. + +At startup, gadget-drone examines `process.cwd()` to determine if it's a workspace directory, and if so, starts a worker process that connects to gadget-code and waits for work orders. It processes work orders in project directories in the gadget-drone workspace directory, and communicates events, status, and results to the IDE via gadget-code's web services and Socket.IO. + +gadget-drone never connects directly to MongoDB or Redis — it communicates entirely through the Gadget Code API. + +### gadget-code + +gadget-code runs on server infrastructure (MongoDB, Redis, etc.) and serves the browser-based IDE. The IDE connects to gadget-code via Socket.IO to send and receive commands in chat sessions to gadget-drone. + +gadget-code can be stacked on a single host for local development, and can achieve significant scale on a single host. It can also be deployed in tiers, potentially made of clusters, and the web tier can be horizontally scaled for production use with high availability. + +Libraries such as [redis-adapter](https://github.com/socketio/socket.io-redis-adapter) and [redis-emitter](https://github.com/socketio/socket.io-redis-emitter) are used for message routing and distribution in the Socket.IO library, handling the real-time message routing among gadget-code, gadget-drone, and the IDE running in the browser. diff --git a/packages/ai/README.md b/packages/ai/README.md index ddc0670..7c0e11d 100644 --- a/packages/ai/README.md +++ b/packages/ai/README.md @@ -53,8 +53,8 @@ console.log(result.stats.duration.text); // formatted, e.g. "00:00:02" Abstract base class. Currently implemented: -- **`AiOllamaApi`** — Ollama provider -- **`AiOpenAiApi`** — OpenAI provider (stubbed) +- **`OllamaAiApi`** — Ollama provider +- **`OpenAiApi`** — OpenAI provider (stubbed) #### `ai.generate(model, options, streamCallback?)` @@ -83,7 +83,7 @@ Configured via `IAiProvider` with `sdk: "ollama"`. Uses the `ollama` npm package ### OpenAI -Configured via `IAiProvider` with `sdk: "openai"`. Stubbed — `chat()` and `generate()` throw `"Not yet implemented"`. Implement by wiring the `openai` npm package following the same pattern as `AiOllamaApi`. +Configured via `IAiProvider` with `sdk: "openai"`. Stubbed — `chat()` and `generate()` throw `"Not yet implemented"`. Implement by wiring the `openai` npm package following the same pattern as `OllamaAiApi`. ## Duration Formatting @@ -95,4 +95,4 @@ The library uses `numeral` to provide a consistent formatted duration string (`s 2. Update `packages/ai/src/index.ts` — add the new class to the `createAiApi` factory switch 3. Update this README -No consumer code changes required. \ No newline at end of file +No consumer code changes required. diff --git a/packages/ai/src/index.ts b/packages/ai/src/index.ts index 59d9250..0b4c468 100644 --- a/packages/ai/src/index.ts +++ b/packages/ai/src/index.ts @@ -19,11 +19,11 @@ export { AiApi, } from "./api.js"; -export { AiOllamaApi } from "./ollama.js"; -export { AiOpenAiApi } from "./openai.js"; +export { OllamaAiApi } from "./ollama.js"; +export { OpenAiApi } from "./openai.js"; -import { AiOllamaApi } from "./ollama.js"; -import { AiOpenAiApi } from "./openai.js"; +import { OllamaAiApi } from "./ollama.js"; +import { OpenAiApi } from "./openai.js"; import type { IAiProvider } from "./api.js"; import type { IAiLogger } from "./api.js"; import type { AiApi } from "./api.js"; @@ -31,10 +31,10 @@ import type { AiApi } from "./api.js"; export function createAiApi(provider: IAiProvider, logger?: IAiLogger): AiApi { switch (provider.sdk) { case "ollama": - return new AiOllamaApi(provider, logger); + return new OllamaAiApi(provider, logger); case "openai": - return new AiOpenAiApi(provider, logger); + return new OpenAiApi(provider, logger); default: throw new Error(`Unknown AI SDK: ${(provider as IAiProvider).sdk}`); } -} \ No newline at end of file +} diff --git a/packages/ai/src/ollama.ts b/packages/ai/src/ollama.ts index 9b484b9..78834ea 100644 --- a/packages/ai/src/ollama.ts +++ b/packages/ai/src/ollama.ts @@ -18,7 +18,7 @@ import { IAiResponseStreamFn, } from "./api.js"; -export class AiOllamaApi extends AiApi { +export class OllamaAiApi extends AiApi { protected client: Ollama; constructor(provider: IAiProvider, logger?: IAiLogger) { @@ -30,11 +30,11 @@ export class AiOllamaApi extends AiApi { } async listModels(): Promise { - await this.log.debug("AiOllamaApi.listModels called"); + await this.log.debug("OllamaAiApi.listModels called"); } async probeModel(modelId: string): Promise { - await this.log.debug("AiOllamaApi.probeModel called", { modelId }); + await this.log.debug("OllamaAiApi.probeModel called", { modelId }); } async generate( @@ -42,7 +42,7 @@ export class AiOllamaApi extends AiApi { options: IAiGenerateOptions, streamCallback?: IAiResponseStreamFn, ): Promise { - await this.log.debug("AiOllamaApi.generate called", { + await this.log.debug("OllamaAiApi.generate called", { provider: model.provider.name, modelId: model.modelId, }); @@ -85,7 +85,7 @@ export class AiOllamaApi extends AiApi { options: IAiChatOptions, streamCallback?: IAiResponseStreamFn, ): Promise { - await this.log.debug("AiOllamaApi.chat called", { + await this.log.debug("OllamaAiApi.chat called", { provider: model.provider.name, modelId: model.modelId, }); diff --git a/packages/ai/src/openai.ts b/packages/ai/src/openai.ts index d0fa633..5dea233 100644 --- a/packages/ai/src/openai.ts +++ b/packages/ai/src/openai.ts @@ -14,17 +14,17 @@ import { IAiResponseStreamFn, } from "./api.js"; -export class AiOpenAiApi extends AiApi { +export class OpenAiApi extends AiApi { constructor(provider: IAiProvider, logger?: IAiLogger) { super(provider, logger); } async listModels(): Promise { - await this.log.debug("AiOpenAiApi.listModels called"); + await this.log.debug("OpenAiApi.listModels called"); } async probeModel(modelId: string): Promise { - await this.log.debug("AiOpenAiApi.probeModel called", { modelId }); + await this.log.debug("OpenAiApi.probeModel called", { modelId }); } async generate(