mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-17 05:00:16 +00:00
feat(ai): Create unified AI package with OpenAI, Anthropic, and Gemini support
- Set up @mariozechner/ai package structure following monorepo patterns - Install OpenAI, Anthropic, and Google Gemini SDK dependencies - Document comprehensive API investigation for all three providers - Design minimal unified API with streaming-first architecture - Add models.dev integration for pricing and capabilities - Implement automatic caching strategy for all providers - Update project documentation with package creation guide
This commit is contained in:
parent
2c03724862
commit
f064ea0e14
14 changed files with 7437 additions and 21 deletions
606
todos/done/20250817-183528-ai-unified-api-package-analysis.md
Normal file
606
todos/done/20250817-183528-ai-unified-api-package-analysis.md
Normal file
|
|
@ -0,0 +1,606 @@
|
|||
# Analysis: Creating Unified AI Package
|
||||
|
||||
## Package Structure Analysis for Pi Monorepo
|
||||
|
||||
Based on my examination of the existing packages (`tui`, `agent`, and `pods`), here are the comprehensive patterns and conventions used in this monorepo:
|
||||
|
||||
### 1. Package Naming Conventions
|
||||
|
||||
**Scoped NPM packages with consistent naming:**
|
||||
- All packages use the `@mariozechner/` scope
|
||||
- Package names follow the pattern: `@mariozechner/pi-<package-name>`
|
||||
- Special case: the main CLI package is simply `@mariozechner/pi` (not `pi-pods`)
|
||||
|
||||
**Directory structure:**
|
||||
- Packages are located in `/packages/<package-name>/`
|
||||
- Directory names match the suffix of the npm package name (e.g., `tui`, `agent`, `pods`)
|
||||
|
||||
### 2. Package.json Structure Patterns
|
||||
|
||||
**Common fields across all packages:**
|
||||
```json
|
||||
{
|
||||
"name": "@mariozechner/pi-<name>",
|
||||
"version": "0.5.8", // Lockstep versioning - all packages share same version
|
||||
"description": "...",
|
||||
"type": "module", // All packages use ES modules
|
||||
"author": "Mario Zechner",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/badlogic/pi-mono.git",
|
||||
"directory": "packages/<name>"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0" // Consistent Node.js requirement
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Binary packages (agent, pods):**
|
||||
- Include `"bin"` field with CLI command mapping
|
||||
- Examples: `"pi-agent": "dist/cli.js"` and `"pi": "dist/cli.js"`
|
||||
|
||||
**Library packages (tui):**
|
||||
- Include `"main"` field pointing to built entry point
|
||||
- Include `"types"` field for TypeScript definitions
|
||||
|
||||
### 3. Scripts Configuration
|
||||
|
||||
**Universal scripts across all packages:**
|
||||
- `"clean": "rm -rf dist"` - Removes build artifacts
|
||||
- `"build": "tsc -p tsconfig.build.json"` - Builds with dedicated build config
|
||||
- `"check": "biome check --write ."` - Linting and formatting
|
||||
- `"prepublishOnly": "npm run clean && npm run build"` - Pre-publish cleanup
|
||||
|
||||
**CLI-specific build scripts:**
|
||||
- Add `&& chmod +x dist/cli.js` for executable permissions
|
||||
- Copy additional assets (e.g., `&& cp src/models.json dist/` for pods package)
|
||||
|
||||
### 4. Dependencies Structure
|
||||
|
||||
**Dependency hierarchy follows a clear pattern:**
|
||||
```
|
||||
pi-tui (foundation) -> pi-agent (uses tui) -> pi (uses agent)
|
||||
```
|
||||
|
||||
**Internal dependencies:**
|
||||
- Use exact version matching for internal packages (e.g., `"^0.5.8"`)
|
||||
- Agent depends on TUI: `"@mariozechner/pi-tui": "^0.5.8"`
|
||||
- Pods depends on Agent: `"@mariozechner/pi-agent": "^0.5.8"`
|
||||
|
||||
**External dependencies:**
|
||||
- Common dependencies like `chalk` are used across multiple packages
|
||||
- Specialized dependencies are package-specific (e.g., `marked` for tui, `openai` for agent)
|
||||
|
||||
### 5. TypeScript Configuration
|
||||
|
||||
**Dual TypeScript configuration approach:**
|
||||
|
||||
**`tsconfig.build.json` (for production builds):**
|
||||
```json
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
```
|
||||
|
||||
**Root `tsconfig.json` (for development and type checking):**
|
||||
- Contains path mappings for cross-package imports during development
|
||||
- Includes all source and test files
|
||||
- Uses `"noEmit": true` for type checking without building
|
||||
|
||||
### 6. Source Directory Structure
|
||||
|
||||
**Standard structure across all packages:**
|
||||
```
|
||||
src/
|
||||
├── index.ts # Main export file
|
||||
├── cli.ts # CLI entry point (if applicable)
|
||||
├── <core-files>.ts # Core functionality
|
||||
├── components/ # Components (for tui)
|
||||
├── tools/ # Tool implementations (for agent)
|
||||
├── commands/ # Command implementations (for pods)
|
||||
└── renderers/ # Output renderers (for agent)
|
||||
```
|
||||
|
||||
### 7. Export Patterns (index.ts)
|
||||
|
||||
**Comprehensive type and function exports:**
|
||||
- Export both types and implementation classes
|
||||
- Use `export type` for type-only exports
|
||||
- Group exports logically with comments
|
||||
- Example from tui: exports components, interfaces, and utilities
|
||||
- Example from agent: exports core classes, types, and utilities
|
||||
|
||||
### 8. Files Configuration
|
||||
|
||||
**Files included in NPM packages:**
|
||||
- `"files": ["dist"]` or `"files": ["dist/**/*", "README.md"]`
|
||||
- All packages include built `dist/` directory
|
||||
- Some include additional files like README.md or scripts
|
||||
|
||||
### 9. README.md Structure
|
||||
|
||||
**Comprehensive documentation pattern:**
|
||||
- Feature overview with key capabilities
|
||||
- Quick start section with code examples
|
||||
- Detailed API documentation
|
||||
- Installation instructions
|
||||
- Development setup
|
||||
- Testing information (especially for tui)
|
||||
- Examples and usage patterns
|
||||
|
||||
### 10. Testing Structure (TUI package)
|
||||
|
||||
**Dedicated test directory:**
|
||||
- `test/` directory with `.test.ts` files for unit tests
|
||||
- Example applications (e.g., `chat-app.ts`, `file-browser.ts`)
|
||||
- Custom testing infrastructure (e.g., `virtual-terminal.ts`)
|
||||
- Test script: `"test": "node --test --import tsx test/*.test.ts"`
|
||||
|
||||
### 11. Version Management
|
||||
|
||||
**Lockstep versioning:**
|
||||
- All packages share the same version number
|
||||
- Root package.json scripts handle version bumping across all packages
|
||||
- Version sync script ensures internal dependency versions match
|
||||
|
||||
### 12. Build Order
|
||||
|
||||
**Dependency-aware build order:**
|
||||
- Root build script builds packages in dependency order
|
||||
- `"build": "npm run build -w @mariozechner/pi-tui && npm run build -w @mariozechner/pi-agent && npm run build -w @mariozechner/pi"`
|
||||
|
||||
### 13. Common Configuration Files
|
||||
|
||||
**Shared across monorepo:**
|
||||
- `biome.json` - Unified linting and formatting configuration
|
||||
- `tsconfig.base.json` - Base TypeScript configuration
|
||||
- `.gitignore` - Ignores `dist/`, `node_modules/`, and other build artifacts
|
||||
- Husky pre-commit hooks for formatting and type checking
|
||||
|
||||
### 14. Keywords and Metadata
|
||||
|
||||
**Descriptive keywords for NPM discovery:**
|
||||
- Each package includes relevant keywords (e.g., "tui", "terminal", "agent", "ai", "llm")
|
||||
- Keywords help with package discoverability
|
||||
|
||||
This analysis shows a well-structured monorepo with consistent patterns that would make adding new packages straightforward by following these established conventions.
|
||||
|
||||
## Monorepo Configuration Analysis
|
||||
|
||||
Based on my analysis of the pi-mono monorepo configuration, here's a comprehensive guide on how to properly integrate a new package:
|
||||
|
||||
### 1. Root Package.json Configuration
|
||||
|
||||
**Workspace Configuration:**
|
||||
- Uses npm workspaces with `"workspaces": ["packages/*"]`
|
||||
- All packages are located under `/packages/` directory
|
||||
- Private monorepo (`"private": true`) with ESM modules (`"type": "module"`)
|
||||
|
||||
**Build System:**
|
||||
- **Sequential Build Order**: The build script explicitly defines dependency order:
|
||||
```json
|
||||
"build": "npm run build -w @mariozechner/pi-tui && npm run build -w @mariozechner/pi-agent && npm run build -w @mariozechner/pi"
|
||||
```
|
||||
- **Dependency Chain**: `pi-tui` → `pi-agent` → `pi` (pods)
|
||||
- **Important**: New packages must be inserted in the correct dependency order in the build script
|
||||
|
||||
**Scripts Available:**
|
||||
- `clean`: Cleans all package dist folders
|
||||
- `build`: Sequential build respecting dependencies
|
||||
- `check`: Runs Biome formatting, package checks, and TypeScript checking
|
||||
- `test`: Runs tests across all packages
|
||||
- Version management scripts (lockstep versioning)
|
||||
- Publishing scripts with dry-run capability
|
||||
|
||||
### 2. Root TypeScript Configuration
|
||||
|
||||
**Dual Configuration System:**
|
||||
- **`tsconfig.base.json`**: Base TypeScript settings for all packages
|
||||
- **`tsconfig.json`**: Development configuration with path mappings for cross-package imports
|
||||
- **Package `tsconfig.build.json`**: Clean build configs per package
|
||||
|
||||
**Path Mappings** (in `/Users/badlogic/workspaces/pi-mono/tsconfig.json`):
|
||||
```json
|
||||
"paths": {
|
||||
"@mariozechner/pi-tui": ["./packages/tui/src/index.ts"],
|
||||
"@mariozechner/pi-agent": ["./packages/agent/src/index.ts"],
|
||||
"@mariozechner/pi": ["./packages/pods/src/index.ts"]
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Package Dependencies and Structure
|
||||
|
||||
**Dependency Structure:**
|
||||
- `pi-tui` (base library) - no internal dependencies
|
||||
- `pi-agent` depends on `pi-tui`
|
||||
- `pi` (pods) depends on `pi-agent`
|
||||
|
||||
**Standard Package Structure:**
|
||||
```
|
||||
packages/new-package/
|
||||
├── src/
|
||||
│ ├── index.ts # Main export file
|
||||
│ └── ... # Implementation files
|
||||
├── package.json # Package configuration
|
||||
├── tsconfig.build.json # Build-specific TypeScript config
|
||||
├── README.md # Package documentation
|
||||
└── dist/ # Build output (gitignored)
|
||||
```
|
||||
|
||||
### 4. Version Management
|
||||
|
||||
**Lockstep Versioning:**
|
||||
- All packages share the same version number (currently 0.5.8)
|
||||
- Automated version sync script: `/Users/badlogic/workspaces/pi-mono/scripts/sync-versions.js`
|
||||
- Inter-package dependencies are automatically updated to match current versions
|
||||
|
||||
**Version Scripts:**
|
||||
- `npm run version:patch/minor/major` - Updates all package versions and syncs dependencies
|
||||
- Automatic dependency version synchronization
|
||||
|
||||
### 5. GitIgnore Patterns
|
||||
|
||||
**Package-Level Ignores:**
|
||||
```
|
||||
packages/*/node_modules/
|
||||
packages/*/dist/
|
||||
```
|
||||
Plus standard ignores for logs, IDE files, environment files, etc.
|
||||
|
||||
## How to Integrate a New Package
|
||||
|
||||
### Step 1: Create Package Structure
|
||||
```bash
|
||||
mkdir packages/your-new-package
|
||||
cd packages/your-new-package
|
||||
```
|
||||
|
||||
### Step 2: Create package.json
|
||||
```json
|
||||
{
|
||||
"name": "@mariozechner/your-new-package",
|
||||
"version": "0.5.8",
|
||||
"description": "Your package description",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": ["dist"],
|
||||
"scripts": {
|
||||
"clean": "rm -rf dist",
|
||||
"build": "tsc -p tsconfig.build.json",
|
||||
"check": "biome check --write .",
|
||||
"prepublishOnly": "npm run clean && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
// Add dependencies on other packages in the monorepo if needed
|
||||
// "@mariozechner/pi-tui": "^0.5.8"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"keywords": ["relevant", "keywords"],
|
||||
"author": "Mario Zechner",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/badlogic/pi-mono.git",
|
||||
"directory": "packages/your-new-package"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Create tsconfig.build.json
|
||||
```json
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Create src/index.ts
|
||||
```typescript
|
||||
// Main exports for your package
|
||||
export * from './your-main-module.js';
|
||||
```
|
||||
|
||||
### Step 5: Update Root Configuration
|
||||
|
||||
**Add to `/Users/badlogic/workspaces/pi-mono/tsconfig.json` paths:**
|
||||
```json
|
||||
"paths": {
|
||||
"@mariozechner/pi-tui": ["./packages/tui/src/index.ts"],
|
||||
"@mariozechner/pi-agent": ["./packages/agent/src/index.ts"],
|
||||
"@mariozechner/pi": ["./packages/pods/src/index.ts"],
|
||||
"@mariozechner/your-new-package": ["./packages/your-new-package/src/index.ts"]
|
||||
}
|
||||
```
|
||||
|
||||
**Update build script in root `/Users/badlogic/workspaces/pi-mono/package.json`:**
|
||||
```json
|
||||
"build": "npm run build -w @mariozechner/pi-tui && npm run build -w @mariozechner/pi-agent && npm run build -w @mariozechner/your-new-package && npm run build -w @mariozechner/pi"
|
||||
```
|
||||
(Insert in correct dependency order)
|
||||
|
||||
### Step 6: Update sync-versions.js
|
||||
If your package depends on other monorepo packages, add synchronization logic to `/Users/badlogic/workspaces/pi-mono/scripts/sync-versions.js`.
|
||||
|
||||
### Step 7: Install and Test
|
||||
```bash
|
||||
# From monorepo root
|
||||
npm install
|
||||
npm run build
|
||||
npm run check
|
||||
```
|
||||
|
||||
## Key Requirements for New Packages
|
||||
|
||||
1. **Must use ESM modules** (`"type": "module"`)
|
||||
2. **Must follow lockstep versioning** (same version as other packages)
|
||||
3. **Must be placed in correct build order** based on dependencies
|
||||
4. **Must use tab indentation** (Biome config: `"indentStyle": "tab"`)
|
||||
5. **Must avoid `any` types** unless absolutely necessary (project instruction)
|
||||
6. **Must include proper TypeScript declarations** (`"declaration": true`)
|
||||
7. **Must use Node.js >= 20.0.0** (engine requirement)
|
||||
8. **Must follow the standard package structure** with src/, dist/, proper exports
|
||||
|
||||
## Development Workflow
|
||||
|
||||
1. **Development**: Use `tsx` to run source files directly (no build needed)
|
||||
2. **Type Checking**: `npm run check` works across all packages
|
||||
3. **Building**: Sequential builds respect dependency order
|
||||
4. **Publishing**: Automatic version sync and cross-package dependency updates
|
||||
5. **Testing**: Each package can have its own test suite
|
||||
|
||||
This monorepo is well-structured for maintaining multiple related packages with clean dependency management and automated version synchronization.
|
||||
|
||||
## Detailed Findings: Unified AI API Requirements Based on Current pi-agent Usage
|
||||
|
||||
After thoroughly analyzing the existing agent package (`/Users/badlogic/workspaces/pi-mono/packages/agent`), here are the comprehensive requirements for a unified AI API based on current usage patterns:
|
||||
|
||||
### **1. Core API Structure & Event System**
|
||||
|
||||
**Current Pattern:**
|
||||
- Event-driven architecture using `AgentEvent` types
|
||||
- Single `AgentEventReceiver` interface for all output handling
|
||||
- Support for both single-shot and interactive modes
|
||||
|
||||
**Required API Features:**
|
||||
```typescript
|
||||
type AgentEvent =
|
||||
| { type: "session_start"; sessionId: string; model: string; api: string; baseURL: string; systemPrompt: string }
|
||||
| { type: "assistant_start" }
|
||||
| { type: "reasoning"; text: string }
|
||||
| { type: "tool_call"; toolCallId: string; name: string; args: string }
|
||||
| { type: "tool_result"; toolCallId: string; result: string; isError: boolean }
|
||||
| { type: "assistant_message"; text: string }
|
||||
| { type: "error"; message: string }
|
||||
| { type: "user_message"; text: string }
|
||||
| { type: "interrupted" }
|
||||
| { type: "token_usage"; inputTokens: number; outputTokens: number; totalTokens: number; cacheReadTokens: number; cacheWriteTokens: number; reasoningTokens: number }
|
||||
```
|
||||
|
||||
### **2. OpenAI API Integration Patterns**
|
||||
|
||||
**Current Implementation:**
|
||||
- Uses OpenAI SDK v5.12.2 (`import OpenAI from "openai"`)
|
||||
- Supports both Chat Completions (`/v1/chat/completions`) and Responses API (`/v1/responses`)
|
||||
- Provider detection based on base URL patterns
|
||||
|
||||
**Provider Support Required:**
|
||||
```typescript
|
||||
// Detected providers based on baseURL patterns
|
||||
type Provider = "openai" | "gemini" | "groq" | "anthropic" | "openrouter" | "other"
|
||||
|
||||
// Provider-specific configurations
|
||||
interface ProviderConfig {
|
||||
openai: { reasoning_effort: "minimal" | "low" | "medium" | "high" }
|
||||
gemini: { extra_body: { google: { thinking_config: { thinking_budget: number, include_thoughts: boolean } } } }
|
||||
groq: { reasoning_format: "parsed", reasoning_effort: string }
|
||||
openrouter: { reasoning: { effort: "low" | "medium" | "high" } }
|
||||
}
|
||||
```
|
||||
|
||||
### **3. Streaming vs Non-Streaming**
|
||||
|
||||
**Current Status:**
|
||||
- **No streaming currently implemented** - uses standard request/response
|
||||
- All API calls are non-streaming: `await client.chat.completions.create()` and `await client.responses.create()`
|
||||
- Events are emitted synchronously after full response
|
||||
|
||||
**Streaming Requirements for Unified API:**
|
||||
- Support for streaming responses with partial content updates
|
||||
- Event-driven streaming with `assistant_message_delta` events
|
||||
- Proper handling of tool call streaming
|
||||
- Reasoning token streaming for supported models
|
||||
|
||||
### **4. Tool Calling Architecture**
|
||||
|
||||
**Current Implementation:**
|
||||
```typescript
|
||||
// Tool definitions for both APIs
|
||||
toolsForResponses: Array<{type: "function", name: string, description: string, parameters: object}>
|
||||
toolsForChat: ChatCompletionTool[]
|
||||
|
||||
// Tool execution with abort support
|
||||
async function executeTool(name: string, args: string, signal?: AbortSignal): Promise<string>
|
||||
|
||||
// Built-in tools: read, list, bash, glob, rg (ripgrep)
|
||||
```
|
||||
|
||||
**Unified API Requirements:**
|
||||
- Automatic tool format conversion between Chat Completions and Responses API
|
||||
- Built-in tools with filesystem and shell access
|
||||
- Custom tool registration capability
|
||||
- Tool execution with proper abort/interrupt handling
|
||||
- Tool result streaming for long-running operations
|
||||
|
||||
### **5. Message Structure Handling**
|
||||
|
||||
**Current Pattern:**
|
||||
- Dual message format support based on API type
|
||||
- Automatic conversion between formats in `setEvents()` method
|
||||
|
||||
**Chat Completions Format:**
|
||||
```typescript
|
||||
{ role: "system" | "user" | "assistant" | "tool", content: string, tool_calls?: any[] }
|
||||
```
|
||||
|
||||
**Responses API Format:**
|
||||
```typescript
|
||||
{ type: "message" | "function_call" | "function_call_output", content: any[] }
|
||||
```
|
||||
|
||||
### **6. Session Persistence System**
|
||||
|
||||
**Current Implementation:**
|
||||
```typescript
|
||||
interface SessionData {
|
||||
config: AgentConfig
|
||||
events: SessionEvent[]
|
||||
totalUsage: TokenUsage
|
||||
}
|
||||
|
||||
// File-based persistence in ~/.pi/sessions/
|
||||
// JSONL format with session headers and event entries
|
||||
// Automatic session continuation support
|
||||
```
|
||||
|
||||
**Requirements:**
|
||||
- Directory-based session organization
|
||||
- Event replay capability for session restoration
|
||||
- Cumulative token usage tracking
|
||||
- Session metadata (config, timestamps, working directory)
|
||||
|
||||
### **7. Token Counting & Usage Tracking**
|
||||
|
||||
**Current Implementation:**
|
||||
```typescript
|
||||
interface TokenUsage {
|
||||
inputTokens: number
|
||||
outputTokens: number
|
||||
totalTokens: number
|
||||
cacheReadTokens: number
|
||||
cacheWriteTokens: number
|
||||
reasoningTokens: number // For o1/o3 and reasoning models
|
||||
}
|
||||
```
|
||||
|
||||
**Provider-Specific Token Mapping:**
|
||||
- OpenAI: `prompt_tokens`, `completion_tokens`, `cached_tokens`, `reasoning_tokens`
|
||||
- Responses API: `input_tokens`, `output_tokens`, `cached_tokens`, `reasoning_tokens`
|
||||
- Cumulative tracking across conversations
|
||||
|
||||
### **8. Abort/Interrupt Handling**
|
||||
|
||||
**Current Pattern:**
|
||||
```typescript
|
||||
class Agent {
|
||||
private abortController: AbortController | null = null
|
||||
|
||||
async ask(message: string) {
|
||||
this.abortController = new AbortController()
|
||||
// Pass signal to all API calls and tool executions
|
||||
}
|
||||
|
||||
interrupt(): void {
|
||||
this.abortController?.abort()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Requirements:**
|
||||
- AbortController integration for all async operations
|
||||
- Graceful interruption of API calls, tool execution, and streaming
|
||||
- Proper cleanup and "interrupted" event emission
|
||||
- Signal propagation to nested operations
|
||||
|
||||
### **9. Reasoning/Thinking Support**
|
||||
|
||||
**Current Implementation:**
|
||||
```typescript
|
||||
// Provider-specific reasoning extraction
|
||||
function parseReasoningFromMessage(message: any, baseURL?: string): {
|
||||
cleanContent: string
|
||||
reasoningTexts: string[]
|
||||
}
|
||||
|
||||
// Automatic reasoning support detection
|
||||
async function checkReasoningSupport(client, model, api, baseURL, signal): Promise<boolean>
|
||||
```
|
||||
|
||||
**Provider Support:**
|
||||
- **OpenAI o1/o3**: Full thinking content via Responses API
|
||||
- **Groq GPT-OSS**: Reasoning via `reasoning_format: "parsed"`
|
||||
- **Gemini 2.5**: Thinking content via `<thought>` tags
|
||||
- **OpenRouter**: Model-dependent reasoning support
|
||||
|
||||
### **10. Error Handling Patterns**
|
||||
|
||||
**Current Approach:**
|
||||
- Try/catch blocks around all API calls
|
||||
- Error events emitted through event system
|
||||
- Specific error handling for reasoning model failures
|
||||
- Provider-specific error interpretation
|
||||
|
||||
### **11. Configuration Management**
|
||||
|
||||
**Current Structure:**
|
||||
```typescript
|
||||
interface AgentConfig {
|
||||
apiKey: string
|
||||
baseURL: string
|
||||
model: string
|
||||
api: "completions" | "responses"
|
||||
systemPrompt: string
|
||||
}
|
||||
```
|
||||
|
||||
**Provider Detection:**
|
||||
```typescript
|
||||
function detectProvider(baseURL?: string): Provider {
|
||||
// URL pattern matching for automatic provider configuration
|
||||
}
|
||||
```
|
||||
|
||||
### **12. Output Rendering System**
|
||||
|
||||
**Current Renderers:**
|
||||
- **ConsoleRenderer**: Terminal output with animations, token display
|
||||
- **TuiRenderer**: Full interactive TUI with pi-tui integration
|
||||
- **JsonRenderer**: JSONL event stream output
|
||||
|
||||
**Requirements:**
|
||||
- Event-based rendering architecture
|
||||
- Real-time token usage display
|
||||
- Loading animations for async operations
|
||||
- Markdown rendering support
|
||||
- Tool execution progress indication
|
||||
|
||||
### **Summary: Key Unified API Requirements**
|
||||
|
||||
1. **Event-driven architecture** with standardized event types
|
||||
2. **Dual API support** (Chat Completions + Responses API) with automatic format conversion
|
||||
3. **Provider abstraction** with automatic detection and configuration
|
||||
4. **Comprehensive tool system** with abort support and built-in tools
|
||||
5. **Session persistence** with event replay and token tracking
|
||||
6. **Reasoning/thinking support** across multiple providers
|
||||
7. **Interrupt handling** with AbortController integration
|
||||
8. **Token usage tracking** with provider-specific mapping
|
||||
9. **Flexible rendering** through event receiver pattern
|
||||
10. **Configuration management** with provider-specific settings
|
||||
|
||||
The unified API should maintain this event-driven, provider-agnostic approach while adding streaming capabilities and enhanced tool execution features that the current implementation lacks.
|
||||
46
todos/done/20250817-183528-ai-unified-api-package.md
Normal file
46
todos/done/20250817-183528-ai-unified-api-package.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Create AI Package with Unified API
|
||||
|
||||
**Status:** Done
|
||||
**Agent PID:** 10965
|
||||
|
||||
## Original Todo
|
||||
ai: create a new package ai (package name @mariozechner/ai) which implements a common api for the openai, anthropic, and google gemini apis
|
||||
- look at the other packages and how they are set up, mirror that setup for ai
|
||||
- install the latest version of each dependency via npm in the ai package
|
||||
- openai@5.12.2
|
||||
- @anthropic-ai/sdk@0.60.0
|
||||
- @google/genai@1.14.0
|
||||
- investigate the APIs in their respective node_modules folder so you understand how to use them. specifically, we need to understand how to:
|
||||
- stream responses, including reasoning/thinking tokens and tool calls
|
||||
- abort requests
|
||||
- handle errors
|
||||
- handle stop reasons
|
||||
- maintain the context (message history) such that it can be serialized in a uniform format to disk, and deserialized again later and used with the other api
|
||||
- count tokens (input, output, cached read, cached write)
|
||||
- enable caching
|
||||
- Create a plan.md in the ai package that details how the unified API on top of all three could look like. we want the most minimal api possible, which allows serialization/deserialization, turning on/off reasoning/thinking, and handle system prompt and tool specifications
|
||||
|
||||
## Description
|
||||
Create the initial package scaffold for @mariozechner/ai following the established monorepo patterns, install the required dependencies (openai, anthropic, google genai SDKs), and create a plan.md file that details the unified API design for all three providers.
|
||||
|
||||
*Read [analysis.md](./analysis.md) in full for detailed codebase research and context*
|
||||
|
||||
## Implementation Plan
|
||||
- [x] Create package directory structure at packages/ai/
|
||||
- [x] Create package.json with proper configuration following monorepo patterns
|
||||
- [x] Create tsconfig.build.json for build configuration
|
||||
- [x] Create initial src/index.ts file
|
||||
- [x] Add package to root tsconfig.json path mappings
|
||||
- [x] Update root package.json build script to include ai package
|
||||
- [x] Install dependencies: openai@5.12.2, @anthropic-ai/sdk@0.60.0, @google/genai@1.14.0
|
||||
- [x] Create README.md with package description
|
||||
- [x] Create plan.md detailing the unified API design
|
||||
- [x] Investigate OpenAI, Anthropic, and Gemini APIs in detail
|
||||
- [x] Document implementation details for each API
|
||||
- [x] Update todos/project-description.md with "How to Create a New Package" section
|
||||
- [x] Update todos/project-description.md Testing section to reflect that tui has Node.js built-in tests
|
||||
- [x] Run npm install from root to link everything
|
||||
- [x] Verify package builds correctly with npm run build
|
||||
|
||||
## Notes
|
||||
[Implementation notes]
|
||||
|
|
@ -39,4 +39,98 @@ A comprehensive toolkit for managing Large Language Model (LLM) deployments and
|
|||
- Publish: `npm run publish`
|
||||
|
||||
## Testing
|
||||
Currently no formal testing framework is configured. Test infrastructure exists but no actual test files or framework dependencies are present.
|
||||
The TUI package includes comprehensive tests using Node.js built-in test framework:
|
||||
- Unit tests in `packages/tui/test/*.test.ts`
|
||||
- Test runner: `node --test --import tsx test/*.test.ts`
|
||||
- Virtual terminal for TUI testing via `@xterm/headless`
|
||||
- Example applications for manual testing
|
||||
|
||||
## How to Create a New Package
|
||||
|
||||
Follow these steps to add a new package to the monorepo:
|
||||
|
||||
1. **Create package directory structure:**
|
||||
```bash
|
||||
mkdir -p packages/your-package/src
|
||||
```
|
||||
|
||||
2. **Create package.json:**
|
||||
```json
|
||||
{
|
||||
"name": "@mariozechner/your-package",
|
||||
"version": "0.5.8",
|
||||
"description": "Package description",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": ["dist", "README.md"],
|
||||
"scripts": {
|
||||
"clean": "rm -rf dist",
|
||||
"build": "tsc -p tsconfig.build.json",
|
||||
"check": "biome check --write .",
|
||||
"prepublishOnly": "npm run clean && npm run build"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"keywords": ["relevant", "keywords"],
|
||||
"author": "Mario Zechner",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/badlogic/pi-mono.git",
|
||||
"directory": "packages/your-package"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **Create tsconfig.build.json:**
|
||||
```json
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
```
|
||||
|
||||
4. **Create src/index.ts:**
|
||||
```typescript
|
||||
// Main exports for your package
|
||||
export const version = "0.5.8";
|
||||
```
|
||||
|
||||
5. **Update root tsconfig.json paths:**
|
||||
Add your package to the `paths` mapping in the correct dependency order:
|
||||
```json
|
||||
"paths": {
|
||||
"@mariozechner/pi-tui": ["./packages/tui/src/index.ts"],
|
||||
"@mariozechner/your-package": ["./packages/your-package/src/index.ts"],
|
||||
// ... other packages
|
||||
}
|
||||
```
|
||||
|
||||
6. **Update root package.json build script:**
|
||||
Insert your package in the correct dependency order:
|
||||
```json
|
||||
"build": "npm run build -w @mariozechner/pi-tui && npm run build -w @mariozechner/your-package && ..."
|
||||
```
|
||||
|
||||
7. **Install and verify:**
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
npm run check
|
||||
```
|
||||
|
||||
**Important Notes:**
|
||||
- All packages use lockstep versioning (same version number)
|
||||
- Follow dependency order: foundational packages build first
|
||||
- Use ESM modules (`"type": "module"`)
|
||||
- No `any` types unless absolutely necessary
|
||||
- Include README.md with package documentation
|
||||
Loading…
Add table
Add a link
Reference in a new issue