ai-zero-token 2.0.2 → 2.0.4
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 +20 -0
- package/README.md +31 -6
- package/README.zh-CN.md +31 -6
- package/admin-ui/dist/assets/accounts-CTjk9c4F.js +4 -0
- package/admin-ui/dist/assets/{docs-CihX3Xsm.js → docs-oNIugCIL.js} +3 -3
- package/admin-ui/dist/assets/{image-bed-BGjlDLks.js → image-bed-CQtIhjg_.js} +1 -1
- package/admin-ui/dist/assets/index-By4r-wy3.css +1 -0
- package/admin-ui/dist/assets/index-rgcJgVAu.js +10 -0
- package/admin-ui/dist/assets/{launch-BWw7Odq7.js → launch-B-2Zdz9m.js} +1 -1
- package/admin-ui/dist/assets/logs-JFuSf56b.js +1 -0
- package/admin-ui/dist/assets/{network-detect-cUdjg4zk.js → network-detect-SfvK6uhx.js} +1 -1
- package/admin-ui/dist/assets/{overview-CsjVVcvi.js → overview-X_WodIqE.js} +1 -1
- package/admin-ui/dist/assets/settings-0eXUAvcm.js +1 -0
- package/admin-ui/dist/assets/{tester-BIvH_8DY.js → tester-ocpF053C.js} +1 -1
- package/admin-ui/dist/index.html +2 -2
- package/build/mac-install-guide.txt +25 -0
- package/build/tray-icon-template.png +0 -0
- package/dist/core/providers/openai-codex/chat.js +77 -0
- package/dist/core/services/auth-service.js +88 -12
- package/dist/core/services/chat-service.js +1 -0
- package/dist/core/services/config-service.js +87 -23
- package/dist/core/services/version-service.js +1 -1
- package/dist/core/store/profile-store.js +73 -32
- package/dist/core/store/settings-store.js +14 -0
- package/dist/desktop/main.js +616 -15
- package/dist/server/app.js +512 -58
- package/dist/server/index.js +2 -1
- package/docs/API_USAGE.md +65 -1
- package/docs/DESKTOP_RELEASE.md +48 -3
- package/package.json +33 -2
- package/admin-ui/dist/assets/accounts-Ddq82u6R.js +0 -1
- package/admin-ui/dist/assets/index-CX8e0-BB.js +0 -10
- package/admin-ui/dist/assets/index-ywn2Jwpu.css +0 -1
- package/admin-ui/dist/assets/logs-DDdgDVwo.js +0 -1
- package/admin-ui/dist/assets/settings-Be99HpDD.js +0 -1
|
@@ -3,8 +3,34 @@ import { getPreferredCodexModel, hasCodexModel } from "../models/openai-codex-mo
|
|
|
3
3
|
import {
|
|
4
4
|
createDefaultSettings,
|
|
5
5
|
loadSettings,
|
|
6
|
+
normalizeQuotaSyncConcurrency,
|
|
6
7
|
saveSettings
|
|
7
8
|
} from "../store/settings-store.js";
|
|
9
|
+
function normalizeNetworkProxy(settings, params) {
|
|
10
|
+
const requestedUrl = params.url?.trim() ?? "";
|
|
11
|
+
const url = requestedUrl || (!params.enabled ? settings.networkProxy.url : "");
|
|
12
|
+
const noProxy = params.noProxy?.trim() || settings.networkProxy.noProxy || "localhost,127.0.0.1,::1";
|
|
13
|
+
if (params.enabled) {
|
|
14
|
+
if (!url) {
|
|
15
|
+
throw new Error("\u542F\u7528\u4EE3\u7406\u65F6\u5FC5\u987B\u586B\u5199\u4EE3\u7406\u5730\u5740\u3002");
|
|
16
|
+
}
|
|
17
|
+
let parsed;
|
|
18
|
+
try {
|
|
19
|
+
parsed = new URL(url);
|
|
20
|
+
} catch {
|
|
21
|
+
throw new Error("\u4EE3\u7406\u5730\u5740\u683C\u5F0F\u9519\u8BEF\uFF0C\u8BF7\u586B\u5199\u5B8C\u6574\u7684\u4EE3\u7406 URL\u3002");
|
|
22
|
+
}
|
|
23
|
+
const supportedProtocols = /* @__PURE__ */ new Set(["http:", "https:", "socks4:", "socks4a:", "socks5:", "socks5h:"]);
|
|
24
|
+
if (!supportedProtocols.has(parsed.protocol)) {
|
|
25
|
+
throw new Error("\u4EE3\u7406\u5730\u5740\u4EC5\u652F\u6301 http\u3001https\u3001socks4\u3001socks4a\u3001socks5 \u6216 socks5h\u3002");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
enabled: params.enabled,
|
|
30
|
+
url,
|
|
31
|
+
noProxy
|
|
32
|
+
};
|
|
33
|
+
}
|
|
8
34
|
class ConfigService {
|
|
9
35
|
async getSettings() {
|
|
10
36
|
return this.ensureSettings();
|
|
@@ -43,31 +69,9 @@ class ConfigService {
|
|
|
43
69
|
}
|
|
44
70
|
async setNetworkProxy(params) {
|
|
45
71
|
const settings = await this.getSettings();
|
|
46
|
-
const requestedUrl = params.url?.trim() ?? "";
|
|
47
|
-
const url = requestedUrl || (!params.enabled ? settings.networkProxy.url : "");
|
|
48
|
-
const noProxy = params.noProxy?.trim() || settings.networkProxy.noProxy || "localhost,127.0.0.1,::1";
|
|
49
|
-
if (params.enabled) {
|
|
50
|
-
if (!url) {
|
|
51
|
-
throw new Error("\u542F\u7528\u4EE3\u7406\u65F6\u5FC5\u987B\u586B\u5199\u4EE3\u7406\u5730\u5740\u3002");
|
|
52
|
-
}
|
|
53
|
-
let parsed;
|
|
54
|
-
try {
|
|
55
|
-
parsed = new URL(url);
|
|
56
|
-
} catch {
|
|
57
|
-
throw new Error("\u4EE3\u7406\u5730\u5740\u683C\u5F0F\u9519\u8BEF\uFF0C\u8BF7\u586B\u5199\u5B8C\u6574\u7684\u4EE3\u7406 URL\u3002");
|
|
58
|
-
}
|
|
59
|
-
const supportedProtocols = /* @__PURE__ */ new Set(["http:", "https:", "socks4:", "socks4a:", "socks5:", "socks5h:"]);
|
|
60
|
-
if (!supportedProtocols.has(parsed.protocol)) {
|
|
61
|
-
throw new Error("\u4EE3\u7406\u5730\u5740\u4EC5\u652F\u6301 http\u3001https\u3001socks4\u3001socks4a\u3001socks5 \u6216 socks5h\u3002");
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
72
|
const next = {
|
|
65
73
|
...settings,
|
|
66
|
-
networkProxy:
|
|
67
|
-
enabled: params.enabled,
|
|
68
|
-
url,
|
|
69
|
-
noProxy
|
|
70
|
-
}
|
|
74
|
+
networkProxy: normalizeNetworkProxy(settings, params)
|
|
71
75
|
};
|
|
72
76
|
await saveSettings(next);
|
|
73
77
|
return next;
|
|
@@ -83,6 +87,18 @@ class ConfigService {
|
|
|
83
87
|
await saveSettings(next);
|
|
84
88
|
return next;
|
|
85
89
|
}
|
|
90
|
+
async setRuntimeConfig(params) {
|
|
91
|
+
const settings = await this.getSettings();
|
|
92
|
+
const next = {
|
|
93
|
+
...settings,
|
|
94
|
+
runtime: {
|
|
95
|
+
...settings.runtime,
|
|
96
|
+
quotaSyncConcurrency: normalizeQuotaSyncConcurrency(params.quotaSyncConcurrency, settings.runtime.quotaSyncConcurrency)
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
await saveSettings(next);
|
|
100
|
+
return next;
|
|
101
|
+
}
|
|
86
102
|
async getServerConfig() {
|
|
87
103
|
const settings = await this.getSettings();
|
|
88
104
|
return settings.server;
|
|
@@ -99,6 +115,54 @@ class ConfigService {
|
|
|
99
115
|
await saveSettings(next);
|
|
100
116
|
return next;
|
|
101
117
|
}
|
|
118
|
+
async updateSettings(params) {
|
|
119
|
+
const settings = await this.getSettings();
|
|
120
|
+
let next = { ...settings };
|
|
121
|
+
if (params.defaultModel) {
|
|
122
|
+
if (!await hasCodexModel(params.defaultModel)) {
|
|
123
|
+
throw new Error(`\u5F53\u524D\u7F51\u5173\u672A\u627E\u5230\u53EF\u7528\u6A21\u578B: ${params.defaultModel}`);
|
|
124
|
+
}
|
|
125
|
+
next = {
|
|
126
|
+
...next,
|
|
127
|
+
defaultProvider: "openai-codex",
|
|
128
|
+
defaultModel: params.defaultModel
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
if (params.networkProxy) {
|
|
132
|
+
next = {
|
|
133
|
+
...next,
|
|
134
|
+
networkProxy: normalizeNetworkProxy(next, params.networkProxy)
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (params.autoSwitch) {
|
|
138
|
+
next = {
|
|
139
|
+
...next,
|
|
140
|
+
autoSwitch: {
|
|
141
|
+
enabled: params.autoSwitch.enabled
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (params.runtime) {
|
|
146
|
+
next = {
|
|
147
|
+
...next,
|
|
148
|
+
runtime: {
|
|
149
|
+
...next.runtime,
|
|
150
|
+
quotaSyncConcurrency: normalizeQuotaSyncConcurrency(params.runtime.quotaSyncConcurrency, next.runtime.quotaSyncConcurrency)
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (params.server) {
|
|
155
|
+
next = {
|
|
156
|
+
...next,
|
|
157
|
+
server: {
|
|
158
|
+
...next.server,
|
|
159
|
+
port: params.server.port
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
await saveSettings(next);
|
|
164
|
+
return next;
|
|
165
|
+
}
|
|
102
166
|
async resetSettings() {
|
|
103
167
|
const defaults = createDefaultSettings();
|
|
104
168
|
await saveSettings(defaults);
|
|
@@ -56,7 +56,7 @@ class VersionService {
|
|
|
56
56
|
const manifest = await readPackageManifest();
|
|
57
57
|
const registryUrl = `https://registry.npmjs.org/${encodeURIComponent(manifest.name)}/latest`;
|
|
58
58
|
try {
|
|
59
|
-
const latestVersion = await this.fetchNpmLatestVersion(registryUrl);
|
|
59
|
+
const latestVersion = process.env.AZT_FORCE_LATEST_VERSION || await this.fetchNpmLatestVersion(registryUrl);
|
|
60
60
|
const needsUpdate = compareSemver(manifest.version, latestVersion) < 0;
|
|
61
61
|
return {
|
|
62
62
|
packageName: manifest.name,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
getStorePath
|
|
7
7
|
} from "./state-paths.js";
|
|
8
8
|
const PROFILE_CLAIM_PATH = "https://api.openai.com/profile";
|
|
9
|
+
let storeMutationQueue = Promise.resolve();
|
|
9
10
|
function createEmptyStore() {
|
|
10
11
|
return {
|
|
11
12
|
version: 1,
|
|
@@ -73,36 +74,50 @@ async function saveStore(store) {
|
|
|
73
74
|
await fs.writeFile(getStorePath(), `${JSON.stringify(store, null, 2)}
|
|
74
75
|
`, "utf8");
|
|
75
76
|
}
|
|
77
|
+
async function withStoreMutation(operation) {
|
|
78
|
+
const run = storeMutationQueue.then(operation, operation);
|
|
79
|
+
storeMutationQueue = run.then(
|
|
80
|
+
() => void 0,
|
|
81
|
+
() => void 0
|
|
82
|
+
);
|
|
83
|
+
return run;
|
|
84
|
+
}
|
|
76
85
|
async function saveProfile(profile) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
await withStoreMutation(async () => {
|
|
87
|
+
const store = await loadStore();
|
|
88
|
+
store.profiles[profile.profileId] = profile;
|
|
89
|
+
store.activeProfileId = profile.profileId;
|
|
90
|
+
await saveStore(store);
|
|
91
|
+
});
|
|
81
92
|
}
|
|
82
93
|
async function updateProfile(profileId, updater) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
return withStoreMutation(async () => {
|
|
95
|
+
const store = await loadStore();
|
|
96
|
+
const profile = store.profiles[profileId];
|
|
97
|
+
if (!profile) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const updated = updater(profile);
|
|
101
|
+
store.profiles[profileId] = updated;
|
|
102
|
+
await saveStore(store);
|
|
103
|
+
return updated;
|
|
104
|
+
});
|
|
92
105
|
}
|
|
93
106
|
async function listProfiles() {
|
|
94
107
|
const store = await loadStore();
|
|
95
108
|
return Object.values(store.profiles);
|
|
96
109
|
}
|
|
97
110
|
async function setActiveProfile(profileId) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
111
|
+
return withStoreMutation(async () => {
|
|
112
|
+
const store = await loadStore();
|
|
113
|
+
const profile = store.profiles[profileId];
|
|
114
|
+
if (!profile) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
store.activeProfileId = profileId;
|
|
118
|
+
await saveStore(store);
|
|
119
|
+
return profile;
|
|
120
|
+
});
|
|
106
121
|
}
|
|
107
122
|
async function getActiveProfile() {
|
|
108
123
|
const store = await loadStore();
|
|
@@ -114,19 +129,44 @@ async function getActiveProfile() {
|
|
|
114
129
|
return first ?? null;
|
|
115
130
|
}
|
|
116
131
|
async function removeProfile(profileId) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
store.activeProfileId
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
132
|
+
return withStoreMutation(async () => {
|
|
133
|
+
const store = await loadStore();
|
|
134
|
+
if (!store.profiles[profileId]) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
delete store.profiles[profileId];
|
|
138
|
+
if (store.activeProfileId === profileId) {
|
|
139
|
+
store.activeProfileId = Object.keys(store.profiles)[0];
|
|
140
|
+
}
|
|
141
|
+
await saveStore(store);
|
|
142
|
+
return store.activeProfileId ? store.profiles[store.activeProfileId] ?? null : null;
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
async function removeProfiles(profileIds) {
|
|
146
|
+
return withStoreMutation(async () => {
|
|
147
|
+
const idSet = new Set(profileIds.map((id) => id.trim()).filter(Boolean));
|
|
148
|
+
if (idSet.size === 0) {
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
const store = await loadStore();
|
|
152
|
+
let removed = 0;
|
|
153
|
+
for (const profileId of idSet) {
|
|
154
|
+
if (store.profiles[profileId]) {
|
|
155
|
+
delete store.profiles[profileId];
|
|
156
|
+
removed += 1;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (store.activeProfileId && !store.profiles[store.activeProfileId]) {
|
|
160
|
+
store.activeProfileId = Object.keys(store.profiles)[0];
|
|
161
|
+
}
|
|
162
|
+
await saveStore(store);
|
|
163
|
+
return removed;
|
|
164
|
+
});
|
|
127
165
|
}
|
|
128
166
|
async function clearStore() {
|
|
129
|
-
await
|
|
167
|
+
await withStoreMutation(async () => {
|
|
168
|
+
await fs.rm(getStateDir(), { recursive: true, force: true });
|
|
169
|
+
});
|
|
130
170
|
}
|
|
131
171
|
export {
|
|
132
172
|
clearStore,
|
|
@@ -136,6 +176,7 @@ export {
|
|
|
136
176
|
listProfiles,
|
|
137
177
|
loadStore,
|
|
138
178
|
removeProfile,
|
|
179
|
+
removeProfiles,
|
|
139
180
|
saveProfile,
|
|
140
181
|
saveStore,
|
|
141
182
|
setActiveProfile,
|
|
@@ -18,6 +18,9 @@ function createDefaultSettings() {
|
|
|
18
18
|
autoSwitch: {
|
|
19
19
|
enabled: false
|
|
20
20
|
},
|
|
21
|
+
runtime: {
|
|
22
|
+
quotaSyncConcurrency: 16
|
|
23
|
+
},
|
|
21
24
|
server: {
|
|
22
25
|
host: "0.0.0.0",
|
|
23
26
|
port: 8787
|
|
@@ -42,6 +45,9 @@ async function loadSettings() {
|
|
|
42
45
|
autoSwitch: {
|
|
43
46
|
enabled: parsed.autoSwitch?.enabled ?? defaults.autoSwitch.enabled
|
|
44
47
|
},
|
|
48
|
+
runtime: {
|
|
49
|
+
quotaSyncConcurrency: normalizeQuotaSyncConcurrency(parsed.runtime?.quotaSyncConcurrency, defaults.runtime.quotaSyncConcurrency)
|
|
50
|
+
},
|
|
45
51
|
server: {
|
|
46
52
|
host: parsed.server?.host ?? defaults.server.host,
|
|
47
53
|
port: parsed.server?.port ?? defaults.server.port
|
|
@@ -51,6 +57,13 @@ async function loadSettings() {
|
|
|
51
57
|
return createDefaultSettings();
|
|
52
58
|
}
|
|
53
59
|
}
|
|
60
|
+
function normalizeQuotaSyncConcurrency(value, fallback = 16) {
|
|
61
|
+
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number.parseInt(value, 10) : fallback;
|
|
62
|
+
if (!Number.isFinite(parsed)) {
|
|
63
|
+
return fallback;
|
|
64
|
+
}
|
|
65
|
+
return Math.min(32, Math.max(1, Math.trunc(parsed)));
|
|
66
|
+
}
|
|
54
67
|
async function saveSettings(settings) {
|
|
55
68
|
await ensureStateMigrated();
|
|
56
69
|
await fs.mkdir(getStateDir(), { recursive: true });
|
|
@@ -61,5 +74,6 @@ export {
|
|
|
61
74
|
createDefaultSettings,
|
|
62
75
|
getSettingsPath,
|
|
63
76
|
loadSettings,
|
|
77
|
+
normalizeQuotaSyncConcurrency,
|
|
64
78
|
saveSettings
|
|
65
79
|
};
|