Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ src/
│ ├── media-store.ts # Media file persistence
│ └── types.ts # Plugin, EngineContext interfaces
├── ai-providers/
│ ├── claude-code/ # Claude Code CLI subprocess
│ ├── vercel-ai-sdk/ # Vercel AI SDK ToolLoopAgent
│ └── agent-sdk/ # Agent SDK (@anthropic-ai/claude-agent-sdk)
│ └── agent-sdk/ # Claude backend (@anthropic-ai/claude-agent-sdk, supports OAuth + API key)
├── domain/
│ ├── market-data/ # Structured data layer (typebb in-process + OpenBB API remote)
│ ├── trading/ # Unified multi-account trading, guard pipeline, git-like commits
Expand Down Expand Up @@ -72,10 +71,9 @@ Two layers (Engine was removed):

1. **AgentCenter** (`core/agent-center.ts`) — top-level orchestration. Manages sessions, compaction, and routes calls through GenerateRouter. Exposes `ask()` (stateless) and `askWithSession()` (with history).

2. **GenerateRouter** (`core/ai-provider-manager.ts`) — reads `ai-provider.json` on each call, resolves to active provider. Three backends:
- Claude Code CLI (`inputKind: 'text'`)
- Vercel AI SDK (`inputKind: 'messages'`)
- Agent SDK (`inputKind: 'text'`)
2. **GenerateRouter** (`core/ai-provider-manager.ts`) — reads `ai-provider.json` on each call, resolves to active provider. Two backends:
- Agent SDK (`inputKind: 'text'`) — Claude via @anthropic-ai/claude-agent-sdk, tools via in-process MCP
- Vercel AI SDK (`inputKind: 'messages'`) — direct API calls, tools via Vercel tool system

**AIProvider interface**: `ask(prompt)` for one-shot, `generate(input, opts)` for streaming `ProviderEvent` (tool_use / tool_result / text / done). Optional `compact()` for provider-native compaction.

Expand Down
23 changes: 10 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Your one-person Wall Street. Alice is an AI trading agent that gives you your ow

## Features

- **Multi-provider AI** — switch between Claude Code CLI, Vercel AI SDK, and Agent SDK at runtime, no restart needed
- **Multi-provider AI** — switch between Claude (via Agent SDK with OAuth or API key) and Vercel AI SDK at runtime, no restart needed
- **Unified Trading Account (UTA)** — each trading account is a self-contained entity that owns its broker connection, git-like operation history, and guard pipeline. AI interacts with UTAs, never with brokers directly. All order types use IBKR's type system (`@traderalice/ibkr`) as the single source of truth, with Alpaca and CCXT adapting to it
- **Trading-as-Git** — stage orders, commit with a message, push to execute. Every commit gets an 8-char hash. Full history reviewable via `tradingLog` / `tradingShow`
- **Guard pipeline** — pre-execution safety checks (max position size, cooldown, symbol whitelist) that run inside each UTA before orders reach the broker
Expand All @@ -39,7 +39,7 @@ Your one-person Wall Street. Alice is an AI trading agent that gives you your ow

## Key Concepts

**Provider** — The AI backend that powers Alice. Claude Code (subprocess), Vercel AI SDK (in-process), or Agent SDK (`@anthropic-ai/claude-agent-sdk`). Switchable at runtime via `ai-provider.json`.
**Provider** — The AI backend that powers Alice. Claude (via `@anthropic-ai/claude-agent-sdk`, supports OAuth login or API key) or Vercel AI SDK (direct API calls to Anthropic, OpenAI, Google). Switchable at runtime via `ai-provider.json`.

**Extension** — A self-contained tool package registered in ToolCenter. Each extension owns its tools, state, and persistence. Examples: trading, brain, analysis-kit.

Expand All @@ -64,9 +64,8 @@ Your one-person Wall Street. Alice is an AI trading agent that gives you your ow
```mermaid
graph LR
subgraph Providers
CC[Claude Code CLI]
AS[Claude / Agent SDK]
VS[Vercel AI SDK]
AS[Agent SDK]
end

subgraph Core
Expand Down Expand Up @@ -102,12 +101,12 @@ graph LR
MCP[MCP Server]
end

CC --> PR
VS --> PR
AS --> PR
VS --> PR
PR --> AC
AC --> S
TC -->|Vercel tools| VS
TC -->|in-process MCP| AS
TC -->|MCP tools| MCP
OBB --> AK
OBB --> NC
Expand All @@ -128,7 +127,7 @@ graph LR
MCP --> AC
```

**Providers** — interchangeable AI backends. Claude Code spawns `claude -p` as a subprocess; Vercel AI SDK runs a `ToolLoopAgent` in-process; Agent SDK uses `@anthropic-ai/claude-agent-sdk`. `ProviderRouter` reads `ai-provider.json` on each call to select the active backend at runtime.
**Providers** — interchangeable AI backends. Claude (Agent SDK) uses `@anthropic-ai/claude-agent-sdk` with tools delivered via in-process MCP — supports Claude Pro/Max OAuth login or API key. Vercel AI SDK runs a `ToolLoopAgent` in-process with direct API calls. `ProviderRouter` reads `ai-provider.json` on each call to select the active backend at runtime.

**Core** — `AgentCenter` is the top-level orchestration center that routes all calls (both stateless and session-aware) through `ProviderRouter`. `ToolCenter` is a centralized tool registry — extensions register tools there, and it exports them in Vercel AI SDK and MCP formats. `EventLog` provides persistent append-only event storage (JSONL) with real-time subscriptions and crash recovery. `ConnectorCenter` tracks which channel the user last spoke through.

Expand All @@ -149,7 +148,7 @@ pnpm install && pnpm build
pnpm dev
```

Open [localhost:3002](http://localhost:3002) and start chatting. No API keys or config needed — the default setup uses Claude Code as the AI backend with your existing login.
Open [localhost:3002](http://localhost:3002) and start chatting. No API keys or config needed — the default setup uses your local Claude Code login (Claude Pro/Max subscription).

```bash
pnpm dev # start backend (port 3002) with watch mode
Expand All @@ -164,16 +163,15 @@ pnpm test # run tests

All config lives in `data/config/` as JSON files with Zod validation. Missing files fall back to sensible defaults. You can edit these files directly or use the Web UI.

**AI Provider** — The default provider is Claude Code (`claude -p` subprocess). To use the [Vercel AI SDK](https://sdk.vercel.ai/docs) instead (Anthropic, OpenAI, Google, etc.), switch `ai-provider.json` to `vercel-ai-sdk` and add your API key to `api-keys.json`. A third option, Agent SDK (`@anthropic-ai/claude-agent-sdk`), is also available via `agent-sdk`.
**AI Provider** — The default provider is Claude (Agent SDK), which uses your local Claude Code login — no API key needed. To use the [Vercel AI SDK](https://sdk.vercel.ai/docs) instead (Anthropic, OpenAI, Google, etc.), switch `ai-provider.json` to `vercel-ai-sdk` and add your API key. Both can be switched at runtime via the Web UI.

**Trading** — Unified Trading Account (UTA) architecture. Define platforms in `platforms.json` (CCXT exchanges, Alpaca), then create accounts in `accounts.json` referencing a platform. Each account becomes a UTA with its own git history and guard config. Legacy `crypto.json` and `securities.json` are still supported.

| File | Purpose |
|------|---------|
| `engine.json` | Trading pairs, tick interval, timeframe |
| `agent.json` | Max agent steps, evolution mode toggle, Claude Code tool permissions |
| `ai-provider.json` | Active AI provider (`claude-code`, `vercel-ai-sdk`, or `agent-sdk`), switchable at runtime |
| `api-keys.json` | AI provider API keys (Anthropic, OpenAI, Google) — only needed for Vercel AI SDK mode |
| `ai-provider.json` | Active AI provider (`agent-sdk` or `vercel-ai-sdk`), login method, switchable at runtime |
| `platforms.json` | Trading platform definitions (CCXT exchanges, Alpaca) |
| `accounts.json` | Trading account credentials and guard config, references platforms |
| `crypto.json` | CCXT exchange config + API keys, allowed symbols, guards |
Expand Down Expand Up @@ -218,9 +216,8 @@ src/
media-store.ts # Media file persistence
types.ts # Plugin, EngineContext interfaces
ai-providers/
claude-code/ # Claude Code CLI subprocess wrapper
vercel-ai-sdk/ # Vercel AI SDK ToolLoopAgent wrapper
agent-sdk/ # Agent SDK (@anthropic-ai/claude-agent-sdk) wrapper
agent-sdk/ # Claude backend (@anthropic-ai/claude-agent-sdk, OAuth + API key)
extension/
analysis-kit/ # Indicator calculator and market data tools
equity/ # Equity fundamentals and data adapter
Expand Down
19 changes: 15 additions & 4 deletions src/ai-providers/agent-sdk/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { query as sdkQuery } from '@anthropic-ai/claude-agent-sdk'
import type { McpSdkServerConfigWithInstance } from '@anthropic-ai/claude-agent-sdk'
import { pino } from 'pino'
import type { ContentBlock } from '../../core/session.js'

import { readAIProviderConfig } from '../../core/config.js'

const logger = pino({
Expand Down Expand Up @@ -37,6 +38,7 @@ export interface AgentSdkOverride {
model?: string
apiKey?: string
baseUrl?: string
loginMethod?: 'api-key' | 'claudeai'
}

export interface AgentSdkMessage {
Expand Down Expand Up @@ -115,12 +117,20 @@ export async function askAgentSdk(
const finalAllowed = allowedTools.length > 0 ? allowedTools : modeAllowed
const finalDisallowed = [...disallowedTools, ...modeDisallowed]

// Build env with API key injection
// Build env with authentication
const aiConfig = await readAIProviderConfig()
const apiKey = override?.apiKey ?? aiConfig.apiKeys.anthropic
const baseUrl = override?.baseUrl ?? aiConfig.baseUrl
const loginMethod = override?.loginMethod ?? aiConfig.loginMethod ?? 'api-key'
const isOAuthMode = loginMethod === 'claudeai'

const env: Record<string, string | undefined> = { ...process.env }
if (apiKey) env.ANTHROPIC_API_KEY = apiKey
if (isOAuthMode) {
// Force OAuth by removing any inherited API key
delete env.ANTHROPIC_API_KEY
} else {
const apiKey = override?.apiKey ?? aiConfig.apiKeys.anthropic
if (apiKey) env.ANTHROPIC_API_KEY = apiKey
}
const baseUrl = override?.baseUrl ?? aiConfig.baseUrl
if (baseUrl) env.ANTHROPIC_BASE_URL = baseUrl

// MCP servers
Expand Down Expand Up @@ -148,6 +158,7 @@ export async function askAgentSdk(
permissionMode: 'bypassPermissions',
allowDangerouslySkipPermissions: true,
persistSession: false,
...(loginMethod === 'claudeai' ? { forceLoginMethod: 'claudeai' as const } : {}),
},
})) {
// assistant message — extract tool_use + text blocks
Expand Down
81 changes: 0 additions & 81 deletions src/ai-providers/claude-code/claude-code-provider.ts

This file was deleted.

3 changes: 0 additions & 3 deletions src/ai-providers/claude-code/index.ts

This file was deleted.

Loading
Loading