diff --git a/README.md b/README.md index 886a9b92..1adae656 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,13 @@ # OpenAlice -Your one-person Wall Street. Alice is an AI trading agent that covers equities, crypto, commodities, forex, and macro — from research and analysis through position entry, ongoing management, to exit. +Your one-person Wall Street. Alice is an AI trading agent that covers equities, crypto, commodities, forex, and macro, from research and analysis through position entry, ongoing management, and exit. -- **Full-spectrum** — analyze and trade across asset classes. Multiple brokers combine into one unified workspace so you're never stuck with "I can see it but can't trade it." -- **Full-lifecycle** — not just entry signals. Research, position sizing, ongoing monitoring, risk management, and exit decisions — Alice covers the entire trading lifecycle, 24/7. -- **Full-control** — every trade goes through version history and safety checks, and requires your explicit approval before execution. You see every step, you can stop every step. +- **Full-spectrum** - analyze and trade across asset classes. Multiple brokers combine into one unified workspace so you're never stuck with "I can see it but can't trade it." +- **Full-lifecycle** - not just entry signals. Research, position sizing, ongoing monitoring, risk management, and exit decisions. Alice covers the entire trading lifecycle, 24/7. +- **Full-control** - every trade goes through version history and safety checks, and requires your explicit approval before execution. You see every step, and you can stop every step. -Alice runs on your own machine, because trading involves private keys and real money — that trust can't be outsourced. +Alice runs on your own machine, because trading involves private keys and real money. That trust cannot be outsourced.
{profile.model || 'Auto (subscription plan)'} {profile.model || 'Auto (CLI session)'}
@@ -27,144 +27,212 @@ Alice runs on your own machine, because trading involves private keys and real m
### Trading
-- **Unified Trading Account (UTA)** — multiple brokers (CCXT, Alpaca, Interactive Brokers) combine into unified workspaces. AI interacts with UTAs, never with brokers directly
-- **Trading-as-Git** — stage orders, commit with a message, push to execute. Full history reviewable with commit hashes
-- **Guard pipeline** — pre-execution safety checks (max position size, cooldown, symbol whitelist) per account
-- **Account snapshots** — periodic and event-driven state capture with equity curve visualization
+- **Unified Trading Account (UTA)** - multiple brokers (CCXT, Alpaca, Interactive Brokers) combine into unified workspaces. AI interacts with UTAs, never with brokers directly.
+- **Trading-as-Git** - stage orders, commit with a message, push to execute. Full history is reviewable with commit hashes.
+- **Guard pipeline** - pre-execution safety checks (max position size, cooldown, symbol whitelist) per account.
+- **Account snapshots** - periodic and event-driven state capture with equity curve visualization.
-### Research & Analysis
+### Research and Analysis
-- **Market data** — equity, crypto, commodity, currency, and macro data via TypeScript-native OpenBB engine. Unified cross-asset symbol search and technical indicator calculator
-- **Fundamental research** — company profiles, financial statements, ratios, analyst estimates, earnings calendar, insider trading, and market movers. Currently deepest for equities, expanding to other asset classes
-- **News** — background RSS collection with archive search
+- **Market data** - equity, crypto, commodity, currency, and macro data via the TypeScript-native OpenBB engine. Includes unified cross-asset symbol search and a technical indicator calculator.
+- **Fundamental research** - company profiles, financial statements, ratios, analyst estimates, earnings calendar, insider trading, and market movers.
+- **News** - background RSS collection with archive search.
### Automation
-An append-only event log sits at the center of Alice. All system activity — trades, messages, scheduled fires, heartbeat results — flows through as typed events with real-time subscriptions. Automation features are listeners on this bus:
+An append-only event log sits at the center of Alice. All system activity, trades, messages, scheduled fires, and heartbeat results, flows through as typed events with real-time subscriptions.
-- **Cron scheduling** — cron expressions, intervals, or one-shot timestamps. On fire, emits an event → listener routes through AI → delivers reply to your last-used channel
-- **Heartbeat** — a special cron job that periodically reviews market conditions, filters by active hours, and only reaches out when something matters
-- **Webhooks** — inbound event triggers from external systems (planned)
+- **Cron scheduling** - cron expressions, intervals, or one-shot timestamps. On fire, Alice routes the event through AI and delivers the reply to your last-used channel.
+- **Heartbeat** - a special cron job that periodically reviews market conditions, filters by active hours, and only reaches out when something matters.
+- **Webhooks** - inbound event triggers from external systems (planned).
### Interface
-- **Web UI** — chat with SSE streaming, sub-channels, portfolio dashboard with equity curve, and full config management
-- **Telegram** — mobile access with trading panel
-- **MCP server** — tool exposure for external agents
+- **Web UI** - chat with SSE streaming, sub-channels, portfolio dashboard with equity curve, and full config management.
+- **Telegram** - mobile access with a trading panel.
+- **MCP server** - tool exposure for external agents.
-### And More!
-
-- **Multi-provider AI** — Claude (Agent SDK with OAuth or API key) or Vercel AI SDK (Anthropic, OpenAI, Google), switchable at runtime
-- **Brain** — persistent memory and emotion tracking across conversations
-- **Evolution mode** — permission escalation that gives Alice full project access including Bash, enabling self-modification
+### And More
+- **Multi-provider AI** - Codex CLI, Claude (Agent SDK with OAuth or API key), or Vercel AI SDK (Anthropic, OpenAI, Google), switchable at runtime.
+- **Brain** - persistent memory and emotion tracking across conversations.
+- **Evolution mode** - permission escalation that gives Alice full project access including Bash, enabling self-modification.
## Architecture
Alice has four layers. Each layer only talks to the one directly above or below it.
```mermaid
-graph TB
- subgraph Interface["Interface — where users interact"]
- WEB[Web UI]
- TG[Telegram]
- MCP[MCP Server]
+graph LR
+ subgraph Providers
+ CX[Codex CLI]
+ AS[Claude / Agent SDK]
+ VS[Vercel AI SDK]
end
- subgraph Core["Core — orchestration & routing"]
- AC[AgentCenter]
+ subgraph Core
PR[ProviderRouter]
+ AC[AgentCenter]
TC[ToolCenter]
+ S[Session Store]
EL[Event Log]
CCR[ConnectorCenter]
end
- subgraph Domain["Domain — business logic"]
- subgraph UTA["UTA (Trading)"]
- TG2[Trading Git]
+ subgraph Domain
+ MD[Market Data]
+ AN[Analysis]
+ subgraph UTA[Unified Trading Account]
+ TR[Trading Git]
GD[Guards]
BK[Brokers]
+ SN[Snapshots]
end
- MD[Market Data]
- AN[Analysis]
- NC[News]
+ NC[News Collector]
BR[Brain]
+ BW[Browser]
end
- subgraph Automation["Automation — scheduled & event-driven"]
+ subgraph Tasks
CRON[Cron Engine]
HB[Heartbeat]
end
- WEB & TG & MCP --> AC
- AC --> PR
- PR -->|Claude| AS[Agent SDK]
- PR -->|Vercel| VS[Vercel AI SDK]
- TC --> Domain
- EL --> Automation
- CCR --> Interface
+ subgraph Interfaces
+ WEB[Web UI]
+ TG[Telegram]
+ MCP[MCP Server]
+ end
+
+ CX --> PR
+ AS --> PR
+ VS --> PR
+ PR --> AC
+ AC --> S
+ TC -->|Vercel tools| VS
+ TC -->|in-process MCP| AS
+ TC -->|MCP tools| MCP
+ MD --> AN
+ MD --> NC
+ AN --> TC
+ GD --> TR
+ TR --> BK
+ UTA --> TC
+ NC --> TC
+ BR --> TC
+ BW --> TC
+ CRON --> EL
+ HB --> CRON
+ EL --> CRON
+ CCR --> WEB
+ CCR --> TG
+ WEB --> AC
+ TG --> AC
+ MCP --> AC
```
-**Interface** — external surfaces (Web UI, Telegram, MCP). Users and external agents connect here. ConnectorCenter tracks last-used channel for delivery routing.
+**Providers** - interchangeable AI backends. Codex uses the local `codex exec` CLI and mounts Alice's MCP server into the Codex run, so the agent is genuinely Codex-driven. Claude uses `@anthropic-ai/claude-agent-sdk` with tools delivered via in-process MCP. Vercel AI SDK runs a `ToolLoopAgent` in-process with direct API calls.
-**Core** — AgentCenter routes all AI calls through ProviderRouter. ToolCenter is a shared registry — domain modules register tools there, and it exports them to whichever AI provider is active. EventLog is the central event bus.
+**Core** - AgentCenter routes all AI calls through ProviderRouter. ToolCenter is a shared registry, domain modules register tools there, and it exports them to whichever AI provider is active. EventLog is the central event bus.
-**Domain** — business logic. UTA is the trading workspace (see Key Concepts below). Market Data, Analysis, News, and Brain are independent modules, each exposed to AI through tool registrations.
+**Domain** - business logic. UTA is the trading workspace. Market Data, Analysis, News, and Brain are independent modules, each exposed to AI through tool registrations.
-**Automation** — listeners on the EventLog bus. Cron fires scheduled jobs, Heartbeat is a special cron job for periodic market review.
+**Automation** - listeners on the EventLog bus. Cron fires scheduled jobs, and Heartbeat is a special cron job for periodic market review.
## Key Concepts
-**UTA (Unified Trading Account)** — The core abstraction. Each UTA wraps a broker connection, operation history, guard pipeline, and snapshot scheduler into a single self-contained workspace. AI and the frontend interact with UTAs exclusively — brokers are internal implementation details. Multiple UTAs work like independent repositories: one for Alpaca US equities, one for Bybit crypto, each with its own history and guards.
+**UTA (Unified Trading Account)** - The core abstraction. Each UTA wraps a broker connection, operation history, guard pipeline, and snapshot scheduler into a single self-contained workspace. AI and the frontend interact with UTAs exclusively, brokers are internal implementation details.
-**Trading-as-Git** — The workflow inside each UTA. Stage orders, commit with a message, then push to execute. Push runs guards, dispatches to the broker, snapshots account state, and records a commit with an 8-char hash. Full history is reviewable like `git log` / `git show`.
+**Trading-as-Git** - The workflow inside each UTA. Stage orders, commit with a message, then push to execute. Push runs guards, dispatches to the broker, snapshots account state, and records a commit with an 8-char hash.
-**Guard** — A pre-execution safety check that runs inside a UTA before orders reach the broker. Guards enforce limits (max position size, cooldown between trades, symbol whitelist) and are configured per-account. Think of it as ESLint for trading — automated rules that catch problems before they go live.
+**Guard** - A pre-execution safety check that runs inside a UTA before orders reach the broker. Guards enforce limits such as max position size, cooldown between trades, and symbol whitelists.
-**Heartbeat** — A periodic check-in where Alice reviews market conditions and decides whether to send you a message. Useful for monitoring positions overnight or tracking macro events — Alice reaches out when something matters, stays quiet when it doesn't.
+**Heartbeat** - A periodic check-in where Alice reviews market conditions and decides whether to send you a message.
-**Connector** — An external interface through which users interact with Alice. Built-in: Web UI, Telegram, MCP Ask. Delivery always goes to the channel you last spoke through.
+**Connector** - An external interface through which users interact with Alice. Built-in connectors include Web UI, Telegram, and MCP Ask. Delivery always goes to the channel you last spoke through.
-**AI Provider** — The AI backend that powers Alice. Claude (via Agent SDK, supports OAuth login or API key) or Vercel AI SDK (Anthropic, OpenAI, Google). Switchable at runtime — no restart needed.
+**AI Provider** - The AI backend that powers Alice. The default is Codex CLI (`codex exec`) with Alice's MCP tools mounted into the local Codex session. Claude and Vercel AI SDK are also available, and providers can be switched at runtime with no restart needed.
## Quick Start
-Prerequisites: Node.js 22+, pnpm 10+, [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated.
+Prerequisites: Node.js 22+, pnpm 10+, and [Codex CLI](https://developers.openai.com/codex/cli) installed and authenticated.
```bash
git clone https://github.com/TraderAlice/OpenAlice.git
cd OpenAlice
-pnpm install && pnpm build
-pnpm dev
+codex login
+corepack pnpm install && corepack pnpm build
+corepack pnpm dev
+```
+
+Open [localhost:3002](http://localhost:3002) and start chatting. No API keys or extra provider setup are needed. The default profile uses your local Codex CLI session.
+
+```bash
+corepack pnpm dev # start backend (port 3002) with watch mode
+corepack pnpm dev:ui # start frontend dev server (port 5173) with hot reload
+corepack pnpm build # production build (backend + UI)
+corepack pnpm test # run tests
```
-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).
+> **Note:** Port 3002 serves the UI only after `pnpm build`. For frontend development, use `pnpm dev:ui` (port 5173), which proxies to the backend and provides hot reload.
+
+## Daily Workflow
+
+For normal daily use, the shortest path is:
+
+```bash
+cd OpenAlice
+codex login # only when needed
+corepack pnpm dev
+```
+
+Then open [localhost:3002](http://localhost:3002) and chat with the default profile. That profile routes every turn through local Codex CLI, and Codex reaches Alice's trading, research, browser, and session tools through the built-in MCP server on port `3001`.
+
+If you want a different backend later, open the AI Provider page in the Web UI and switch profiles there. No restart is required.
+
+On Windows, you can use the bundled launcher instead:
+
+```powershell
+powershell -ExecutionPolicy Bypass -File .\scripts\start-openalice.ps1
+```
+
+Or:
+
+```bat
+.\scripts\start-openalice.cmd
+```
+
+Or, if you prefer npm scripts:
+
+```bash
+corepack pnpm dev:codex
+```
## Configuration
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 (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.
+**AI Provider** - The default provider is Codex CLI, which uses your local `codex login` session and runs Alice through `codex exec` with Alice's MCP tools attached automatically. To use Claude Agent SDK or the [Vercel AI SDK](https://sdk.vercel.ai/docs) instead, switch `ai-provider-manager.json` or use the Web UI. Providers can be switched at runtime with no restart.
-**Trading** — Unified Trading Account (UTA) architecture. Each account in `accounts.json` becomes a UTA with its own broker connection, git history, and guard config. Broker-specific settings live in the `brokerConfig` field — each broker type declares its own schema and validates it internally.
+**Trading** - Unified Trading Account (UTA) architecture. Each account in `accounts.json` becomes a UTA with its own broker connection, git history, and guard config.
| 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 (`agent-sdk` or `vercel-ai-sdk`), login method, switchable at runtime |
-| `accounts.json` | Trading accounts with `type`, `enabled`, `guards`, and `brokerConfig` (broker-specific settings) |
+| `ai-provider-manager.json` | Active AI provider profile (`codex`, `agent-sdk`, or `vercel-ai-sdk`), login method, switchable at runtime |
+| `accounts.json` | Trading accounts with `type`, `enabled`, `guards`, and `brokerConfig` |
| `connectors.json` | Web/MCP server ports, MCP Ask enable |
-| `telegram.json` | Telegram bot credentials + enable |
+| `telegram.json` | Telegram bot credentials and enable flag |
| `web-subchannels.json` | Web UI sub-channel definitions with per-channel AI provider overrides |
| `tools.json` | Tool enable/disable configuration |
-| `market-data.json` | Data backend (`typebb-sdk` / `openbb-api`), per-asset-class providers, provider API keys, embedded HTTP server config |
+| `market-data.json` | Data backend configuration and provider API keys |
| `news.json` | RSS feeds, fetch interval, retention period |
| `snapshot.json` | Account snapshot interval and retention |
-| `compaction.json` | Context window limits, auto-compaction thresholds |
-| `heartbeat.json` | Heartbeat enable/disable, interval, active hours |
+| `compaction.json` | Context window limits and auto-compaction thresholds |
+| `heartbeat.json` | Heartbeat enable/disable, interval, and active hours |
-Persona and heartbeat prompts use a **default + user override** pattern:
+Persona and heartbeat prompts use a default plus user override pattern:
| Default (git-tracked) | User override (gitignored) |
|------------------------|---------------------------|
@@ -179,13 +247,13 @@ OpenAlice is a pnpm monorepo with Turborepo build orchestration. See [docs/proje
## Roadmap to v1
-OpenAlice is in pre-release. All planned v1 milestones are now complete — remaining work is testing and stabilization.
+OpenAlice is in pre-release. All planned v1 milestones are now complete. Remaining work is testing and stabilization.
-- [x] **Tool confirmation** — achieved through Trading-as-Git's push approval mechanism. Order execution requires explicit user approval at the push step, similar to merging a PR
-- [x] **Trading-as-Git stable interface** — the core workflow (stage → commit → push → approval) is stable and running in production
-- [x] **IBKR broker** — Interactive Brokers integration via TWS/Gateway. `IbkrBroker` bridges the callback-based `@traderalice/ibkr` SDK to the Promise-based `IBroker` interface via `RequestBridge`. Supports all IBroker methods including conId-based contract resolution
-- [x] **Account snapshot & analytics** — periodic and event-driven snapshots with equity curve visualization, configurable intervals, and carry-forward for data gaps
+- [x] **Tool confirmation** - achieved through Trading-as-Git's push approval mechanism.
+- [x] **Trading-as-Git stable interface** - the core workflow is stable and running in production.
+- [x] **IBKR broker** - Interactive Brokers integration via TWS/Gateway.
+- [x] **Account snapshot and analytics** - periodic and event-driven snapshots with equity curve visualization.
## Star History
-[](https://star-history.com/#TraderAlice/OpenAlice&Date)
\ No newline at end of file
+[](https://star-history.com/#TraderAlice/OpenAlice&Date)
diff --git a/package.json b/package.json
index c590852a..a774413f 100644
--- a/package.json
+++ b/package.json
@@ -5,9 +5,13 @@
"type": "module",
"scripts": {
"dev": "tsx watch src/main.ts",
- "dev:ui": "pnpm --filter open-alice-ui dev",
- "predev": "turbo run build --filter=@traderalice/opentypebb --filter=@traderalice/ibkr",
- "build": "turbo run build && tsup src/main.ts --format esm --dts",
+ "dev:ui": "corepack pnpm --filter open-alice-ui dev",
+ "dev:codex": "powershell -ExecutionPolicy Bypass -File ./scripts/start-openalice.ps1",
+ "build:deps": "corepack pnpm --filter @traderalice/opentypebb build && corepack pnpm --filter @traderalice/ibkr build",
+ "build:ui": "corepack pnpm --filter open-alice-ui build",
+ "build:server": "tsup src/main.ts --format esm --dts",
+ "predev": "corepack pnpm build:deps",
+ "build": "corepack pnpm build:deps && corepack pnpm build:ui && corepack pnpm build:server",
"start": "node dist/main.js",
"test": "vitest run",
"test:e2e": "vitest run --config vitest.e2e.config.ts",
@@ -36,8 +40,8 @@
"@alpacahq/alpaca-trade-api": "^3.1.3",
"@anthropic-ai/claude-agent-sdk": "^0.2.72",
"@grammyjs/auto-retry": "^2.0.2",
- "@hono/node-server": "^1.19.11",
- "@modelcontextprotocol/sdk": "^1.27.1",
+ "@hono/node-server": "^1.19.14",
+ "@modelcontextprotocol/sdk": "^1.29.0",
"@sinclair/typebox": "0.34.48",
"@traderalice/ibkr": "workspace:*",
"@traderalice/opentypebb": "workspace:*",
@@ -49,7 +53,7 @@
"express": "^5.2.1",
"file-type": "^21.3.2",
"grammy": "^1.40.0",
- "hono": "^4.12.7",
+ "hono": "^4.12.14",
"json5": "^2.2.3",
"openai": "^6.33.0",
"pino": "^10.3.1",
@@ -62,8 +66,12 @@
},
"pnpm": {
"overrides": {
- "@alpacahq/alpaca-trade-api>axios": "^0.30.3",
- "@alpacahq/alpaca-trade-api>eslint": "-"
+ "@alpacahq/alpaca-trade-api>axios": "^1.15.0",
+ "@alpacahq/alpaca-trade-api>eslint": "-",
+ "follow-redirects": "^1.16.0",
+ "@alpacahq/alpaca-trade-api>lodash": "^4.18.1",
+ "@modelcontextprotocol/sdk>express-rate-limit": "^8.3.2",
+ "path-to-regexp": "^8.4.2"
}
},
"devDependencies": {
diff --git a/packages/ibkr/package.json b/packages/ibkr/package.json
index 346ba031..3bec4182 100644
--- a/packages/ibkr/package.json
+++ b/packages/ibkr/package.json
@@ -18,7 +18,7 @@
"directory": "packages/ibkr"
},
"scripts": {
- "build": "rm -rf dist && tsc",
+ "build": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && tsc",
"test": "vitest run --config vitest.config.ts",
"test:e2e": "vitest run --config vitest.e2e.config.ts",
"test:all": "vitest run --config vitest.config.ts && vitest run --config vitest.e2e.config.ts",
diff --git a/packages/opentypebb/package.json b/packages/opentypebb/package.json
index e9fac0da..3dc2840d 100644
--- a/packages/opentypebb/package.json
+++ b/packages/opentypebb/package.json
@@ -42,8 +42,8 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
- "@hono/node-server": "^1.13.8",
- "hono": "^4.12.7",
+ "@hono/node-server": "^1.19.14",
+ "hono": "^4.12.14",
"undici": "^7.24.4",
"yahoo-finance2": "^3.13.1",
"zod": "^3.24.2"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4d061825..37eae5a1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -5,8 +5,12 @@ settings:
excludeLinksFromLockfile: false
overrides:
- '@alpacahq/alpaca-trade-api>axios': ^0.30.3
+ '@alpacahq/alpaca-trade-api>axios': ^1.15.0
'@alpacahq/alpaca-trade-api>eslint': '-'
+ follow-redirects: ^1.16.0
+ '@alpacahq/alpaca-trade-api>lodash': ^4.18.1
+ '@modelcontextprotocol/sdk>express-rate-limit': ^8.3.2
+ path-to-regexp: ^8.4.2
importers:
@@ -31,11 +35,11 @@ importers:
specifier: ^2.0.2
version: 2.0.2(grammy@1.40.0)
'@hono/node-server':
- specifier: ^1.19.11
- version: 1.19.11(hono@4.12.7)
+ specifier: ^1.19.14
+ version: 1.19.14(hono@4.12.14)
'@modelcontextprotocol/sdk':
- specifier: ^1.27.1
- version: 1.27.1(zod@4.3.6)
+ specifier: ^1.29.0
+ version: 1.29.0(zod@4.3.6)
'@sinclair/typebox':
specifier: 0.34.48
version: 0.34.48
@@ -70,8 +74,8 @@ importers:
specifier: ^1.40.0
version: 1.40.0
hono:
- specifier: ^4.12.7
- version: 4.12.7
+ specifier: ^4.12.14
+ version: 4.12.14
json5:
specifier: ^2.2.3
version: 2.2.3
@@ -177,11 +181,11 @@ importers:
packages/opentypebb:
dependencies:
'@hono/node-server':
- specifier: ^1.13.8
- version: 1.19.11(hono@4.12.7)
+ specifier: ^1.19.14
+ version: 1.19.14(hono@4.12.14)
hono:
- specifier: ^4.12.7
- version: 4.12.7
+ specifier: ^4.12.14
+ version: 4.12.14
undici:
specifier: ^7.24.4
version: 7.24.4
@@ -790,8 +794,8 @@ packages:
'@grammyjs/types@3.24.0':
resolution: {integrity: sha512-qQIEs4lN5WqUdr4aT8MeU6UFpMbGYAvcvYSW1A4OO1PABGJQHz/KLON6qvpf+5RxaNDQBxiY2k2otIhg/AG7RQ==}
- '@hono/node-server@1.19.11':
- resolution: {integrity: sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==}
+ '@hono/node-server@1.19.14':
+ resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==}
engines: {node: '>=18.14.1'}
peerDependencies:
hono: ^4
@@ -965,8 +969,8 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
- '@modelcontextprotocol/sdk@1.27.1':
- resolution: {integrity: sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA==}
+ '@modelcontextprotocol/sdk@1.29.0':
+ resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==}
engines: {node: '>=18'}
peerDependencies:
'@cfworker/json-schema': ^4.1.1
@@ -1565,8 +1569,8 @@ packages:
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
engines: {node: '>=8.0.0'}
- axios@0.30.3:
- resolution: {integrity: sha512-5/tmEb6TmE/ax3mdXBc/Mi6YdPGxQsv+0p5YlciXWt3PHIn0VamqCXhRMtScnwY3lbgSXLneOuXAKUhgmSRpwg==}
+ axios@1.15.0:
+ resolution: {integrity: sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==}
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
@@ -1900,8 +1904,8 @@ packages:
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
engines: {node: '>=12.0.0'}
- express-rate-limit@8.2.1:
- resolution: {integrity: sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==}
+ express-rate-limit@8.3.2:
+ resolution: {integrity: sha512-77VmFeJkO0/rvimEDuUC5H30oqUC4EyOhyGccfqoLebB0oiEYfM7nwPrsDsBL1gsTpwfzX8SFy2MT3TDyRq+bg==}
engines: {node: '>= 16'}
peerDependencies:
express: '>= 4.11'
@@ -1954,8 +1958,8 @@ packages:
fix-dts-default-cjs-exports@1.0.1:
resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==}
- follow-redirects@1.15.11:
- resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==}
+ follow-redirects@1.16.0:
+ resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
@@ -2029,8 +2033,8 @@ packages:
resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==}
engines: {node: '>=12.0.0'}
- hono@4.12.7:
- resolution: {integrity: sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw==}
+ hono@4.12.14:
+ resolution: {integrity: sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==}
engines: {node: '>=16.9.0'}
html-encoding-sniffer@6.0.0:
@@ -2068,8 +2072,8 @@ packages:
resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
engines: {node: '>=12'}
- ip-address@10.0.1:
- resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==}
+ ip-address@10.1.0:
+ resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==}
engines: {node: '>= 12'}
ipaddr.js@1.9.1:
@@ -2237,8 +2241,8 @@ packages:
resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- lodash@4.17.23:
- resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==}
+ lodash@4.18.1:
+ resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
long@5.3.2:
resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
@@ -2402,8 +2406,8 @@ packages:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
- path-to-regexp@8.3.0:
- resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==}
+ path-to-regexp@8.4.2:
+ resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==}
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
@@ -2482,8 +2486,9 @@ packages:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
- proxy-from-env@1.1.0:
- resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+ proxy-from-env@2.1.0:
+ resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==}
+ engines: {node: '>=10'}
psl@1.15.0:
resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
@@ -3227,11 +3232,11 @@ snapshots:
'@alpacahq/alpaca-trade-api@3.1.3':
dependencies:
- axios: 0.30.3
+ axios: 1.15.0
dotenv: 6.2.0
events: 3.3.0
just-extend: 4.2.1
- lodash: 4.17.23
+ lodash: 4.18.1
minimist: 1.2.8
msgpack5: 5.3.2
nats: 1.4.12
@@ -3601,9 +3606,9 @@ snapshots:
'@grammyjs/types@3.24.0': {}
- '@hono/node-server@1.19.11(hono@4.12.7)':
+ '@hono/node-server@1.19.14(hono@4.12.14)':
dependencies:
- hono: 4.12.7
+ hono: 4.12.14
'@img/colour@1.0.0': {}
@@ -3720,9 +3725,9 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
- '@modelcontextprotocol/sdk@1.27.1(zod@4.3.6)':
+ '@modelcontextprotocol/sdk@1.29.0(zod@4.3.6)':
dependencies:
- '@hono/node-server': 1.19.11(hono@4.12.7)
+ '@hono/node-server': 1.19.14(hono@4.12.14)
ajv: 8.18.0
ajv-formats: 3.0.1(ajv@8.18.0)
content-type: 1.0.5
@@ -3731,8 +3736,8 @@ snapshots:
eventsource: 3.0.7
eventsource-parser: 3.0.6
express: 5.2.1
- express-rate-limit: 8.2.1(express@5.2.1)
- hono: 4.12.7
+ express-rate-limit: 8.3.2(express@5.2.1)
+ hono: 4.12.14
jose: 6.1.3
json-schema-typed: 8.0.2
pkce-challenge: 5.0.1
@@ -4263,11 +4268,11 @@ snapshots:
atomic-sleep@1.0.0: {}
- axios@0.30.3:
+ axios@1.15.0:
dependencies:
- follow-redirects: 1.15.11
+ follow-redirects: 1.16.0
form-data: 4.0.5
- proxy-from-env: 1.1.0
+ proxy-from-env: 2.1.0
transitivePeerDependencies:
- debug
@@ -4601,10 +4606,10 @@ snapshots:
expect-type@1.3.0: {}
- express-rate-limit@8.2.1(express@5.2.1):
+ express-rate-limit@8.3.2(express@5.2.1):
dependencies:
express: 5.2.1
- ip-address: 10.0.1
+ ip-address: 10.1.0
express@5.2.1:
dependencies:
@@ -4695,7 +4700,7 @@ snapshots:
mlly: 1.8.0
rollup: 4.57.1
- follow-redirects@1.15.11: {}
+ follow-redirects@1.16.0: {}
form-data@4.0.5:
dependencies:
@@ -4766,7 +4771,7 @@ snapshots:
highlight.js@11.11.1: {}
- hono@4.12.7: {}
+ hono@4.12.14: {}
html-encoding-sniffer@6.0.0:
dependencies:
@@ -4802,7 +4807,7 @@ snapshots:
internmap@2.0.3: {}
- ip-address@10.0.1: {}
+ ip-address@10.1.0: {}
ipaddr.js@1.9.1: {}
@@ -4932,7 +4937,7 @@ snapshots:
load-tsconfig@0.2.5: {}
- lodash@4.17.23: {}
+ lodash@4.18.1: {}
long@5.3.2: {}
@@ -5058,7 +5063,7 @@ snapshots:
path-key@3.1.1: {}
- path-to-regexp@8.3.0: {}
+ path-to-regexp@8.4.2: {}
pathe@2.0.3: {}
@@ -5142,7 +5147,7 @@ snapshots:
forwarded: 0.2.0
ipaddr.js: 1.9.1
- proxy-from-env@1.1.0: {}
+ proxy-from-env@2.1.0: {}
psl@1.15.0:
dependencies:
@@ -5284,7 +5289,7 @@ snapshots:
depd: 2.0.0
is-promise: 4.0.0
parseurl: 1.3.3
- path-to-regexp: 8.3.0
+ path-to-regexp: 8.4.2
transitivePeerDependencies:
- supports-color
diff --git a/scripts/start-openalice.cmd b/scripts/start-openalice.cmd
new file mode 100644
index 00000000..1e80f7a2
--- /dev/null
+++ b/scripts/start-openalice.cmd
@@ -0,0 +1,2 @@
+@echo off
+powershell -ExecutionPolicy Bypass -File "%~dp0start-openalice.ps1" %*
diff --git a/scripts/start-openalice.ps1 b/scripts/start-openalice.ps1
new file mode 100644
index 00000000..68fd899a
--- /dev/null
+++ b/scripts/start-openalice.ps1
@@ -0,0 +1,44 @@
+param(
+ [switch]$NoBrowser
+)
+
+$ErrorActionPreference = "Stop"
+
+$repoRoot = Split-Path -Parent $PSScriptRoot
+Set-Location $repoRoot
+
+function Assert-Command($name) {
+ if (-not (Get-Command $name -ErrorAction SilentlyContinue)) {
+ throw "Required command not found: $name"
+ }
+}
+
+function Assert-PortAvailable($port) {
+ $existing = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1
+ if ($existing) {
+ throw "Port $port is already in use by PID $($existing.OwningProcess). Stop the running service first."
+ }
+}
+
+Assert-Command "codex"
+Assert-Command "corepack"
+
+$loginStatus = & cmd /c "codex login status 2>&1"
+if ($LASTEXITCODE -ne 0 -or ($loginStatus -join "`n") -notmatch "Logged in") {
+ Write-Host "Codex is not logged in yet. Run `codex login` first." -ForegroundColor Yellow
+ exit 1
+}
+
+Assert-PortAvailable 3001
+Assert-PortAvailable 3002
+Assert-PortAvailable 6901
+
+if (-not $NoBrowser) {
+ Start-Job -ScriptBlock {
+ Start-Sleep -Seconds 6
+ Start-Process "http://localhost:3002"
+ } | Out-Null
+}
+
+Write-Host "Starting Open Alice with Codex CLI..." -ForegroundColor Cyan
+& corepack pnpm dev
diff --git a/src/ai-providers/codex/__test__/codex.e2e.spec.ts b/src/ai-providers/codex/__test__/codex.e2e.spec.ts
deleted file mode 100644
index 7caecb64..00000000
--- a/src/ai-providers/codex/__test__/codex.e2e.spec.ts
+++ /dev/null
@@ -1,175 +0,0 @@
-/**
- * Codex provider E2E tests — verifies real API communication.
- *
- * Requires ~/.codex/auth.json (run `codex login` first).
- * Skips gracefully if auth is not configured.
- *
- * Run: pnpm test:e2e
- */
-
-import { describe, it, expect, beforeAll, beforeEach } from 'vitest'
-import OpenAI from 'openai'
-import { readFile } from 'node:fs/promises'
-import { join } from 'node:path'
-import { homedir } from 'node:os'
-
-// ==================== Setup ====================
-
-const OAUTH_BASE_URL = 'https://chatgpt.com/backend-api/codex'
-const MODEL = 'gpt-5.4-mini' // Use mini for faster/cheaper e2e
-
-let client: OpenAI | null = null
-
-async function tryLoadToken(): Promise