@tokenbuddy/tb-admin 1.0.13 → 1.0.15
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/dist/src/bootstrap-registry.d.ts +1 -0
- package/dist/src/bootstrap-registry.d.ts.map +1 -1
- package/dist/src/bootstrap-registry.js.map +1 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +30 -16
- package/dist/src/cli.js.map +1 -1
- package/dist/src/server-cmd.d.ts +27 -2
- package/dist/src/server-cmd.d.ts.map +1 -1
- package/dist/src/server-cmd.js +131 -26
- package/dist/src/server-cmd.js.map +1 -1
- package/dist/src/ui-actions.d.ts +88 -0
- package/dist/src/ui-actions.d.ts.map +1 -0
- package/dist/src/ui-actions.js +763 -0
- package/dist/src/ui-actions.js.map +1 -0
- package/dist/src/ui-command.d.ts +4 -0
- package/dist/src/ui-command.d.ts.map +1 -0
- package/dist/src/ui-command.js +37 -0
- package/dist/src/ui-command.js.map +1 -0
- package/dist/src/ui-server.d.ts +23 -0
- package/dist/src/ui-server.d.ts.map +1 -0
- package/dist/src/ui-server.js +245 -0
- package/dist/src/ui-server.js.map +1 -0
- package/dist/src/ui-state.d.ts +134 -0
- package/dist/src/ui-state.d.ts.map +1 -0
- package/dist/src/ui-state.js +407 -0
- package/dist/src/ui-state.js.map +1 -0
- package/dist/src/ui-static.d.ts +2 -0
- package/dist/src/ui-static.d.ts.map +1 -0
- package/dist/src/ui-static.js +144 -0
- package/dist/src/ui-static.js.map +1 -0
- package/dist/src/upstream-balance-probe.d.ts +41 -0
- package/dist/src/upstream-balance-probe.d.ts.map +1 -0
- package/dist/src/upstream-balance-probe.js +379 -0
- package/dist/src/upstream-balance-probe.js.map +1 -0
- package/package.json +1 -1
- package/src/bootstrap-registry.ts +1 -0
- package/src/cli.ts +32 -16
- package/src/server-cmd.ts +163 -29
- package/src/ui-actions.ts +901 -0
- package/src/ui-command.ts +39 -0
- package/src/ui-server.ts +308 -0
- package/src/ui-state.ts +575 -0
- package/src/ui-static.ts +144 -0
- package/src/upstream-balance-probe.ts +505 -0
- package/tests/admin.test.ts +893 -4
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
const DEFAULT_TIMEOUT_MS = 7000;
|
|
2
|
+
const FAILURE_CACHE_TTL_MS = 30000;
|
|
3
|
+
const DEFAULT_CNY_USD_RATE = 0.14;
|
|
4
|
+
export class BalanceProbeCache {
|
|
5
|
+
entries = new Map();
|
|
6
|
+
get(key, now) {
|
|
7
|
+
const entry = this.entries.get(key);
|
|
8
|
+
if (!entry || entry.expiresAt <= now) {
|
|
9
|
+
if (entry) {
|
|
10
|
+
this.entries.delete(key);
|
|
11
|
+
}
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
return entry.snapshot;
|
|
15
|
+
}
|
|
16
|
+
setFailure(key, snapshot, now) {
|
|
17
|
+
this.entries.set(key, {
|
|
18
|
+
snapshot,
|
|
19
|
+
expiresAt: now + FAILURE_CACHE_TTL_MS
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export const defaultBalanceProbeCache = new BalanceProbeCache();
|
|
24
|
+
export async function probeUpstreamBalance(config, options = {}) {
|
|
25
|
+
const now = options.now || Date.now;
|
|
26
|
+
const fetchedAt = now();
|
|
27
|
+
const key = cacheKey(config);
|
|
28
|
+
const cache = options.cache || defaultBalanceProbeCache;
|
|
29
|
+
const cached = cache.get(key, fetchedAt);
|
|
30
|
+
if (cached) {
|
|
31
|
+
return cached;
|
|
32
|
+
}
|
|
33
|
+
const plan = requestPlan(config);
|
|
34
|
+
if (!plan) {
|
|
35
|
+
const snapshot = failure("unknown", fetchedAt, 0, "unsupported upstream - configure a balance parser");
|
|
36
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
37
|
+
return snapshot;
|
|
38
|
+
}
|
|
39
|
+
if (!config.upstreamApiKey) {
|
|
40
|
+
const snapshot = failure(plan.source, fetchedAt, 0, "missing upstreamApiKey for balance probe");
|
|
41
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
42
|
+
return snapshot;
|
|
43
|
+
}
|
|
44
|
+
const upstreamUserId = stringValue(config.upstreamBalanceProbe?.userId) || stringValue(config.upstreamUserId);
|
|
45
|
+
if (plan.requiresUserId && !upstreamUserId) {
|
|
46
|
+
const snapshot = failure(plan.source, fetchedAt, 0, "missing upstreamUserId for newapi upstream");
|
|
47
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
48
|
+
return snapshot;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const response = await fetchWithTimeout(plan.url, {
|
|
52
|
+
method: "GET",
|
|
53
|
+
headers: requestHeaders(config.upstreamApiKey, plan.requiresUserId ? upstreamUserId : undefined)
|
|
54
|
+
}, options.fetch || fetch, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
const snapshot = failure(plan.source, fetchedAt, response.status, httpErrorMessage(response.status));
|
|
57
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
58
|
+
return snapshot;
|
|
59
|
+
}
|
|
60
|
+
const payload = await response.json();
|
|
61
|
+
const snapshot = parseBalancePayload(payload, plan, fetchedAt, cnyUsdRate(options.cnyUsdRate));
|
|
62
|
+
if (snapshot.error) {
|
|
63
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
64
|
+
}
|
|
65
|
+
return snapshot;
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const snapshot = failure(plan.source, fetchedAt, 0, `network: ${err instanceof Error ? err.message : String(err)}`);
|
|
69
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
70
|
+
return snapshot;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function requestPlan(config) {
|
|
74
|
+
const template = balanceProbeTemplateValue(config.upstreamBalanceProbe?.template);
|
|
75
|
+
if (template === "none") {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
const balanceUrl = stringValue(config.upstreamBalanceProbe?.url) || stringValue(config.upstreamBalanceUrl);
|
|
79
|
+
const upstreamUrl = stringValue(config.upstreamUrl);
|
|
80
|
+
if (template && template !== "auto") {
|
|
81
|
+
return explicitRequestPlan(template, balanceUrl, upstreamUrl);
|
|
82
|
+
}
|
|
83
|
+
const host = hostName(balanceUrl || upstreamUrl);
|
|
84
|
+
if (host === "api.deepseek.com") {
|
|
85
|
+
return { source: "deepseek", url: "https://api.deepseek.com/user/balance", currency: "CNY", requiresUserId: false };
|
|
86
|
+
}
|
|
87
|
+
if (host === "api.stepfun.ai" || host === "api.stepfun.com") {
|
|
88
|
+
return { source: "stepfun", url: "https://api.stepfun.com/v1/accounts", currency: "CNY", requiresUserId: false };
|
|
89
|
+
}
|
|
90
|
+
if (host === "api.siliconflow.cn" || host === "api.siliconflow.com") {
|
|
91
|
+
const currency = host.endsWith(".cn") ? "CNY" : "USD";
|
|
92
|
+
const url = host.endsWith(".cn") ? "https://api.siliconflow.cn/v1/user/info" : "https://api.siliconflow.com/v1/user/info";
|
|
93
|
+
return { source: "siliconflow", url, currency, requiresUserId: false };
|
|
94
|
+
}
|
|
95
|
+
if (host === "openrouter.ai") {
|
|
96
|
+
return { source: "openrouter", url: "https://openrouter.ai/api/v1/credits", currency: "USD", requiresUserId: false };
|
|
97
|
+
}
|
|
98
|
+
if (host === "api.novita.ai") {
|
|
99
|
+
return { source: "novita", url: "https://api.novita.ai/v3/user/balance", currency: "USD", requiresUserId: false };
|
|
100
|
+
}
|
|
101
|
+
if (balanceUrl && isUsageEndpoint(balanceUrl)) {
|
|
102
|
+
return { source: "usage_generic", url: balanceUrl, currency: "USD", requiresUserId: false };
|
|
103
|
+
}
|
|
104
|
+
if (balanceUrl) {
|
|
105
|
+
return { source: "newapi_generic", url: balanceUrl, currency: "USD", requiresUserId: true };
|
|
106
|
+
}
|
|
107
|
+
const genericUsageUrl = upstreamUrl ? usageUrl(upstreamUrl) : undefined;
|
|
108
|
+
if (genericUsageUrl) {
|
|
109
|
+
return { source: "usage_generic", url: genericUsageUrl, currency: "USD", requiresUserId: false };
|
|
110
|
+
}
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
function explicitRequestPlan(template, balanceUrl, upstreamUrl) {
|
|
114
|
+
if (template === "deepseek") {
|
|
115
|
+
return { source: "deepseek", url: balanceUrl || "https://api.deepseek.com/user/balance", currency: "CNY", requiresUserId: false };
|
|
116
|
+
}
|
|
117
|
+
if (template === "stepfun") {
|
|
118
|
+
return { source: "stepfun", url: balanceUrl || "https://api.stepfun.com/v1/accounts", currency: "CNY", requiresUserId: false };
|
|
119
|
+
}
|
|
120
|
+
if (template === "siliconflow") {
|
|
121
|
+
const host = hostName(balanceUrl || upstreamUrl);
|
|
122
|
+
const currency = host.endsWith(".com") ? "USD" : "CNY";
|
|
123
|
+
const url = balanceUrl || (currency === "USD" ? "https://api.siliconflow.com/v1/user/info" : "https://api.siliconflow.cn/v1/user/info");
|
|
124
|
+
return { source: "siliconflow", url, currency, requiresUserId: false };
|
|
125
|
+
}
|
|
126
|
+
if (template === "openrouter") {
|
|
127
|
+
return { source: "openrouter", url: balanceUrl || "https://openrouter.ai/api/v1/credits", currency: "USD", requiresUserId: false };
|
|
128
|
+
}
|
|
129
|
+
if (template === "novita") {
|
|
130
|
+
return { source: "novita", url: balanceUrl || "https://api.novita.ai/v3/user/balance", currency: "USD", requiresUserId: false };
|
|
131
|
+
}
|
|
132
|
+
if (template === "newapi_generic") {
|
|
133
|
+
return balanceUrl ? { source: "newapi_generic", url: balanceUrl, currency: "USD", requiresUserId: true } : undefined;
|
|
134
|
+
}
|
|
135
|
+
if (template === "usage_generic") {
|
|
136
|
+
const url = balanceUrl || (upstreamUrl ? usageUrl(upstreamUrl) : undefined);
|
|
137
|
+
return url ? { source: "usage_generic", url, currency: "USD", requiresUserId: false } : undefined;
|
|
138
|
+
}
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
function requestHeaders(upstreamApiKey, upstreamUserId) {
|
|
142
|
+
const headers = {
|
|
143
|
+
"Authorization": `Bearer ${upstreamApiKey}`
|
|
144
|
+
};
|
|
145
|
+
if (upstreamUserId) {
|
|
146
|
+
headers["New-Api-User"] = upstreamUserId;
|
|
147
|
+
}
|
|
148
|
+
return headers;
|
|
149
|
+
}
|
|
150
|
+
async function fetchWithTimeout(url, init, fetchFn, timeoutMs) {
|
|
151
|
+
const controller = new AbortController();
|
|
152
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
153
|
+
try {
|
|
154
|
+
return await fetchFn(url, { ...init, signal: controller.signal });
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
clearTimeout(timer);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function parseBalancePayload(payload, plan, fetchedAt, cnyRate) {
|
|
161
|
+
const object = objectValue(payload);
|
|
162
|
+
if (!object) {
|
|
163
|
+
return failure(plan.source, fetchedAt, 200, "balance response must be an object");
|
|
164
|
+
}
|
|
165
|
+
if (plan.source === "deepseek") {
|
|
166
|
+
return parseDeepSeek(object, fetchedAt, cnyRate);
|
|
167
|
+
}
|
|
168
|
+
if (plan.source === "stepfun") {
|
|
169
|
+
return amountSnapshot(numberFrom(object.balance), "CNY", "stepfun", fetchedAt, cnyRate);
|
|
170
|
+
}
|
|
171
|
+
if (plan.source === "siliconflow") {
|
|
172
|
+
return parseSiliconFlow(object, plan.currency, fetchedAt, cnyRate);
|
|
173
|
+
}
|
|
174
|
+
if (plan.source === "openrouter") {
|
|
175
|
+
return parseOpenRouter(object, fetchedAt, cnyRate);
|
|
176
|
+
}
|
|
177
|
+
if (plan.source === "novita") {
|
|
178
|
+
const availableBalance = numberFrom(object.availableBalance);
|
|
179
|
+
return amountSnapshot(availableBalance === null ? null : availableBalance / 10000, "USD", "novita", fetchedAt, cnyRate);
|
|
180
|
+
}
|
|
181
|
+
if (plan.source === "newapi_generic") {
|
|
182
|
+
return parseNewApi(object, fetchedAt, cnyRate);
|
|
183
|
+
}
|
|
184
|
+
if (plan.source === "usage_generic") {
|
|
185
|
+
return parseUsageGeneric(object, fetchedAt, cnyRate);
|
|
186
|
+
}
|
|
187
|
+
return failure("unknown", fetchedAt, 0, "unsupported upstream - configure a balance parser");
|
|
188
|
+
}
|
|
189
|
+
function parseDeepSeek(payload, fetchedAt, cnyRate) {
|
|
190
|
+
const infos = Array.isArray(payload.balance_infos) ? payload.balance_infos : [];
|
|
191
|
+
const first = objectValue(infos[0]);
|
|
192
|
+
const currency = currencyValue(first?.currency) || "CNY";
|
|
193
|
+
const rawAmount = numberFrom(first?.total_balance);
|
|
194
|
+
if (payload.is_available === false) {
|
|
195
|
+
return {
|
|
196
|
+
...amountSnapshot(rawAmount, currency, "deepseek", fetchedAt, cnyRate),
|
|
197
|
+
error: { httpStatus: 200, message: "Insufficient balance" }
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
if (!first) {
|
|
201
|
+
return amountSnapshot(null, currency, "deepseek", fetchedAt, cnyRate);
|
|
202
|
+
}
|
|
203
|
+
if (rawAmount === null) {
|
|
204
|
+
return failure("deepseek", fetchedAt, 200, "missing field: balance_infos[].total_balance", currency);
|
|
205
|
+
}
|
|
206
|
+
return amountSnapshot(rawAmount, currency, "deepseek", fetchedAt, cnyRate);
|
|
207
|
+
}
|
|
208
|
+
function parseSiliconFlow(payload, currency, fetchedAt, cnyRate) {
|
|
209
|
+
const code = numberFrom(payload.code);
|
|
210
|
+
if (code !== null && code !== 20000) {
|
|
211
|
+
return failure("siliconflow", fetchedAt, 200, `upstream code: ${code}`, currency);
|
|
212
|
+
}
|
|
213
|
+
const data = objectValue(payload.data);
|
|
214
|
+
if (!data) {
|
|
215
|
+
return failure("siliconflow", fetchedAt, 200, "missing field: data", currency);
|
|
216
|
+
}
|
|
217
|
+
const snapshot = amountSnapshot(numberFrom(data.totalBalance), currency, "siliconflow", fetchedAt, cnyRate);
|
|
218
|
+
const status = stringValue(data.status);
|
|
219
|
+
if (status && status !== "ok") {
|
|
220
|
+
return {
|
|
221
|
+
...snapshot,
|
|
222
|
+
error: { httpStatus: 200, message: `upstream status: ${status}` }
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
return snapshot;
|
|
226
|
+
}
|
|
227
|
+
function parseOpenRouter(payload, fetchedAt, cnyRate) {
|
|
228
|
+
const data = objectValue(payload.data) || payload;
|
|
229
|
+
const totalCredits = numberFrom(data.total_credits);
|
|
230
|
+
const totalUsage = numberFrom(data.total_usage);
|
|
231
|
+
if (totalCredits === null || totalUsage === null) {
|
|
232
|
+
return failure("openrouter", fetchedAt, 200, "missing field: data.total_credits or data.total_usage", "USD");
|
|
233
|
+
}
|
|
234
|
+
return amountSnapshot(Math.max(0, totalCredits - totalUsage), "USD", "openrouter", fetchedAt, cnyRate);
|
|
235
|
+
}
|
|
236
|
+
function parseNewApi(payload, fetchedAt, cnyRate) {
|
|
237
|
+
const data = objectValue(payload.data);
|
|
238
|
+
if (!data) {
|
|
239
|
+
return failure("newapi_generic", fetchedAt, 200, "missing field: data", "USD");
|
|
240
|
+
}
|
|
241
|
+
const quota = numberFrom(data.quota);
|
|
242
|
+
const usedQuota = numberFrom(data.used_quota);
|
|
243
|
+
if (quota === null || usedQuota === null) {
|
|
244
|
+
return failure("newapi_generic", fetchedAt, 200, "missing field: data.quota or data.used_quota", "USD");
|
|
245
|
+
}
|
|
246
|
+
return amountSnapshot((quota - usedQuota) / 500000, "USD", "newapi_generic", fetchedAt, cnyRate);
|
|
247
|
+
}
|
|
248
|
+
function parseUsageGeneric(payload, fetchedAt, cnyRate) {
|
|
249
|
+
const quota = objectValue(payload.quota);
|
|
250
|
+
const rawAmount = numberFrom(payload.remaining) ?? numberFrom(quota?.remaining) ?? numberFrom(payload.balance);
|
|
251
|
+
const currency = currencyValue(payload.unit) || currencyValue(quota?.unit) || "USD";
|
|
252
|
+
if (rawAmount === null) {
|
|
253
|
+
return failure("usage_generic", fetchedAt, 200, "missing field: remaining, quota.remaining, or balance", currency);
|
|
254
|
+
}
|
|
255
|
+
const snapshot = amountSnapshot(rawAmount, currency, "usage_generic", fetchedAt, cnyRate);
|
|
256
|
+
const isValid = booleanValue(payload.is_active) ?? booleanValue(payload.isValid) ?? true;
|
|
257
|
+
if (!isValid) {
|
|
258
|
+
return {
|
|
259
|
+
...snapshot,
|
|
260
|
+
error: { httpStatus: 200, message: "upstream key is not active" }
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
return snapshot;
|
|
264
|
+
}
|
|
265
|
+
function amountSnapshot(rawAmount, currency, source, fetchedAt, cnyRate) {
|
|
266
|
+
return {
|
|
267
|
+
rawAmount,
|
|
268
|
+
amountUsdMicros: rawAmount === null ? null : Math.round(rawAmount * (currency === "CNY" ? cnyRate : 1) * 1000000),
|
|
269
|
+
currency,
|
|
270
|
+
source,
|
|
271
|
+
fetchedAt
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
function failure(source, fetchedAt, httpStatus, message, currency = null) {
|
|
275
|
+
return {
|
|
276
|
+
rawAmount: null,
|
|
277
|
+
amountUsdMicros: null,
|
|
278
|
+
currency,
|
|
279
|
+
source,
|
|
280
|
+
fetchedAt,
|
|
281
|
+
error: { httpStatus, message }
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function httpErrorMessage(status) {
|
|
285
|
+
if (status === 401) {
|
|
286
|
+
return "unauthorized: check upstreamApiKey";
|
|
287
|
+
}
|
|
288
|
+
if (status === 403) {
|
|
289
|
+
return "forbidden: upstream rejected the credentials";
|
|
290
|
+
}
|
|
291
|
+
if (status === 429) {
|
|
292
|
+
return "rate limited";
|
|
293
|
+
}
|
|
294
|
+
if (status >= 500) {
|
|
295
|
+
return "upstream 5xx";
|
|
296
|
+
}
|
|
297
|
+
return `upstream http ${status}`;
|
|
298
|
+
}
|
|
299
|
+
function cnyUsdRate(value) {
|
|
300
|
+
if (value !== undefined && Number.isFinite(value) && value > 0) {
|
|
301
|
+
return value;
|
|
302
|
+
}
|
|
303
|
+
const envValue = Number(process.env.TB_CNY_USD_RATE);
|
|
304
|
+
return Number.isFinite(envValue) && envValue > 0 ? envValue : DEFAULT_CNY_USD_RATE;
|
|
305
|
+
}
|
|
306
|
+
function cacheKey(config) {
|
|
307
|
+
return [
|
|
308
|
+
stringValue(config.upstreamBalanceProbe?.template),
|
|
309
|
+
stringValue(config.upstreamBalanceProbe?.url),
|
|
310
|
+
stringValue(config.upstreamBalanceProbe?.userId),
|
|
311
|
+
stringValue(config.upstreamBalanceUrl),
|
|
312
|
+
stringValue(config.upstreamUrl),
|
|
313
|
+
stringValue(config.upstreamApiKey),
|
|
314
|
+
stringValue(config.upstreamUserId)
|
|
315
|
+
].join("|");
|
|
316
|
+
}
|
|
317
|
+
function balanceProbeTemplateValue(value) {
|
|
318
|
+
return value === "auto" ||
|
|
319
|
+
value === "deepseek" ||
|
|
320
|
+
value === "stepfun" ||
|
|
321
|
+
value === "siliconflow" ||
|
|
322
|
+
value === "openrouter" ||
|
|
323
|
+
value === "novita" ||
|
|
324
|
+
value === "newapi_generic" ||
|
|
325
|
+
value === "usage_generic" ||
|
|
326
|
+
value === "none"
|
|
327
|
+
? value
|
|
328
|
+
: undefined;
|
|
329
|
+
}
|
|
330
|
+
function hostName(value) {
|
|
331
|
+
if (!value) {
|
|
332
|
+
return "";
|
|
333
|
+
}
|
|
334
|
+
try {
|
|
335
|
+
return new URL(value).hostname.replace(/^www\./, "");
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
return "";
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
function usageUrl(value) {
|
|
342
|
+
try {
|
|
343
|
+
const url = new URL(value);
|
|
344
|
+
url.pathname = "/v1/usage";
|
|
345
|
+
url.search = "";
|
|
346
|
+
url.hash = "";
|
|
347
|
+
return url.toString();
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
return undefined;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function isUsageEndpoint(value) {
|
|
354
|
+
try {
|
|
355
|
+
return new URL(value).pathname.replace(/\/+$/, "") === "/v1/usage";
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
function objectValue(value) {
|
|
362
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
363
|
+
? value
|
|
364
|
+
: undefined;
|
|
365
|
+
}
|
|
366
|
+
function stringValue(value) {
|
|
367
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
368
|
+
}
|
|
369
|
+
function numberFrom(value) {
|
|
370
|
+
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN;
|
|
371
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
372
|
+
}
|
|
373
|
+
function booleanValue(value) {
|
|
374
|
+
return typeof value === "boolean" ? value : undefined;
|
|
375
|
+
}
|
|
376
|
+
function currencyValue(value) {
|
|
377
|
+
return value === "USD" || value === "CNY" ? value : undefined;
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=upstream-balance-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upstream-balance-probe.js","sourceRoot":"","sources":["../../src/upstream-balance-probe.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Command } from "commander";
|
|
|
2
2
|
import { ConfigManager } from "./config.js";
|
|
3
3
|
import { AdminClient } from "./client.js";
|
|
4
4
|
import { FlyProvider } from "./server-cmd.js";
|
|
5
|
+
import { bindAdminUiCommand } from "./ui-command.js";
|
|
5
6
|
import {
|
|
6
7
|
loadRegistryFile,
|
|
7
8
|
SellerRegistryDocument,
|
|
@@ -142,6 +143,13 @@ function loadYamlOrJsonFile(filePath: string): any {
|
|
|
142
143
|
return YAML.load(fs.readFileSync(filePath, "utf8"));
|
|
143
144
|
}
|
|
144
145
|
|
|
146
|
+
function requireUpstreamModels(data: any): any[] {
|
|
147
|
+
if (!Array.isArray(data?.models)) {
|
|
148
|
+
throw new Error("operator upstream summary must contain top-level models array");
|
|
149
|
+
}
|
|
150
|
+
return data.models;
|
|
151
|
+
}
|
|
152
|
+
|
|
145
153
|
/**
|
|
146
154
|
* 构造 admin commander program,绑定所有 `tb-admin` 子命令(profile / registry / seller / config / backup 等)。
|
|
147
155
|
* 顶层选项支持 `--url` / `--token` / `--profile` / `--config`,与 `ConfigManager` 协同解析。
|
|
@@ -160,6 +168,8 @@ export function buildAdminCli(configManager: ConfigManager): Command {
|
|
|
160
168
|
.option("--profile <profile>", "Use custom profile instead of default")
|
|
161
169
|
.option("--config <path>", "Use custom config file path");
|
|
162
170
|
|
|
171
|
+
bindAdminUiCommand(program, configManager);
|
|
172
|
+
|
|
163
173
|
// Helper to resolve client
|
|
164
174
|
function getClient(): AdminClient {
|
|
165
175
|
const opts = program.opts();
|
|
@@ -350,26 +360,31 @@ export function buildAdminCli(configManager: ConfigManager): Command {
|
|
|
350
360
|
program
|
|
351
361
|
.command("models")
|
|
352
362
|
.description("List available upstream models")
|
|
353
|
-
.
|
|
363
|
+
.option("--json", "Print current upstream model summary as JSON")
|
|
364
|
+
.action(async (options) => {
|
|
354
365
|
try {
|
|
355
366
|
const client = getClient();
|
|
356
367
|
const data = await client.get("/operator/admin/upstreams");
|
|
368
|
+
const models = requireUpstreamModels(data);
|
|
369
|
+
if (options.json) {
|
|
370
|
+
console.log(JSON.stringify({ models }, null, 2));
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
357
373
|
const table = new Table({ head: ["Model ID", "Input Price/1M", "Output Price/1M", "Streaming"] });
|
|
358
374
|
|
|
359
|
-
for (const
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
]);
|
|
367
|
-
}
|
|
375
|
+
for (const model of models) {
|
|
376
|
+
table.push([
|
|
377
|
+
model.id,
|
|
378
|
+
`${model.inputPriceMicrosPer1m ?? "unknown"} micros`,
|
|
379
|
+
`${model.outputPriceMicrosPer1m ?? "unknown"} micros`,
|
|
380
|
+
model.streaming ? "Yes" : "No"
|
|
381
|
+
]);
|
|
368
382
|
}
|
|
369
383
|
console.log("=== Upstream Model Configurations ===");
|
|
370
384
|
console.log(table.toString());
|
|
371
385
|
} catch (err: any) {
|
|
372
386
|
console.error("Error:", err.message);
|
|
387
|
+
process.exit(1);
|
|
373
388
|
}
|
|
374
389
|
});
|
|
375
390
|
|
|
@@ -419,9 +434,6 @@ export function buildAdminCli(configManager: ConfigManager): Command {
|
|
|
419
434
|
console.log("Auto-refreshing upstream model catalog (upstream URL or key changed)...");
|
|
420
435
|
const refreshResp = await client.post("/operator/admin/upstreams/refresh", { autoModels: true });
|
|
421
436
|
console.log(` refreshed: ${refreshResp.refreshedModels ?? 0} models from upstream`);
|
|
422
|
-
if (refreshResp.upstreams && refreshResp.upstreams[0]?.error) {
|
|
423
|
-
throw new Error(`upstream refresh failed: ${refreshResp.upstreams[0].error}`);
|
|
424
|
-
}
|
|
425
437
|
}
|
|
426
438
|
|
|
427
439
|
const document = await getSellerConfig(client);
|
|
@@ -764,6 +776,7 @@ export function buildAdminCli(configManager: ConfigManager): Command {
|
|
|
764
776
|
console.log(out);
|
|
765
777
|
} catch (err: any) {
|
|
766
778
|
console.error("Error:", err.message);
|
|
779
|
+
process.exit(1);
|
|
767
780
|
}
|
|
768
781
|
});
|
|
769
782
|
|
|
@@ -778,6 +791,7 @@ export function buildAdminCli(configManager: ConfigManager): Command {
|
|
|
778
791
|
.option("--volume-size-gb <gb>", "Persistent volume size in GB", (v) => parseInt(v, 10))
|
|
779
792
|
.option("--volume-id <id>", "Attach existing volume by ID (skips volume creation)")
|
|
780
793
|
.option("--volume-snapshot-retention-days <days>", "Volume snapshot retention days", (v) => parseInt(v, 10))
|
|
794
|
+
.option("--initial-config <path>", "Initial seller YAML config to inject as TOKENBUDDY_SELLER_CONFIG_B64")
|
|
781
795
|
.requiredOption("--operator-secret <secret>", "Operator secret to configure")
|
|
782
796
|
.option("--dry-run", "Dry run display without actual execution")
|
|
783
797
|
.action((name, options) => {
|
|
@@ -792,32 +806,33 @@ export function buildAdminCli(configManager: ConfigManager): Command {
|
|
|
792
806
|
volumeSizeGb: options.volumeSizeGb,
|
|
793
807
|
volumeId: options.volumeId,
|
|
794
808
|
volumeSnapshotRetentionDays: options.volumeSnapshotRetentionDays,
|
|
809
|
+
initialConfigPath: options.initialConfig,
|
|
795
810
|
operatorSecret: options.operatorSecret,
|
|
796
811
|
dryRun: options.dryRun
|
|
797
812
|
});
|
|
798
813
|
console.log(res);
|
|
799
814
|
} catch (err: any) {
|
|
800
815
|
console.error("Error:", err.message);
|
|
816
|
+
process.exit(1);
|
|
801
817
|
}
|
|
802
818
|
});
|
|
803
819
|
|
|
804
820
|
sellerCmd
|
|
805
821
|
.command("deploy <app>")
|
|
806
|
-
.description("
|
|
807
|
-
.requiredOption("--fly-config <path>", "Fly.io config file path, for example deploy/fly.io/fly.tb-seller.toml")
|
|
822
|
+
.description("Update an existing seller app's Machines to an explicit image without changing Fly.io config or volumes")
|
|
808
823
|
.requiredOption("--image <image>", "Published Docker image, for example registry.fly.io/tb-seller:<v>")
|
|
809
824
|
.option("--dry-run", "Dry run")
|
|
810
825
|
.action((app, options) => {
|
|
811
826
|
try {
|
|
812
827
|
const res = flyProvider.deploySeller({
|
|
813
828
|
app,
|
|
814
|
-
config: options.flyConfig,
|
|
815
829
|
image: options.image,
|
|
816
830
|
dryRun: options.dryRun
|
|
817
831
|
});
|
|
818
832
|
console.log(res);
|
|
819
833
|
} catch (err: any) {
|
|
820
834
|
console.error("Error:", err.message);
|
|
835
|
+
process.exit(1);
|
|
821
836
|
}
|
|
822
837
|
});
|
|
823
838
|
|
|
@@ -849,6 +864,7 @@ export function buildAdminCli(configManager: ConfigManager): Command {
|
|
|
849
864
|
}
|
|
850
865
|
} catch (err: any) {
|
|
851
866
|
console.error("Error:", err.message);
|
|
867
|
+
process.exit(1);
|
|
852
868
|
}
|
|
853
869
|
});
|
|
854
870
|
|