myapikey 0.19.0 → 0.19.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -256
- package/README.zh-CN.md +80 -257
- package/package.json +1 -1
- package/packages/core/src/cli/index.ts +1 -1
- package/packages/core/src/server/admin.ts +3 -3
- package/packages/core/src/server/proxy.ts +64 -35
- package/packages/core/src/shared/types.ts +11 -10
- package/packages/web/dist/assets/{index-VlfUQRHs.js → index-DHemqm93.js} +1 -1
- package/packages/web/dist/index.html +1 -1
package/README.md
CHANGED
|
@@ -2,311 +2,134 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/myapikey)
|
|
4
4
|
[](./LICENSE)
|
|
5
|
-
[](#up-and-running-in-60-seconds)
|
|
6
6
|
[](#development)
|
|
7
7
|
|
|
8
8
|
English | [简体中文](README.zh-CN.md)
|
|
9
9
|
|
|
10
|
-
**One address, one key,
|
|
10
|
+
**One address, one key, every AI tool you use.** A tiny self-hosted LLM gateway for your home server: keep your provider keys in one place, point every tool at the same URL with the same key, and fail over automatically when a backend breaks.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
## Sound familiar?
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
- You use **Claude Code, a few OpenAI-compatible CLIs, editor plugins, scripts** — and each one needs its own base URL + API key pasted in.
|
|
15
|
+
- Your **real keys** (OpenAI, Anthropic, OpenRouter, a local Ollama…) are scattered across a dozen config files. Rotating one means remembering everywhere it's pasted.
|
|
16
|
+
- Your **main provider 429s or goes down** mid-task and the tool just dies. Switching to a backup means re-editing configs.
|
|
17
|
+
- You tried **one-api / new-api-style gateways**, which *translate* between formats — and drop fields, mangle streams, or hold new upstream parameters hostage until someone updates the gateway.
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
MyAPIKey is built to end exactly this.
|
|
17
20
|
|
|
18
|
-
##
|
|
21
|
+
## What you get
|
|
19
22
|
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
- [API surface](#api-surface)
|
|
29
|
-
- [Storage](#storage)
|
|
30
|
-
- [Development](#development)
|
|
31
|
-
- [Notes and non-goals](#notes-and-non-goals)
|
|
23
|
+
- **One address, one key.** Every tool points at `http://<your-server>:7800` with a single `sk-myapikey-…` key. Real provider keys live only inside the gateway — rotate one, swap a backend, and no tool config ever changes again.
|
|
24
|
+
- **Automatic failover + circuit breaker.** Give a model an ordered chain of backends. On `429` / `5xx` / timeout the next one takes over; a source that keeps failing cools down (30 s → 5 min) so later calls skip it. Your agent never notices.
|
|
25
|
+
- **Pure passthrough, zero translation.** OpenAI-format calls reach OpenAI-speaking backends, Anthropic-format calls reach Anthropic-speaking backends — bodies forwarded byte-for-byte, streaming straight through. New upstream fields and parameters work without the gateway "supporting" them first.
|
|
26
|
+
- **Rate limiting that queues instead of 429ing.** Cap each backend's rpm, or give a model an even per-minute pace; excess calls wait in the gateway instead of coming straight back as `429`.
|
|
27
|
+
- **Model name mapping.** Expose a friendly name to your tools (`claude-sonnet-4`); each backend maps it to its own real id (`claude-sonnet-4-20250514` here, something else there).
|
|
28
|
+
- **A default thinking level per slot.** Pin a reasoning effort / token budget on a route; it overrides whatever the request carried — handy for taming Claude Code.
|
|
29
|
+
- **See everything.** Web UI (English / 简体中文): live call log, success rate, p50/p95 latency, per-model / per-backend / per-day stats. The CLI can do all of it too.
|
|
30
|
+
- **Featherweight.** No database — one `data.json` plus a `logs.jsonl`. Runs with `npx`. Built for LAN / home-server use.
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
## Up and running in 60 seconds
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
If any of these sound familiar, MyAPIKey is for you:
|
|
38
|
-
|
|
39
|
-
- You juggle **several API keys** across OpenAI, Anthropic, OpenRouter, a local model, etc., and you're tired of pasting a different one into every tool.
|
|
40
|
-
- You want **one stable address** for your agents, even when the provider behind it changes.
|
|
41
|
-
- You want **automatic fallback** — if your primary backend rate-limits or goes down, the next one takes over.
|
|
42
|
-
- You want to **rename or swap a model** without editing every tool's config.
|
|
43
|
-
- You'd like a **log of every call** (latency, status, which backend served it).
|
|
44
|
-
|
|
45
|
-
MyAPIKey gives you all of that. You keep your real provider keys inside the gateway; your tools only ever know `http://<host>:7800` and one `sk-myapikey-…` key.
|
|
46
|
-
|
|
47
|
-
**The one thing to know up front:** the gateway **forwards in your tool's native format and never translates**. A call to the OpenAI endpoint reaches an OpenAI-speaking backend; a call to the Anthropic endpoint reaches an Anthropic-speaking backend. This keeps your requests and responses lossless. (See [How routing works](#how-routing-works) once you're set up.)
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## Quick start
|
|
52
|
-
|
|
53
|
-
Requires **Node.js 18+**. No install needed — run it straight from npm:
|
|
34
|
+
Requires Node.js 18+.
|
|
54
35
|
|
|
55
36
|
```bash
|
|
56
37
|
npx myapikey serve # → http://localhost:7800
|
|
57
38
|
```
|
|
58
39
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
npm install -g myapikey
|
|
63
|
-
myapikey serve
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
On first run it prints generated credentials **and saves them to a file** so you can't lose them:
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
First run — here are your credentials (save them):
|
|
70
|
-
username : <random> (web login)
|
|
71
|
-
password : <random> (web login)
|
|
72
|
-
api key : sk-myapikey-… (put this in the tool's "api key" field)
|
|
73
|
-
↳ also written to ~/.myapikey/credentials.txt
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
Open `http://localhost:7800` in a browser and sign in with the **username / password** to reach the web UI. The **API key** is separate — that's what your AI tools use later.
|
|
77
|
-
|
|
78
|
-
> Forgot the credentials? `cat ~/.myapikey/credentials.txt` (regenerated on every start). Override the data location with `--data-dir <path>` or the `MYAPIKEY_DATA_DIR` env var.
|
|
40
|
+
First run prints your credentials and also saves them to `~/.myapikey/credentials.txt`:
|
|
79
41
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
## Add your first backend
|
|
85
|
-
|
|
86
|
-
A **backend** (provider) is one upstream API: OpenAI, Anthropic, OpenRouter, a local Ollama, a vendor like Volcengine Ark, etc. You add it once with its real key, then enable models through it.
|
|
87
|
-
|
|
88
|
-
### Easiest: the web UI
|
|
89
|
-
|
|
90
|
-
1. Open the **Models** tab → **Add backend**.
|
|
91
|
-
2. Enter a name, the backend's base URL(s), and its API key.
|
|
92
|
-
3. Pick the wire format(s) it speaks: `openai`, `anthropic` (or both).
|
|
93
|
-
4. Save, then click **discover** to pull its model list.
|
|
94
|
-
5. **Enable** the models you want, per format slot.
|
|
95
|
-
|
|
96
|
-
### Or, the CLI
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
# An OpenAI-compatible backend. The OpenAI base includes the version segment
|
|
100
|
-
# (e.g. /v1, or a vendor's own like Ark's /api/v3).
|
|
101
|
-
myapikey provider add openai-direct \
|
|
102
|
-
--base-url-openai https://api.openai.com/v1 \
|
|
103
|
-
--key sk-... \
|
|
104
|
-
--formats openai
|
|
105
|
-
|
|
106
|
-
# An Anthropic backend. The Anthropic base EXCLUDES /v1
|
|
107
|
-
# (https://api.anthropic.com, or Ark's /api/plan).
|
|
108
|
-
myapikey provider add anthropic-direct \
|
|
109
|
-
--base-url-anthropic https://api.anthropic.com \
|
|
110
|
-
--key sk-ant-... \
|
|
111
|
-
--formats anthropic
|
|
112
|
-
|
|
113
|
-
# See what each offers, then enable a model on a slot:
|
|
114
|
-
myapikey provider models openai-direct
|
|
115
|
-
myapikey model enable gpt-4o-mini --format openai --via openai-direct
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
That model is now reachable through the gateway. To add a **fallback** for the same model (used when the first one fails), add another backend and chain it:
|
|
42
|
+
1. Open `http://localhost:7800` and sign in with the printed **username / password** (web login).
|
|
43
|
+
2. **Models** tab → **Add backend**: paste the backend's base URL + its real API key, tick the formats it speaks (`openai` / `anthropic`), then **discover** → **enable** the models you want.
|
|
44
|
+
3. Point your tools at the gateway — every tool's "API key" field gets the **gateway key**, not your web password:
|
|
119
45
|
|
|
120
46
|
```bash
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
myapikey model list # see the routing table
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
> `--format` selects the routing **slot**: `openai` (for `/openai/v1/chat/completions`), `anthropic` (for `/anthropic/v1/messages`), or `responses` (for `/openai/v1/responses`). The `responses` slot only accepts backends you've marked **supportsResponses** — set that toggle in the web UI (the CLI doesn't expose it yet).
|
|
128
|
-
|
|
129
|
-
---
|
|
130
|
-
|
|
131
|
-
## Connect a tool
|
|
132
|
-
|
|
133
|
-
Once a model is enabled, point any agent at the gateway. Get your connection info:
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
myapikey whoami # prints base url + api key + ready-to-paste env lines
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
For an **OpenAI-compatible** tool (covers `/chat/completions` *and* `/responses`):
|
|
47
|
+
# Claude Code / anything Anthropic
|
|
48
|
+
export ANTHROPIC_BASE_URL=http://localhost:7800/anthropic
|
|
49
|
+
export ANTHROPIC_API_KEY=sk-myapikey-…
|
|
140
50
|
|
|
141
|
-
|
|
51
|
+
# OpenAI-compatible tools (Codex, CLIs, plugins)
|
|
142
52
|
export OPENAI_BASE_URL=http://localhost:7800/openai/v1
|
|
143
|
-
export OPENAI_API_KEY
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
For **Anthropic / Claude Code**:
|
|
147
|
-
|
|
148
|
-
```bash
|
|
149
|
-
export ANTHROPIC_BASE_URL=http://localhost:7800/anthropic
|
|
150
|
-
export ANTHROPIC_API_KEY=<gateway api key>
|
|
53
|
+
export OPENAI_API_KEY=sk-myapikey-…
|
|
151
54
|
```
|
|
152
55
|
|
|
153
|
-
>
|
|
56
|
+
> Why `…/openai/v1` but `…/anthropic`? Each SDK appends its own paths (OpenAI adds `/chat/completions`, Anthropic adds `/v1/messages`), so the gateway follows each ecosystem's own convention. Each surface also has its own `/models`, listing only models enabled for that format. `myapikey whoami` prints all of this ready to paste, anytime.
|
|
154
57
|
|
|
155
|
-
|
|
58
|
+
4. Smoke test without any tool:
|
|
156
59
|
|
|
157
60
|
```bash
|
|
158
61
|
myapikey call gpt-4o-mini "Say hello in one sentence."
|
|
159
62
|
```
|
|
160
63
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
**Raw HTTP** (no SDK) — hit either surface directly with the gateway API key as a `Bearer` token:
|
|
164
|
-
|
|
165
|
-
```bash
|
|
166
|
-
# OpenAI family
|
|
167
|
-
curl http://localhost:7800/openai/v1/chat/completions \
|
|
168
|
-
-H "Authorization: Bearer <gateway api key>" -H "Content-Type: application/json" \
|
|
169
|
-
-d '{"model":"<model>","messages":[{"role":"user","content":"hi"}]}'
|
|
170
|
-
|
|
171
|
-
# Anthropic family
|
|
172
|
-
curl http://localhost:7800/anthropic/v1/messages \
|
|
173
|
-
-H "Authorization: Bearer <gateway api key>" -H "Content-Type: application/json" \
|
|
174
|
-
-d '{"model":"<model>","max_tokens":16,"messages":[{"role":"user","content":"hi"}]}'
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Whichever endpoint you point a tool at, the gateway forwards in that format and never translates — so make sure each model you call is backed by at least one source on the matching slot ([see below](#how-routing-works)).
|
|
178
|
-
|
|
179
|
-
---
|
|
64
|
+
Prefer the terminal? `provider add` → `provider models` → `model enable` does the same job — cheat sheet below.
|
|
180
65
|
|
|
181
|
-
## How routing works
|
|
66
|
+
## How routing works (the whole story)
|
|
182
67
|
|
|
183
|
-
The gateway
|
|
68
|
+
- The gateway has two entrances: `/openai/v1/*` (chat completions, responses, models) and `/anthropic/v1/*` (messages, models). A request is forwarded in the entrance's format, **never translated**.
|
|
69
|
+
- Each model has an independent, ordered backend chain **per format**. Within a chain, `429` / `5xx` / timeouts fail over to the next backend; other `4xx` errors come back as-is (they're the caller's fault, not the backend's). No failover once streaming has started. If no backend serves that model on that format, you get a `404` — a clear failure beats a silent translation.
|
|
70
|
+
- Anything that speaks either format works: OpenAI, Anthropic, OpenRouter, Ollama / vLLM, Volcengine Ark, your company's internal gateway…
|
|
184
71
|
|
|
185
|
-
|
|
72
|
+
## Why no translation?
|
|
186
73
|
|
|
187
|
-
|
|
74
|
+
one-api / new-api convert OpenAI ↔ Anthropic shapes. Convenient, until a field gets dropped, a stream gets mangled, or a new upstream parameter needs a gateway update before you can send it. OpenRouter is hosted and takes a cut per call. MyAPIKey's answer is to not have a translation layer at all:
|
|
188
75
|
|
|
189
|
-
|
|
76
|
+
| | MyAPIKey | one-api / new-api | OpenRouter |
|
|
77
|
+
|---|---|---|---|
|
|
78
|
+
| Deploy | self-hosted, one `npx` | self-hosted, heavier | hosted service |
|
|
79
|
+
| Cost | free | free | markup per call |
|
|
80
|
+
| Formats | passthrough, byte-for-byte | translated | translated |
|
|
81
|
+
| New upstream params | work immediately | wait for gateway support | wait for platform support |
|
|
82
|
+
| Provider keys | on your machine | on your machine | on their platform |
|
|
190
83
|
|
|
191
|
-
|
|
84
|
+
The trade-off, stated plainly: an Anthropic-format backend cannot be called through the OpenAI entrance. If what you want is format conversion, this isn't your tool (yet).
|
|
192
85
|
|
|
193
|
-
|
|
86
|
+
## Managing it
|
|
194
87
|
|
|
195
|
-
|
|
88
|
+
**Web UI** — `http://localhost:7800`, English + 简体中文. Five tabs: **Connect** (copy-paste-ready env lines), **Models** (backends, discovery, per-format enable, drag-to-order chains, name mapping, test call), **Logs** (live timeline), **Stats** (counts, success rate, p50/p95 by model / backend / day), **Settings** (rotate API key, change password, circuit-breaker state, storage paths).
|
|
196
89
|
|
|
197
|
-
|
|
90
|
+
**CLI cheat sheet** (same admin API as the web UI — the two never drift apart):
|
|
198
91
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
If no mapping is set for a source, the public model name is sent unchanged.
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
## Web UI
|
|
216
|
-
|
|
217
|
-
Visit `http://localhost:7800`, sign in with your username/password. Ships in **English and Chinese** (toggle in the top bar). Five tabs:
|
|
218
|
-
|
|
219
|
-
- **Connect** — copy-paste base URL / API key / login, plus ready-to-use SDK env lines.
|
|
220
|
-
- **Models** — full CRUD: add sources, discover & enable models per slot, drag-order priority, toggle each slot, set [model name mapping](#model-name-mapping), and run an end-to-end **test** call against any model + slot.
|
|
221
|
-
- **Logs** — live recent-calls timeline (latency, status, source, format), with circuit-breaker cooldown events shown alongside the failures that triggered them.
|
|
222
|
-
- **Stats** — aggregate call counts / success rate / latency (p50, p95) by model, source, format, and day, over a selectable range (24h / 7d / 30d / 90d / all).
|
|
223
|
-
- **Settings** — rotate the API key, change the account password, view/reset circuit-breaker state, and see where `data.json` + `logs.jsonl` live.
|
|
92
|
+
| I want to… | Command |
|
|
93
|
+
|---|---|
|
|
94
|
+
| run the gateway | `myapikey serve [--port 7800] [--data-dir <dir>]` |
|
|
95
|
+
| print what to paste into tools | `myapikey whoami` |
|
|
96
|
+
| add a backend | `myapikey provider add <name> --base-url-openai https://api.openai.com/v1 --key sk-… --formats openai` |
|
|
97
|
+
| see a backend's models | `myapikey provider models <name>` |
|
|
98
|
+
| enable a model | `myapikey model enable <model> --format openai --via <backend>` |
|
|
99
|
+
| add a fallback + set order | `myapikey model add-provider <model> <backend> --format openai` · `myapikey model prioritize <model> <primary> <backup> --format openai` |
|
|
100
|
+
| see the routing table | `myapikey model list` |
|
|
101
|
+
| pace a model | `myapikey model pace <model> <rpm\|0>` |
|
|
102
|
+
| pin a slot's thinking level | `myapikey model thinking <model> <index> [value] --format <fmt>` |
|
|
103
|
+
| quick test | `myapikey call <model> "hi"` |
|
|
224
104
|
|
|
225
|
-
|
|
105
|
+
> OpenAI base URLs **include** the version segment (`/v1`, Ark's `/api/v3`); Anthropic base URLs **exclude** it (`https://api.anthropic.com`). The `responses` format only accepts backends you've marked `supportsResponses` (web UI toggle).
|
|
106
|
+
> CLI global flags: `-u/--url`, `--user`, `--pass`, `--api-key`, or env `MYAPIKEY_URL` / `MYAPIKEY_USER` / `MYAPIKEY_PASS` / `MYAPIKEY_API_KEY`.
|
|
226
107
|
|
|
227
|
-
|
|
108
|
+
## Where your data lives
|
|
228
109
|
|
|
229
|
-
|
|
110
|
+
One directory (default `~/.myapikey`, override with `--data-dir` or `MYAPIKEY_DATA_DIR`):
|
|
230
111
|
|
|
231
|
-
|
|
|
112
|
+
| File | What |
|
|
232
113
|
|---|---|
|
|
233
|
-
| `
|
|
234
|
-
| `
|
|
235
|
-
| `
|
|
236
|
-
| `
|
|
237
|
-
| `provider models <ref>` | discover models offered by a backend |
|
|
238
|
-
| `provider remove <ref>` | remove a backend (id or name) |
|
|
239
|
-
| `model enable <name> --format <fmt> [--via <ref>]` | enable a model on a slot (openai / anthropic / responses) |
|
|
240
|
-
| `model disable <name> --format <fmt>` | disable one slot (keeps config) |
|
|
241
|
-
| `model list` | show the per-slot routing table |
|
|
242
|
-
| `model add-provider <name> <ref> --format <fmt>` | add a fallback source for a slot |
|
|
243
|
-
| `model remove-provider <name> <ref> --format <fmt>` | remove a source from a slot |
|
|
244
|
-
| `model prioritize <name> <ref>... --format <fmt>` | set source order for a slot (left = primary) |
|
|
245
|
-
| `model remove <name>` | remove a model entirely (all slots) |
|
|
246
|
-
| `call <model> [prompt...]` | quick test through the gateway (OpenAI path) |
|
|
247
|
-
|
|
248
|
-
`<ref>` is a provider id or name. Global flags: `-u/--url`, `--user`, `--pass`, `--api-key` (or `MYAPIKEY_URL` / `MYAPIKEY_USER` / `MYAPIKEY_PASS` / `MYAPIKEY_API_KEY` env vars).
|
|
249
|
-
|
|
250
|
-
---
|
|
251
|
-
|
|
252
|
-
## API surface
|
|
253
|
-
|
|
254
|
-
**Agent-facing (two surfaces, one API key — `Authorization: Bearer` or `x-api-key`):**
|
|
255
|
-
|
|
256
|
-
- `POST /openai/v1/chat/completions` — OpenAI-format proxy
|
|
257
|
-
- `POST /openai/v1/responses` — OpenAI Responses API (only sources marked `supportsResponses`)
|
|
258
|
-
- `GET /openai/v1/models` — models enabled on the **openai** slot, OpenAI list shape (public — no key needed)
|
|
259
|
-
- `POST /anthropic/v1/messages` — Anthropic-format proxy
|
|
260
|
-
- `GET /anthropic/v1/models` — models enabled on the **anthropic** slot, Anthropic list shape (public — no key needed)
|
|
261
|
-
- `GET /health` — public liveness check
|
|
262
|
-
|
|
263
|
-
**Admin (`/admin`, account password — HTTP Basic):**
|
|
264
|
-
|
|
265
|
-
- `/admin/account` `GET` / `PUT` — read or change username/password (either field optional)
|
|
266
|
-
- `/admin/api-key` `GET`, `/admin/api-key/rotate` `POST` — the key agents use
|
|
267
|
-
- `/admin/connection` `GET` — detected LAN IP (for pointing other machines at the gateway)
|
|
268
|
-
- `/admin/providers`, `/admin/providers/:id` `POST`/`PUT`/`DELETE`, `/admin/providers/:id/discover` `POST` — backend CRUD + model discovery
|
|
269
|
-
- `/admin/models`, `/admin/models/:name/{providers,priority,map,disable,test}` — routing-table CRUD, [per-source name mapping](#model-name-mapping), and end-to-end test
|
|
270
|
-
- `/admin/logs` `GET` — recent calls (tail of the on-disk log)
|
|
271
|
-
- `/admin/stats?range=24h|7d|30d|90d|all` `GET` — aggregate stats over retained history
|
|
272
|
-
- `/admin/storage` `GET` — where `data.json` + `logs.jsonl` live
|
|
273
|
-
- `/admin/circuit` `GET`, `/admin/circuit/:id/reset` `POST` — circuit-breaker snapshot + manual reset
|
|
274
|
-
|
|
275
|
-
---
|
|
276
|
-
|
|
277
|
-
## Storage
|
|
278
|
-
|
|
279
|
-
Everything lives in one data directory (default `~/.myapikey`):
|
|
280
|
-
|
|
281
|
-
| File | Contents |
|
|
282
|
-
|---|---|
|
|
283
|
-
| `data.json` | all config — providers, the per-model routing table, account, API key |
|
|
284
|
-
| `logs.jsonl` | call history, one JSON object per line (retained ~90 days / 1 M lines) |
|
|
285
|
-
| `credentials.txt` | human-readable web login + API key, regenerated on every startup |
|
|
286
|
-
| `client.json` | CLI client profile (base url + login + API key) |
|
|
287
|
-
|
|
288
|
-
Override the directory with `--data-dir <path>` or `MYAPIKEY_DATA_DIR`. Call logs are never held in memory: the Logs timeline tail-reads the newest ~200 entries, and stats stream over the full retained file on demand.
|
|
289
|
-
|
|
290
|
-
---
|
|
114
|
+
| `data.json` | all config: backends, routing table, account, API key |
|
|
115
|
+
| `logs.jsonl` | call history (kept ~90 days / 1 M lines) |
|
|
116
|
+
| `credentials.txt` | your login + API key in plain text, rewritten every start |
|
|
117
|
+
| `client.json` | the CLI's saved connection profile |
|
|
291
118
|
|
|
292
119
|
## Development
|
|
293
120
|
|
|
294
121
|
```bash
|
|
295
122
|
npm install
|
|
296
|
-
npm run build:web # build the Vue UI into packages/web/dist
|
|
297
|
-
npm
|
|
298
|
-
npm run dev
|
|
299
|
-
npm
|
|
300
|
-
npm run
|
|
123
|
+
npm run build:web # build the Vue UI into packages/web/dist
|
|
124
|
+
npm run dev # gateway with watch reload
|
|
125
|
+
npm run dev:web # vite dev server (proxies API calls to :7800)
|
|
126
|
+
npm test # vitest unit + integration
|
|
127
|
+
npm run test:e2e # playwright against a real gateway process
|
|
128
|
+
npm run typecheck # tsc + vue-tsc
|
|
301
129
|
```
|
|
302
130
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
---
|
|
306
|
-
|
|
307
|
-
## Notes and non-goals
|
|
131
|
+
## Honest limits
|
|
308
132
|
|
|
309
|
-
- **No OpenAI↔Anthropic translation.**
|
|
310
|
-
- **
|
|
311
|
-
- **
|
|
312
|
-
- **The login password and the API key are separate.** The API key is what agents use; rotate it (`POST /admin/api-key/rotate` or the web UI) if a tool's config leaks. Don't hand either to untrusted code.
|
|
133
|
+
- **No OpenAI↔Anthropic translation.** Wrong entrance for a model → `404`.
|
|
134
|
+
- **Single user, no TLS.** Meant for your own network; put a reverse proxy in front if you expose it.
|
|
135
|
+
- **Web password ≠ API key.** The password administers the UI/CLI; agents use the `sk-myapikey-…` key. If a tool config leaks, rotate the key (Settings, or `POST /admin/api-key/rotate`) and nothing else changes.
|