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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
getCodexModelCatalog,
|
|
4
|
+
hasCodexModel
|
|
5
5
|
} from "../models/openai-codex-models.js";
|
|
6
6
|
class ModelService {
|
|
7
7
|
constructor(configService) {
|
|
@@ -11,12 +11,37 @@ class ModelService {
|
|
|
11
11
|
if (provider !== "openai-codex") {
|
|
12
12
|
throw new Error(`\u6682\u4E0D\u652F\u6301 provider: ${provider}`);
|
|
13
13
|
}
|
|
14
|
-
const defaultModel = await
|
|
15
|
-
|
|
14
|
+
const [{ models }, defaultModel] = await Promise.all([
|
|
15
|
+
getCodexModelCatalog(),
|
|
16
|
+
this.configService.getDefaultModel(provider)
|
|
17
|
+
]);
|
|
18
|
+
return models.map((model) => ({
|
|
16
19
|
...model,
|
|
17
20
|
isDefault: model.id === defaultModel
|
|
18
21
|
}));
|
|
19
22
|
}
|
|
23
|
+
async getCatalog(provider = "openai-codex") {
|
|
24
|
+
if (provider !== "openai-codex") {
|
|
25
|
+
throw new Error(`\u6682\u4E0D\u652F\u6301 provider: ${provider}`);
|
|
26
|
+
}
|
|
27
|
+
return (await getCodexModelCatalog()).catalog;
|
|
28
|
+
}
|
|
29
|
+
async refreshModels(provider = "openai-codex") {
|
|
30
|
+
if (provider !== "openai-codex") {
|
|
31
|
+
throw new Error(`\u6682\u4E0D\u652F\u6301 provider: ${provider}`);
|
|
32
|
+
}
|
|
33
|
+
const [{ models, catalog }, defaultModel] = await Promise.all([
|
|
34
|
+
getCodexModelCatalog(),
|
|
35
|
+
this.configService.getDefaultModel(provider)
|
|
36
|
+
]);
|
|
37
|
+
return {
|
|
38
|
+
models: models.map((model) => ({
|
|
39
|
+
...model,
|
|
40
|
+
isDefault: model.id === defaultModel
|
|
41
|
+
})),
|
|
42
|
+
catalog
|
|
43
|
+
};
|
|
44
|
+
}
|
|
20
45
|
async getDefaultModel(provider = "openai-codex") {
|
|
21
46
|
if (provider !== "openai-codex") {
|
|
22
47
|
throw new Error(`\u6682\u4E0D\u652F\u6301 provider: ${provider}`);
|
|
@@ -33,8 +58,8 @@ class ModelService {
|
|
|
33
58
|
if (options?.allowUnknown) {
|
|
34
59
|
return requested;
|
|
35
60
|
}
|
|
36
|
-
if (!
|
|
37
|
-
throw new Error(`\u5F53\u524D
|
|
61
|
+
if (!await hasCodexModel(requested)) {
|
|
62
|
+
throw new Error(`\u5F53\u524D\u7F51\u5173\u672A\u627E\u5230\u53EF\u7528\u6A21\u578B: ${requested}`);
|
|
38
63
|
}
|
|
39
64
|
return requested;
|
|
40
65
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { requestText } from "../providers/http-client.js";
|
|
6
|
+
const VERSION_CACHE_TTL_MS = 10 * 60 * 1e3;
|
|
7
|
+
const packageJsonPath = path.dirname(fileURLToPath(new URL("../../../package.json", import.meta.url)));
|
|
8
|
+
function compareVersionPart(left, right) {
|
|
9
|
+
const leftNumber = Number.parseInt(left, 10);
|
|
10
|
+
const rightNumber = Number.parseInt(right, 10);
|
|
11
|
+
if (Number.isFinite(leftNumber) && Number.isFinite(rightNumber)) {
|
|
12
|
+
return leftNumber - rightNumber;
|
|
13
|
+
}
|
|
14
|
+
return left.localeCompare(right);
|
|
15
|
+
}
|
|
16
|
+
function compareSemver(left, right) {
|
|
17
|
+
const leftParts = left.split(/[.+-]/);
|
|
18
|
+
const rightParts = right.split(/[.+-]/);
|
|
19
|
+
const maxLength = Math.max(leftParts.length, rightParts.length);
|
|
20
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
21
|
+
const diff = compareVersionPart(leftParts[index] ?? "0", rightParts[index] ?? "0");
|
|
22
|
+
if (diff !== 0) {
|
|
23
|
+
return diff;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
async function readPackageManifest() {
|
|
29
|
+
const raw = await fs.readFile(path.join(packageJsonPath, "package.json"), "utf8");
|
|
30
|
+
const parsed = JSON.parse(raw);
|
|
31
|
+
return {
|
|
32
|
+
name: parsed.name ?? "ai-zero-token",
|
|
33
|
+
version: parsed.version ?? "0.0.0"
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
class VersionService {
|
|
37
|
+
cache = null;
|
|
38
|
+
inFlight = null;
|
|
39
|
+
async getVersionStatus(options) {
|
|
40
|
+
const now = Date.now();
|
|
41
|
+
if (!options?.force && this.cache && now - this.cache.checkedAt < VERSION_CACHE_TTL_MS) {
|
|
42
|
+
return this.cache;
|
|
43
|
+
}
|
|
44
|
+
if (this.inFlight) {
|
|
45
|
+
return this.inFlight;
|
|
46
|
+
}
|
|
47
|
+
this.inFlight = this.fetchVersionStatus().then((status) => {
|
|
48
|
+
this.cache = status;
|
|
49
|
+
return status;
|
|
50
|
+
}).finally(() => {
|
|
51
|
+
this.inFlight = null;
|
|
52
|
+
});
|
|
53
|
+
return this.inFlight;
|
|
54
|
+
}
|
|
55
|
+
async fetchVersionStatus() {
|
|
56
|
+
const manifest = await readPackageManifest();
|
|
57
|
+
const registryUrl = `https://registry.npmjs.org/${encodeURIComponent(manifest.name)}/latest`;
|
|
58
|
+
try {
|
|
59
|
+
const response = await requestText({
|
|
60
|
+
method: "GET",
|
|
61
|
+
url: registryUrl,
|
|
62
|
+
timeoutMs: 5e3
|
|
63
|
+
});
|
|
64
|
+
if (response.status < 200 || response.status >= 300) {
|
|
65
|
+
throw new Error(`npm registry returned ${response.status}`);
|
|
66
|
+
}
|
|
67
|
+
const parsed = JSON.parse(response.body);
|
|
68
|
+
const latestVersion = typeof parsed.version === "string" && parsed.version ? parsed.version : void 0;
|
|
69
|
+
if (!latestVersion) {
|
|
70
|
+
throw new Error("npm registry did not return a version");
|
|
71
|
+
}
|
|
72
|
+
const needsUpdate = compareSemver(manifest.version, latestVersion) < 0;
|
|
73
|
+
return {
|
|
74
|
+
packageName: manifest.name,
|
|
75
|
+
currentVersion: manifest.version,
|
|
76
|
+
latestVersion,
|
|
77
|
+
checkedAt: Date.now(),
|
|
78
|
+
needsUpdate,
|
|
79
|
+
registryUrl,
|
|
80
|
+
status: needsUpdate ? "update-available" : "ok"
|
|
81
|
+
};
|
|
82
|
+
} catch (error) {
|
|
83
|
+
return {
|
|
84
|
+
packageName: manifest.name,
|
|
85
|
+
currentVersion: manifest.version,
|
|
86
|
+
checkedAt: Date.now(),
|
|
87
|
+
needsUpdate: false,
|
|
88
|
+
registryUrl,
|
|
89
|
+
status: "error",
|
|
90
|
+
error: error instanceof Error ? error.message : String(error)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
VersionService
|
|
97
|
+
};
|