feat(usage): 在用量查询页面添加服务端时间显示
- 在 UI 中添加服务端时间显示组件,包含样式和国际化支持 - 修改用量 API 返回数据,始终包含 serverTime 字段 - 更新前端 JavaScript 以解析并显示服务端时间 - 新增 OpenClaw 配置指南文档(中/英/日文)
This commit is contained in:
parent
d9f3a8002f
commit
d6c2bd7919
11 changed files with 692 additions and 6 deletions
213
OPENCLAW_CONFIG_GUIDE-JA.md
Normal file
213
OPENCLAW_CONFIG_GUIDE-JA.md
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
# OpenClaw 設定ガイド
|
||||||
|
|
||||||
|
OpenClaw で AIClient-2-API を使用するためのクイック設定ガイド。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 前提条件
|
||||||
|
|
||||||
|
1. AIClient-2-API サービスを起動
|
||||||
|
2. Web UI (`http://localhost:3000`) で少なくとも1つのプロバイダーを設定
|
||||||
|
3. 設定ファイルから API Key を記録
|
||||||
|
4. OpenClaw をインストール
|
||||||
|
- Docker バージョン:[justlikemaki/openclaw-docker-cn-im](https://hub.docker.com/r/justlikemaki/openclaw-docker-cn-im)
|
||||||
|
- または他のインストール方法を使用
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 設定方法
|
||||||
|
|
||||||
|
### 方法1:OpenAI プロトコル(推奨)
|
||||||
|
|
||||||
|
**使用例**:Gemini モデルを使用する場合
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
env: {
|
||||||
|
AICLIENT2API_KEY: "your-api-key"
|
||||||
|
},
|
||||||
|
agents: {
|
||||||
|
defaults: {
|
||||||
|
model: { primary: "aiclient2api/gemini-3-flash-preview" },
|
||||||
|
models: {
|
||||||
|
"aiclient2api/gemini-3-flash-preview": { alias: "Gemini 3 Flash" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
models: {
|
||||||
|
mode: "merge",
|
||||||
|
providers: {
|
||||||
|
aiclient2api: {
|
||||||
|
baseUrl: "http://localhost:3000/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [
|
||||||
|
{
|
||||||
|
id: "gemini-3-flash-preview",
|
||||||
|
name: "Gemini 3 Flash Preview",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 8192
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方法2:Claude プロトコル
|
||||||
|
|
||||||
|
**使用例**:Prompt Caching などの機能を持つ Claude モデルを使用する場合
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
env: {
|
||||||
|
AICLIENT2API_KEY: "your-api-key"
|
||||||
|
},
|
||||||
|
agents: {
|
||||||
|
defaults: {
|
||||||
|
model: { primary: "aiclient2api/claude-sonnet-4-5" },
|
||||||
|
models: {
|
||||||
|
"aiclient2api/claude-sonnet-4-5": { alias: "Claude Sonnet 4.5" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
models: {
|
||||||
|
mode: "merge",
|
||||||
|
providers: {
|
||||||
|
aiclient2api: {
|
||||||
|
baseUrl: "http://localhost:3000",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
models: [
|
||||||
|
{
|
||||||
|
id: "claude-sonnet-4-5",
|
||||||
|
name: "Claude Sonnet 4.5",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 8192
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## プロバイダーの指定(オプション)
|
||||||
|
|
||||||
|
ルーティングパラメータで特定のプロバイダーを指定:
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
models: {
|
||||||
|
providers: {
|
||||||
|
// Kiro Claude(OpenAI プロトコル)
|
||||||
|
"aiclient2api-kiro": {
|
||||||
|
baseUrl: "http://localhost:3000/claude-kiro-oauth/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [...]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Kiro Claude(Claude プロトコル)
|
||||||
|
"aiclient2api-kiro-claude": {
|
||||||
|
baseUrl: "http://localhost:3000/claude-kiro-oauth",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
models: [...]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Gemini CLI(OpenAI プロトコル)
|
||||||
|
"aiclient2api-gemini": {
|
||||||
|
baseUrl: "http://localhost:3000/gemini-cli-oauth/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [...]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Antigravity(OpenAI プロトコル)
|
||||||
|
"aiclient2api-antigravity": {
|
||||||
|
baseUrl: "http://localhost:3000/gemini-antigravity/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [...]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## フォールバックの設定
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
agents: {
|
||||||
|
defaults: {
|
||||||
|
model: {
|
||||||
|
primary: "aiclient2api/claude-sonnet-4-5",
|
||||||
|
fallbacks: [
|
||||||
|
"aiclient2api/gemini-3-flash-preview"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## よく使うコマンド
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# すべてのモデルをリスト表示
|
||||||
|
openclaw models list
|
||||||
|
|
||||||
|
# モデルを切り替え
|
||||||
|
openclaw models set aiclient2api/claude-sonnet-4-5
|
||||||
|
|
||||||
|
# 特定のモデルでチャット
|
||||||
|
openclaw chat --model aiclient2api/gemini-3-flash-preview "あなたの質問"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## プロトコル比較
|
||||||
|
|
||||||
|
| 機能 | OpenAI プロトコル | Claude プロトコル |
|
||||||
|
|------|------------------|------------------|
|
||||||
|
| Base URL | `http://localhost:3000/v1` | `http://localhost:3000` |
|
||||||
|
| API タイプ | `openai-completions` | `anthropic-messages` |
|
||||||
|
| サポートモデル | すべてのモデル | Claude のみ |
|
||||||
|
| 特殊機能 | - | Prompt Caching、Extended Thinking |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## よくある質問
|
||||||
|
|
||||||
|
**Q: 接続に失敗しますか?**
|
||||||
|
- AIClient-2-API サービスが実行中であることを確認
|
||||||
|
- Base URL が正しいか確認(OpenAI プロトコルには `/v1` サフィックスが必要)
|
||||||
|
- `localhost` の代わりに `127.0.0.1` を使用してみる
|
||||||
|
|
||||||
|
**Q: 401 エラー?**
|
||||||
|
- API Key が正しく設定されているか確認
|
||||||
|
- 環境変数 `AICLIENT2API_KEY` が設定されているか確認
|
||||||
|
|
||||||
|
**Q: モデルが利用できない?**
|
||||||
|
- AIClient-2-API Web UI でプロバイダーが設定されているか確認
|
||||||
|
- `openclaw gateway restart` を実行してゲートウェイを再起動
|
||||||
|
- `openclaw models list` を実行してモデルリストを確認
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
詳細については、[AIClient-2-API ドキュメント](./README-JA.md) を参照してください
|
||||||
213
OPENCLAW_CONFIG_GUIDE-ZH.md
Normal file
213
OPENCLAW_CONFIG_GUIDE-ZH.md
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
# OpenClaw 配置指南
|
||||||
|
|
||||||
|
在 OpenClaw 中使用 AIClient-2-API 的快速配置指南。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 前置准备
|
||||||
|
|
||||||
|
1. 启动 AIClient-2-API 服务
|
||||||
|
2. 在 Web UI (`http://localhost:3000`) 配置至少一个提供商
|
||||||
|
3. 记录配置文件中的 API Key
|
||||||
|
4. 安装 OpenClaw
|
||||||
|
- Docker 版本:[justlikemaki/openclaw-docker-cn-im](https://hub.docker.com/r/justlikemaki/openclaw-docker-cn-im)
|
||||||
|
- 或使用其他安装方式
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 配置方式
|
||||||
|
|
||||||
|
### 方式一:OpenAI 协议(推荐)
|
||||||
|
|
||||||
|
**适用场景**:使用 Gemini 模型
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
env: {
|
||||||
|
AICLIENT2API_KEY: "your-api-key"
|
||||||
|
},
|
||||||
|
agents: {
|
||||||
|
defaults: {
|
||||||
|
model: { primary: "aiclient2api/gemini-3-flash-preview" },
|
||||||
|
models: {
|
||||||
|
"aiclient2api/gemini-3-flash-preview": { alias: "Gemini 3 Flash" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
models: {
|
||||||
|
mode: "merge",
|
||||||
|
providers: {
|
||||||
|
aiclient2api: {
|
||||||
|
baseUrl: "http://localhost:3000/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [
|
||||||
|
{
|
||||||
|
id: "gemini-3-flash-preview",
|
||||||
|
name: "Gemini 3 Flash Preview",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 8192
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式二:Claude 协议
|
||||||
|
|
||||||
|
**适用场景**:使用 Claude 模型,需要 Prompt Caching 等特性
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
env: {
|
||||||
|
AICLIENT2API_KEY: "your-api-key"
|
||||||
|
},
|
||||||
|
agents: {
|
||||||
|
defaults: {
|
||||||
|
model: { primary: "aiclient2api/claude-sonnet-4-5" },
|
||||||
|
models: {
|
||||||
|
"aiclient2api/claude-sonnet-4-5": { alias: "Claude Sonnet 4.5" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
models: {
|
||||||
|
mode: "merge",
|
||||||
|
providers: {
|
||||||
|
aiclient2api: {
|
||||||
|
baseUrl: "http://localhost:3000",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
models: [
|
||||||
|
{
|
||||||
|
id: "claude-sonnet-4-5",
|
||||||
|
name: "Claude Sonnet 4.5",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 8192
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 指定提供商(可选)
|
||||||
|
|
||||||
|
通过路由参数指定特定提供商:
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
models: {
|
||||||
|
providers: {
|
||||||
|
// Kiro 提供的 Claude (OpenAI 协议)
|
||||||
|
"aiclient2api-kiro": {
|
||||||
|
baseUrl: "http://localhost:3000/claude-kiro-oauth/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [...]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Kiro 提供的 Claude (Claude 协议)
|
||||||
|
"aiclient2api-kiro-claude": {
|
||||||
|
baseUrl: "http://localhost:3000/claude-kiro-oauth",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
models: [...]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Gemini CLI (OpenAI 协议)
|
||||||
|
"aiclient2api-gemini": {
|
||||||
|
baseUrl: "http://localhost:3000/gemini-cli-oauth/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [...]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Antigravity (OpenAI 协议)
|
||||||
|
"aiclient2api-antigravity": {
|
||||||
|
baseUrl: "http://localhost:3000/gemini-antigravity/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [...]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 配置 Fallback
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
agents: {
|
||||||
|
defaults: {
|
||||||
|
model: {
|
||||||
|
primary: "aiclient2api/claude-sonnet-4-5",
|
||||||
|
fallbacks: [
|
||||||
|
"aiclient2api/gemini-3-flash-preview"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常用命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 列出所有模型
|
||||||
|
openclaw models list
|
||||||
|
|
||||||
|
# 切换模型
|
||||||
|
openclaw models set aiclient2api/claude-sonnet-4-5
|
||||||
|
|
||||||
|
# 使用指定模型对话
|
||||||
|
openclaw chat --model aiclient2api/gemini-3-flash-preview "你的问题"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 协议对比
|
||||||
|
|
||||||
|
| 特性 | OpenAI 协议 | Claude 协议 |
|
||||||
|
|------|------------|------------|
|
||||||
|
| Base URL | `http://localhost:3000/v1` | `http://localhost:3000` |
|
||||||
|
| API 类型 | `openai-completions` | `anthropic-messages` |
|
||||||
|
| 支持模型 | 所有模型 | 仅 Claude |
|
||||||
|
| 特殊特性 | - | Prompt Caching、Extended Thinking |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
**Q: 连接失败?**
|
||||||
|
- 确认 AIClient-2-API 服务运行中
|
||||||
|
- 检查 Base URL 是否正确(OpenAI 协议需要 `/v1` 后缀)
|
||||||
|
- 尝试使用 `127.0.0.1` 替代 `localhost`
|
||||||
|
|
||||||
|
**Q: 401 错误?**
|
||||||
|
- 检查 API Key 是否正确配置
|
||||||
|
- 确认环境变量 `AICLIENT2API_KEY` 已设置
|
||||||
|
|
||||||
|
**Q: 模型不可用?**
|
||||||
|
- 在 AIClient-2-API Web UI 确认已配置对应提供商
|
||||||
|
- 运行 `openclaw gateway restart` 重启网关
|
||||||
|
- 运行 `openclaw models list` 验证模型列表
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
更多信息请参考 [AIClient-2-API 文档](../README-ZH.md)
|
||||||
213
OPENCLAW_CONFIG_GUIDE.md
Normal file
213
OPENCLAW_CONFIG_GUIDE.md
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
# OpenClaw Configuration Guide
|
||||||
|
|
||||||
|
Quick configuration guide for using AIClient-2-API with OpenClaw.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. Start AIClient-2-API service
|
||||||
|
2. Configure at least one provider in Web UI (`http://localhost:3000`)
|
||||||
|
3. Note the API Key from configuration file
|
||||||
|
4. Install OpenClaw
|
||||||
|
- Docker version: [justlikemaki/openclaw-docker-cn-im](https://hub.docker.com/r/justlikemaki/openclaw-docker-cn-im)
|
||||||
|
- Or use other installation methods
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration Methods
|
||||||
|
|
||||||
|
### Method 1: OpenAI Protocol (Recommended)
|
||||||
|
|
||||||
|
**Use Case**: For Gemini models
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
env: {
|
||||||
|
AICLIENT2API_KEY: "your-api-key"
|
||||||
|
},
|
||||||
|
agents: {
|
||||||
|
defaults: {
|
||||||
|
model: { primary: "aiclient2api/gemini-3-flash-preview" },
|
||||||
|
models: {
|
||||||
|
"aiclient2api/gemini-3-flash-preview": { alias: "Gemini 3 Flash" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
models: {
|
||||||
|
mode: "merge",
|
||||||
|
providers: {
|
||||||
|
aiclient2api: {
|
||||||
|
baseUrl: "http://localhost:3000/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [
|
||||||
|
{
|
||||||
|
id: "gemini-3-flash-preview",
|
||||||
|
name: "Gemini 3 Flash Preview",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 8192
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Method 2: Claude Protocol
|
||||||
|
|
||||||
|
**Use Case**: For Claude models with features like Prompt Caching
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
env: {
|
||||||
|
AICLIENT2API_KEY: "your-api-key"
|
||||||
|
},
|
||||||
|
agents: {
|
||||||
|
defaults: {
|
||||||
|
model: { primary: "aiclient2api/claude-sonnet-4-5" },
|
||||||
|
models: {
|
||||||
|
"aiclient2api/claude-sonnet-4-5": { alias: "Claude Sonnet 4.5" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
models: {
|
||||||
|
mode: "merge",
|
||||||
|
providers: {
|
||||||
|
aiclient2api: {
|
||||||
|
baseUrl: "http://localhost:3000",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
models: [
|
||||||
|
{
|
||||||
|
id: "claude-sonnet-4-5",
|
||||||
|
name: "Claude Sonnet 4.5",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 8192
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Specify Provider (Optional)
|
||||||
|
|
||||||
|
Specify a specific provider via routing parameters:
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
models: {
|
||||||
|
providers: {
|
||||||
|
// Kiro Claude (OpenAI Protocol)
|
||||||
|
"aiclient2api-kiro": {
|
||||||
|
baseUrl: "http://localhost:3000/claude-kiro-oauth/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [...]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Kiro Claude (Claude Protocol)
|
||||||
|
"aiclient2api-kiro-claude": {
|
||||||
|
baseUrl: "http://localhost:3000/claude-kiro-oauth",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
models: [...]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Gemini CLI (OpenAI Protocol)
|
||||||
|
"aiclient2api-gemini": {
|
||||||
|
baseUrl: "http://localhost:3000/gemini-cli-oauth/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [...]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Antigravity (OpenAI Protocol)
|
||||||
|
"aiclient2api-antigravity": {
|
||||||
|
baseUrl: "http://localhost:3000/gemini-antigravity/v1",
|
||||||
|
apiKey: "${AICLIENT2API_KEY}",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [...]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configure Fallback
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
agents: {
|
||||||
|
defaults: {
|
||||||
|
model: {
|
||||||
|
primary: "aiclient2api/claude-sonnet-4-5",
|
||||||
|
fallbacks: [
|
||||||
|
"aiclient2api/gemini-3-flash-preview"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all models
|
||||||
|
openclaw models list
|
||||||
|
|
||||||
|
# Switch model
|
||||||
|
openclaw models set aiclient2api/claude-sonnet-4-5
|
||||||
|
|
||||||
|
# Chat with specific model
|
||||||
|
openclaw chat --model aiclient2api/gemini-3-flash-preview "your question"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Protocol Comparison
|
||||||
|
|
||||||
|
| Feature | OpenAI Protocol | Claude Protocol |
|
||||||
|
|---------|----------------|-----------------|
|
||||||
|
| Base URL | `http://localhost:3000/v1` | `http://localhost:3000` |
|
||||||
|
| API Type | `openai-completions` | `anthropic-messages` |
|
||||||
|
| Supported Models | All models | Claude only |
|
||||||
|
| Special Features | - | Prompt Caching, Extended Thinking |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
**Q: Connection failed?**
|
||||||
|
- Confirm AIClient-2-API service is running
|
||||||
|
- Check if Base URL is correct (OpenAI protocol needs `/v1` suffix)
|
||||||
|
- Try using `127.0.0.1` instead of `localhost`
|
||||||
|
|
||||||
|
**Q: 401 error?**
|
||||||
|
- Check if API Key is correctly configured
|
||||||
|
- Confirm environment variable `AICLIENT2API_KEY` is set
|
||||||
|
|
||||||
|
**Q: Model unavailable?**
|
||||||
|
- Confirm provider is configured in AIClient-2-API Web UI
|
||||||
|
- Run `openclaw gateway restart` to restart gateway
|
||||||
|
- Run `openclaw models list` to verify model list
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
For more information, see [AIClient-2-API Documentation](./README.md)
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
[](https://github.com/justlovemaki/AIClient-2-API/stargazers)
|
[](https://github.com/justlovemaki/AIClient-2-API/stargazers)
|
||||||
[](https://github.com/justlovemaki/AIClient-2-API/issues)
|
[](https://github.com/justlovemaki/AIClient-2-API/issues)
|
||||||
|
|
||||||
[中文](./README-ZH.md) | [English](./README.md) | [**👉 日本語**](./README-JA.md) | [**📚 完全ドキュメント**](https://aiproxy.justlikemaki.vip/ja/)
|
[**🔧 OpenClaw 設定**](./OPENCLAW_CONFIG_GUIDE-JA.md) | [中文](./README-ZH.md) | [English](./README.md) | [**👉 日本語**](./README-JA.md) | [**📚 完全ドキュメント**](https://aiproxy.justlikemaki.vip/ja/)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
[](https://github.com/justlovemaki/AIClient-2-API/stargazers)
|
[](https://github.com/justlovemaki/AIClient-2-API/stargazers)
|
||||||
[](https://github.com/justlovemaki/AIClient-2-API/issues)
|
[](https://github.com/justlovemaki/AIClient-2-API/issues)
|
||||||
|
|
||||||
[**👉 中文**](./README-ZH.md) | [English](./README.md) | [日本語](./README-JA.md) | [**📚 完整文档**](https://aiproxy.justlikemaki.vip/zh/)
|
[**🔧 OpenClaw 配置**](./OPENCLAW_CONFIG_GUIDE-ZH.md) | [**👉 中文**](./README-ZH.md) | [English](./README.md) | [日本語](./README-JA.md) | [**📚 完整文档**](https://aiproxy.justlikemaki.vip/zh/)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
[](https://github.com/justlovemaki/AIClient-2-API/stargazers)
|
[](https://github.com/justlovemaki/AIClient-2-API/stargazers)
|
||||||
[](https://github.com/justlovemaki/AIClient-2-API/issues)
|
[](https://github.com/justlovemaki/AIClient-2-API/issues)
|
||||||
|
|
||||||
[中文](./README-ZH.md) | [**👉 English**](./README.md) | [日本語](./README-JA.md) | [**📚 Documentation**](https://aiproxy.justlikemaki.vip/en/)
|
[**🔧 OpenClaw Config**](./OPENCLAW_CONFIG_GUIDE.md) | [中文](./README-ZH.md) | [**👉 English**](./README.md) | [日本語](./README-JA.md) | [**📚 Documentation**](https://aiproxy.justlikemaki.vip/en/)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -269,8 +269,14 @@ export async function handleGetUsage(req, res, currentConfig, providerPoolManage
|
||||||
await writeUsageCache(usageResults);
|
await writeUsageCache(usageResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always include current server time
|
||||||
|
const finalResults = {
|
||||||
|
...usageResults,
|
||||||
|
serverTime: new Date().toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
res.end(JSON.stringify(usageResults));
|
res.end(JSON.stringify(finalResults));
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('[UI API] Failed to get usage:', error);
|
logger.error('[UI API] Failed to get usage:', error);
|
||||||
|
|
@ -300,7 +306,7 @@ export async function handleGetProviderUsage(req, res, currentConfig, providerPo
|
||||||
const cachedData = await readProviderUsageCache(providerType);
|
const cachedData = await readProviderUsageCache(providerType);
|
||||||
if (cachedData) {
|
if (cachedData) {
|
||||||
logger.info(`[Usage API] Returning cached usage data for ${providerType}`);
|
logger.info(`[Usage API] Returning cached usage data for ${providerType}`);
|
||||||
usageResults = cachedData;
|
usageResults = { ...cachedData, fromCache: true };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -312,8 +318,14 @@ export async function handleGetProviderUsage(req, res, currentConfig, providerPo
|
||||||
await updateProviderUsageCache(providerType, usageResults);
|
await updateProviderUsageCache(providerType, usageResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always include current server time
|
||||||
|
const finalResults = {
|
||||||
|
...usageResults,
|
||||||
|
serverTime: new Date().toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
res.end(JSON.stringify(usageResults));
|
res.end(JSON.stringify(finalResults));
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`[UI API] Failed to get usage for ${providerType}:`, error);
|
logger.error(`[UI API] Failed to get usage for ${providerType}:`, error);
|
||||||
|
|
|
||||||
|
|
@ -515,6 +515,7 @@ const translations = {
|
||||||
// Usage
|
// Usage
|
||||||
'usage.title': '用量查询',
|
'usage.title': '用量查询',
|
||||||
'usage.refresh': '刷新用量',
|
'usage.refresh': '刷新用量',
|
||||||
|
'usage.serverTime': '服务端时间',
|
||||||
'usage.lastUpdate': '上次更新: {time}',
|
'usage.lastUpdate': '上次更新: {time}',
|
||||||
'usage.lastUpdateCache': '缓存时间: {time}',
|
'usage.lastUpdateCache': '缓存时间: {time}',
|
||||||
'usage.supportedProvidersPrefix': '支持用量查询的提供商:',
|
'usage.supportedProvidersPrefix': '支持用量查询的提供商:',
|
||||||
|
|
@ -1285,6 +1286,7 @@ const translations = {
|
||||||
// Usage
|
// Usage
|
||||||
'usage.title': 'Usage Query',
|
'usage.title': 'Usage Query',
|
||||||
'usage.refresh': 'Refresh Usage',
|
'usage.refresh': 'Refresh Usage',
|
||||||
|
'usage.serverTime': 'Server Time',
|
||||||
'usage.lastUpdate': 'Last Update: {time}',
|
'usage.lastUpdate': 'Last Update: {time}',
|
||||||
'usage.lastUpdateCache': 'Cache Time: {time}',
|
'usage.lastUpdateCache': 'Cache Time: {time}',
|
||||||
'usage.supportedProvidersPrefix': 'Providers supporting usage query:',
|
'usage.supportedProvidersPrefix': 'Providers supporting usage query:',
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,14 @@ export async function loadUsage() {
|
||||||
// 渲染用量数据
|
// 渲染用量数据
|
||||||
renderUsageData(data, contentEl);
|
renderUsageData(data, contentEl);
|
||||||
|
|
||||||
|
// 更新服务端系统时间
|
||||||
|
if (data.serverTime) {
|
||||||
|
const serverTimeEl = document.getElementById('serverTimeValue');
|
||||||
|
if (serverTimeEl) {
|
||||||
|
serverTimeEl.textContent = new Date(data.serverTime).toLocaleString(getCurrentLanguage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 更新最后更新时间
|
// 更新最后更新时间
|
||||||
if (lastUpdateEl) {
|
if (lastUpdateEl) {
|
||||||
const timeStr = new Date(data.timestamp || Date.now()).toLocaleString(getCurrentLanguage());
|
const timeStr = new Date(data.timestamp || Date.now()).toLocaleString(getCurrentLanguage());
|
||||||
|
|
@ -155,6 +163,14 @@ export async function refreshUsage() {
|
||||||
// 渲染用量数据
|
// 渲染用量数据
|
||||||
renderUsageData(data, contentEl);
|
renderUsageData(data, contentEl);
|
||||||
|
|
||||||
|
// 更新服务端系统时间
|
||||||
|
if (data.serverTime) {
|
||||||
|
const serverTimeEl = document.getElementById('serverTimeValue');
|
||||||
|
if (serverTimeEl) {
|
||||||
|
serverTimeEl.textContent = new Date(data.serverTime).toLocaleString(getCurrentLanguage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 更新最后更新时间
|
// 更新最后更新时间
|
||||||
if (lastUpdateEl) {
|
if (lastUpdateEl) {
|
||||||
const timeStr = new Date().toLocaleString(getCurrentLanguage());
|
const timeStr = new Date().toLocaleString(getCurrentLanguage());
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,20 @@
|
||||||
.usage-last-update {
|
.usage-last-update {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.server-time-display {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
border-left: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.server-time-display i {
|
||||||
|
color: var(--primary-color);
|
||||||
|
margin-right: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.usage-info-banner {
|
.usage-info-banner {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@
|
||||||
<i class="fas fa-sync-alt"></i> <span data-i18n="usage.refresh">刷新用量</span>
|
<i class="fas fa-sync-alt"></i> <span data-i18n="usage.refresh">刷新用量</span>
|
||||||
</button>
|
</button>
|
||||||
<span class="usage-last-update" id="usageLastUpdate" data-i18n="usage.lastUpdate" data-i18n-params='{"time":"--"}'>上次更新: --</span>
|
<span class="usage-last-update" id="usageLastUpdate" data-i18n="usage.lastUpdate" data-i18n-params='{"time":"--"}'>上次更新: --</span>
|
||||||
|
<span class="server-time-display" id="serverTimeDisplay">
|
||||||
|
<span data-i18n="usage.serverTime">服务端时间</span>: <span id="serverTimeValue">--</span>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="usage-info-banner">
|
<div class="usage-info-banner">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue