ai-zero-token 1.0.2 → 1.0.3
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/CHANGELOG.md +14 -0
- package/README.md +9 -0
- package/dist/cli/commands/help.js +2 -1
- package/dist/cli/commands/models.js +14 -3
- package/dist/cli/index.js +1 -1
- package/dist/core/context.js +3 -0
- package/dist/core/models/openai-codex-models.js +89 -0
- package/dist/core/providers/http-client.js +41 -6
- package/dist/core/services/auth-service.js +36 -0
- package/dist/core/services/config-service.js +4 -4
- package/dist/core/services/image-service.js +119 -74
- package/dist/core/services/model-service.js +31 -6
- package/dist/core/services/version-service.js +97 -0
- package/dist/server/admin-page.js +641 -91
- package/dist/server/app.js +40 -3
- package/docs/API_USAGE.md +120 -0
- package/package.json +3 -1
package/dist/server/app.js
CHANGED
|
@@ -298,7 +298,11 @@ function normalizeError(error) {
|
|
|
298
298
|
return error instanceof Error ? error : new Error(String(error));
|
|
299
299
|
}
|
|
300
300
|
function getErrorStatusCode(error) {
|
|
301
|
-
const
|
|
301
|
+
const normalized = normalizeError(error);
|
|
302
|
+
if (typeof normalized.statusCode === "number") {
|
|
303
|
+
return normalized.statusCode;
|
|
304
|
+
}
|
|
305
|
+
const message = normalized.message;
|
|
302
306
|
if (message.includes("\u7F3A\u5C11") || message.includes("\u683C\u5F0F\u9519\u8BEF") || message.includes("\u672A\u5185\u7F6E\u6A21\u578B") || message.includes("\u4E0D\u652F\u6301") || message.includes("\u6CA1\u6709\u63D0\u4F9B")) {
|
|
303
307
|
return 400;
|
|
304
308
|
}
|
|
@@ -335,9 +339,11 @@ function createApp(params) {
|
|
|
335
339
|
};
|
|
336
340
|
});
|
|
337
341
|
async function buildAdminConfig(request) {
|
|
338
|
-
const [status, models, settings, profile, profiles] = await Promise.all([
|
|
342
|
+
const [status, models, modelCatalog, versionStatus, settings, profile, profiles] = await Promise.all([
|
|
339
343
|
ctx.authService.getStatus(),
|
|
340
344
|
ctx.modelService.listModels(),
|
|
345
|
+
ctx.modelService.getCatalog(),
|
|
346
|
+
ctx.versionService.getVersionStatus(),
|
|
341
347
|
ctx.configService.getSettings(),
|
|
342
348
|
ctx.authService.getActiveProfile(),
|
|
343
349
|
ctx.authService.listProfiles()
|
|
@@ -347,6 +353,8 @@ function createApp(params) {
|
|
|
347
353
|
status,
|
|
348
354
|
settings,
|
|
349
355
|
models,
|
|
356
|
+
modelCatalog,
|
|
357
|
+
versionStatus,
|
|
350
358
|
profile: serializeProfile(profile),
|
|
351
359
|
profiles: profiles.map((item) => serializeManagedProfile(item)),
|
|
352
360
|
adminUrl: `${origin}/`,
|
|
@@ -386,11 +394,33 @@ function createApp(params) {
|
|
|
386
394
|
app.get("/_gateway/health", async () => ({ ok: true }));
|
|
387
395
|
app.get("/_gateway/status", async () => ctx.authService.getStatus());
|
|
388
396
|
app.get("/_gateway/models", async () => ({
|
|
389
|
-
data: await ctx.modelService.listModels()
|
|
397
|
+
data: await ctx.modelService.listModels(),
|
|
398
|
+
catalog: await ctx.modelService.getCatalog()
|
|
390
399
|
}));
|
|
400
|
+
app.post("/_gateway/models/refresh", async () => {
|
|
401
|
+
const result = await ctx.modelService.refreshModels();
|
|
402
|
+
return {
|
|
403
|
+
data: result.models,
|
|
404
|
+
catalog: result.catalog
|
|
405
|
+
};
|
|
406
|
+
});
|
|
407
|
+
app.post("/_gateway/admin/runtime-refresh", async (request) => {
|
|
408
|
+
await Promise.all([
|
|
409
|
+
ctx.authService.syncActiveProfileQuota("openai-codex", {
|
|
410
|
+
suppressErrors: true
|
|
411
|
+
}),
|
|
412
|
+
ctx.versionService.getVersionStatus({
|
|
413
|
+
force: true
|
|
414
|
+
})
|
|
415
|
+
]);
|
|
416
|
+
return buildAdminConfig(request);
|
|
417
|
+
});
|
|
391
418
|
app.get("/_gateway/admin/config", async (request) => buildAdminConfig(request));
|
|
392
419
|
app.post("/_gateway/admin/login", async (request) => {
|
|
393
420
|
await ctx.authService.login("openai-codex");
|
|
421
|
+
await ctx.authService.syncActiveProfileQuota("openai-codex", {
|
|
422
|
+
suppressErrors: true
|
|
423
|
+
});
|
|
394
424
|
return buildAdminConfig(request);
|
|
395
425
|
});
|
|
396
426
|
app.post("/_gateway/admin/logout", async (request) => {
|
|
@@ -409,6 +439,13 @@ function createApp(params) {
|
|
|
409
439
|
};
|
|
410
440
|
}
|
|
411
441
|
await ctx.authService.activateProfile(parsed.data.profileId);
|
|
442
|
+
await ctx.authService.syncActiveProfileQuota("openai-codex", {
|
|
443
|
+
suppressErrors: true
|
|
444
|
+
});
|
|
445
|
+
return buildAdminConfig(request);
|
|
446
|
+
});
|
|
447
|
+
app.post("/_gateway/admin/profiles/sync-quota", async (request) => {
|
|
448
|
+
await ctx.authService.syncActiveProfileQuota("openai-codex");
|
|
412
449
|
return buildAdminConfig(request);
|
|
413
450
|
});
|
|
414
451
|
app.post("/_gateway/admin/profiles/remove", async (request, reply) => {
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# AI Zero Token API Usage
|
|
2
|
+
|
|
3
|
+
This guide is for Vibe Coding tools, OpenAI-compatible SDKs, local frontends, and scripts that need to call AI Zero Token through HTTP.
|
|
4
|
+
|
|
5
|
+
## Base URL
|
|
6
|
+
|
|
7
|
+
Start the local gateway:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
azt start
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Default API base URL:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
http://127.0.0.1:8787/v1
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
For another device on the same network, replace `127.0.0.1` with the gateway machine IP.
|
|
20
|
+
|
|
21
|
+
## Auth
|
|
22
|
+
|
|
23
|
+
The local gateway does not require an API key by default.
|
|
24
|
+
|
|
25
|
+
Most OpenAI-compatible clients still require a non-empty key value. Use a placeholder:
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
local
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Vibe Coding Settings
|
|
32
|
+
|
|
33
|
+
Use these values in an OpenAI-compatible provider setup:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
API Base URL: http://127.0.0.1:8787/v1
|
|
37
|
+
API Key: local
|
|
38
|
+
Text model: gpt-5.4
|
|
39
|
+
Image model: gpt-image-2
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Use `GET /v1/models` to see the models available through the current local Codex cache.
|
|
43
|
+
|
|
44
|
+
## Models
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
curl http://127.0.0.1:8787/v1/models
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Refresh the local Codex model list:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
azt models --refresh
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Responses API
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
curl http://127.0.0.1:8787/v1/responses \
|
|
60
|
+
-H "Content-Type: application/json" \
|
|
61
|
+
-d '{
|
|
62
|
+
"model": "gpt-5.4",
|
|
63
|
+
"input": "Reply with OK only."
|
|
64
|
+
}'
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Chat Completions API
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
curl http://127.0.0.1:8787/v1/chat/completions \
|
|
71
|
+
-H "Content-Type: application/json" \
|
|
72
|
+
-d '{
|
|
73
|
+
"model": "gpt-5.4",
|
|
74
|
+
"messages": [
|
|
75
|
+
{ "role": "user", "content": "Reply with OK only." }
|
|
76
|
+
]
|
|
77
|
+
}'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Images API
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
curl http://127.0.0.1:8787/v1/images/generations \
|
|
84
|
+
-H "Content-Type: application/json" \
|
|
85
|
+
-d '{
|
|
86
|
+
"model": "gpt-image-2",
|
|
87
|
+
"prompt": "A clean product poster on a white desk with a laptop and glass cup.",
|
|
88
|
+
"size": "1024x1024",
|
|
89
|
+
"quality": "low",
|
|
90
|
+
"response_format": "b64_json"
|
|
91
|
+
}'
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## JavaScript SDK Example
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import OpenAI from "openai";
|
|
98
|
+
|
|
99
|
+
const client = new OpenAI({
|
|
100
|
+
apiKey: "local",
|
|
101
|
+
baseURL: "http://127.0.0.1:8787/v1",
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const response = await client.chat.completions.create({
|
|
105
|
+
model: "gpt-5.4",
|
|
106
|
+
messages: [
|
|
107
|
+
{ role: "user", content: "Reply with OK only." },
|
|
108
|
+
],
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
console.log(response.choices[0]?.message?.content);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Notes
|
|
115
|
+
|
|
116
|
+
- Login first through the management page or `azt login`.
|
|
117
|
+
- A model appearing in `/v1/models` means the local Codex cache lists it. Final availability still depends on the active account.
|
|
118
|
+
- `stream=true` is not supported yet.
|
|
119
|
+
- The default listener is `0.0.0.0:8787`, so local-network clients can call the gateway by using the machine IP.
|
|
120
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-zero-token",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Local-first OpenAI-compatible AI CLI and gateway with Codex OAuth, multi-account management, and gpt-image-2 image generation.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -57,6 +57,8 @@
|
|
|
57
57
|
},
|
|
58
58
|
"files": [
|
|
59
59
|
"dist",
|
|
60
|
+
"CHANGELOG.md",
|
|
61
|
+
"docs/API_USAGE.md",
|
|
60
62
|
"README.md",
|
|
61
63
|
"package.json"
|
|
62
64
|
]
|