@tokenbuddy/tokenbuddy 1.0.36 → 1.0.38
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/buyer-store.d.ts +7 -2
- package/dist/src/buyer-store.js +46 -7
- package/dist/src/cli.d.ts +1 -0
- package/dist/src/cli.js +15 -7
- package/dist/src/daemon.d.ts +12 -0
- package/dist/src/daemon.js +791 -61
- package/dist/src/doctor-diagnostics.js +1 -6
- package/dist/src/provider-install.d.ts +2 -2
- package/dist/src/provider-install.js +248 -2
- package/dist/src/seller-catalog.d.ts +21 -0
- package/dist/src/seller-catalog.js +17 -0
- package/dist/src/seller-route-planner.d.ts +4 -1
- package/dist/src/seller-route-planner.js +3 -0
- package/dist/src/seller-routing-strategy.d.ts +3 -0
- package/dist/src/terminal-detect.d.ts +1 -1
- package/dist/src/terminal-detect.js +3 -2
- package/dist/src/workdir.d.ts +10 -0
- package/dist/src/workdir.js +26 -0
- package/package.json +15 -2
- package/static/ui/assets/index-Djfl9tw5.js +271 -0
- package/static/ui/assets/index-DkfztCkn.css +1 -0
- package/static/ui/index.html +2 -2
- package/dist/src/buyer-store.d.ts.map +0 -1
- package/dist/src/buyer-store.js.map +0 -1
- package/dist/src/clawtip-bootstrap.d.ts.map +0 -1
- package/dist/src/clawtip-bootstrap.js.map +0 -1
- package/dist/src/cli.d.ts.map +0 -1
- package/dist/src/cli.js.map +0 -1
- package/dist/src/credit-tracker.d.ts.map +0 -1
- package/dist/src/credit-tracker.js.map +0 -1
- package/dist/src/daemon.d.ts.map +0 -1
- package/dist/src/daemon.js.map +0 -1
- package/dist/src/doctor-clawtip-wallet.d.ts.map +0 -1
- package/dist/src/doctor-clawtip-wallet.js.map +0 -1
- package/dist/src/doctor-diagnostics.d.ts.map +0 -1
- package/dist/src/doctor-diagnostics.js.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/init-clawtip-activation.d.ts.map +0 -1
- package/dist/src/init-clawtip-activation.js.map +0 -1
- package/dist/src/init-payment-options.d.ts.map +0 -1
- package/dist/src/init-payment-options.js.map +0 -1
- package/dist/src/init-setup.d.ts.map +0 -1
- package/dist/src/init-setup.js.map +0 -1
- package/dist/src/model-index.d.ts.map +0 -1
- package/dist/src/model-index.js.map +0 -1
- package/dist/src/package-update.d.ts.map +0 -1
- package/dist/src/package-update.js.map +0 -1
- package/dist/src/prewarm-cache.d.ts.map +0 -1
- package/dist/src/prewarm-cache.js.map +0 -1
- package/dist/src/prewarm-scheduler.d.ts.map +0 -1
- package/dist/src/prewarm-scheduler.js.map +0 -1
- package/dist/src/provider-install.d.ts.map +0 -1
- package/dist/src/provider-install.js.map +0 -1
- package/dist/src/provider-routing-config.d.ts.map +0 -1
- package/dist/src/provider-routing-config.js.map +0 -1
- package/dist/src/registry-trust.d.ts.map +0 -1
- package/dist/src/registry-trust.js.map +0 -1
- package/dist/src/route-failover.d.ts.map +0 -1
- package/dist/src/route-failover.js.map +0 -1
- package/dist/src/seller-catalog.d.ts.map +0 -1
- package/dist/src/seller-catalog.js.map +0 -1
- package/dist/src/seller-concurrency-limiter.d.ts.map +0 -1
- package/dist/src/seller-concurrency-limiter.js.map +0 -1
- package/dist/src/seller-metadata-cache.d.ts.map +0 -1
- package/dist/src/seller-metadata-cache.js.map +0 -1
- package/dist/src/seller-pool.d.ts.map +0 -1
- package/dist/src/seller-pool.js.map +0 -1
- package/dist/src/seller-route-planner.d.ts.map +0 -1
- package/dist/src/seller-route-planner.js.map +0 -1
- package/dist/src/seller-routing-config.d.ts.map +0 -1
- package/dist/src/seller-routing-config.js.map +0 -1
- package/dist/src/seller-routing-strategy.d.ts.map +0 -1
- package/dist/src/seller-routing-strategy.js.map +0 -1
- package/dist/src/stream-failover.d.ts.map +0 -1
- package/dist/src/stream-failover.js.map +0 -1
- package/dist/src/tb-clawtip-proof.d.ts.map +0 -1
- package/dist/src/tb-clawtip-proof.js.map +0 -1
- package/dist/src/tb-proxyd.d.ts.map +0 -1
- package/dist/src/tb-proxyd.js.map +0 -1
- package/dist/src/terminal-detect.d.ts.map +0 -1
- package/dist/src/terminal-detect.js.map +0 -1
- package/dist/src/terminal-image.d.ts.map +0 -1
- package/dist/src/terminal-image.js.map +0 -1
- package/src/buyer-store.ts +0 -1090
- package/src/clawtip-bootstrap.ts +0 -65
- package/src/cli.ts +0 -2243
- package/src/credit-tracker.ts +0 -295
- package/src/daemon.ts +0 -5475
- package/src/doctor-clawtip-wallet.ts +0 -95
- package/src/doctor-diagnostics.ts +0 -1026
- package/src/index.ts +0 -16
- package/src/init-clawtip-activation.ts +0 -695
- package/src/init-payment-options.ts +0 -373
- package/src/init-setup.ts +0 -165
- package/src/model-index.ts +0 -278
- package/src/package-update.ts +0 -311
- package/src/prewarm-cache.ts +0 -485
- package/src/prewarm-scheduler.ts +0 -675
- package/src/provider-install.ts +0 -1006
- package/src/provider-routing-config.ts +0 -410
- package/src/registry-trust.ts +0 -51
- package/src/route-failover.ts +0 -304
- package/src/seller-catalog.ts +0 -505
- package/src/seller-concurrency-limiter.ts +0 -161
- package/src/seller-metadata-cache.ts +0 -91
- package/src/seller-pool.ts +0 -557
- package/src/seller-route-planner.ts +0 -513
- package/src/seller-routing-config.ts +0 -211
- package/src/seller-routing-strategy.ts +0 -362
- package/src/stream-failover.ts +0 -152
- package/src/tb-clawtip-proof.ts +0 -28
- package/src/tb-proxyd.ts +0 -101
- package/src/terminal-detect.ts +0 -333
- package/src/terminal-image.ts +0 -228
- package/static/ui/assets/index-0MVXD7bH.css +0 -1
- package/static/ui/assets/index-BVbeDEwq.js +0 -271
- package/static/ui/assets/index-BVbeDEwq.js.map +0 -1
- package/tests/cli-routing.test.ts +0 -363
- package/tests/control-plane-ui-endpoints.test.ts +0 -1630
- package/tests/credit-tracker.test.ts +0 -165
- package/tests/daemon-413-fallback.test.ts +0 -92
- package/tests/daemon-classify.test.ts +0 -452
- package/tests/daemon-roles.test.ts +0 -92
- package/tests/daemon-trusted-registry-cache.test.ts +0 -132
- package/tests/e2e.test.ts +0 -366
- package/tests/image-generation-e2e.test.ts +0 -230
- package/tests/model-index.test.ts +0 -198
- package/tests/package-update.test.ts +0 -147
- package/tests/prewarm-cache.test.ts +0 -296
- package/tests/prewarm-scheduler.test.ts +0 -367
- package/tests/provider-routing-config.test.ts +0 -150
- package/tests/registry-trust.test.ts +0 -28
- package/tests/route-failover.test.ts +0 -222
- package/tests/seller-catalog-413.test.ts +0 -120
- package/tests/seller-catalog-utilities.test.ts +0 -124
- package/tests/seller-concurrency-limiter.test.ts +0 -83
- package/tests/seller-metadata-cache.test.ts +0 -89
- package/tests/seller-pool.test.ts +0 -365
- package/tests/seller-route-planner.test.ts +0 -312
- package/tests/seller-routing-config.test.ts +0 -124
- package/tests/seller-routing-strategy.test.ts +0 -167
- package/tests/stream-failover.test.ts +0 -52
- package/tests/thousand-seller.test.ts +0 -151
- package/tests/tokenbuddy.test.ts +0 -4043
- package/tsconfig.json +0 -8
|
@@ -80,13 +80,14 @@ export interface SafePurchaseLedgerEntry {
|
|
|
80
80
|
* buyer 端单次推理请求的账本输入。
|
|
81
81
|
* `prompt` / `response` 在落库前会 hash,原始内容永不落盘。
|
|
82
82
|
*
|
|
83
|
-
* v1.2 tb-ui v1 (Iter 4)
|
|
83
|
+
* v1.2 tb-ui v1 (Iter 4):补充排查 / 性能 / 路由决策溯源必备字段。
|
|
84
84
|
* - `ttftMs`:首字延迟(从请求发起到首 byte),`forwardProxyRequest` 计算
|
|
85
85
|
* - `fallbackCount`:本请求实际走过的 seller 数(> 1 即发生 failover)
|
|
86
86
|
* - `routeReason`:`planSellerRouteSet().reason`(如 `fullAuto:balanced:routes_3`)
|
|
87
87
|
* - `falloverChain`:failover 路径上 seller id 数组(空 = 主路径成功)
|
|
88
88
|
* - `upstreamStatus`:seller 透传的上游健康状态(`healthy|degraded|unhealthy|unknown`)
|
|
89
89
|
* - `durationMs`:总耗时(req start → response end 或失败)
|
|
90
|
+
* - `avgOutputTokensPerSecond`:请求级输出速度,按输出窗口统计,不由 UI 现场推导
|
|
90
91
|
* - `paymentMethod`:本请求使用的支付方式(`mock|clawtip`)
|
|
91
92
|
*/
|
|
92
93
|
export interface InferenceLedgerInput {
|
|
@@ -130,6 +131,7 @@ export interface InferenceLedgerInput {
|
|
|
130
131
|
falloverChain?: string[];
|
|
131
132
|
upstreamStatus?: string;
|
|
132
133
|
durationMs?: number;
|
|
134
|
+
avgOutputTokensPerSecond?: number;
|
|
133
135
|
paymentMethod?: string;
|
|
134
136
|
}
|
|
135
137
|
/**
|
|
@@ -178,6 +180,7 @@ export interface SafeInferenceLedgerEntry {
|
|
|
178
180
|
falloverChain?: string[];
|
|
179
181
|
upstreamStatus?: string;
|
|
180
182
|
durationMs?: number;
|
|
183
|
+
avgOutputTokensPerSecond?: number;
|
|
181
184
|
paymentMethod?: string;
|
|
182
185
|
}
|
|
183
186
|
/**
|
|
@@ -248,7 +251,7 @@ export interface BuyerStoreOptions {
|
|
|
248
251
|
}
|
|
249
252
|
/**
|
|
250
253
|
* 解析 buyer store 的 DB 路径。
|
|
251
|
-
* 优先级:`dbPath` → `TOKENBUDDY_BUYER_STORE` env → `~/.tokenbuddy
|
|
254
|
+
* 优先级:`dbPath` → `TOKENBUDDY_BUYER_STORE` env → `TB_WORKDIR` env → `~/.config/tokenbuddy/buyer-store.db`。
|
|
252
255
|
*
|
|
253
256
|
* @param options 解析选项
|
|
254
257
|
* @returns DB 文件绝对路径
|
|
@@ -292,6 +295,8 @@ export declare class BuyerStore {
|
|
|
292
295
|
listInferenceLedger(): SafeInferenceLedgerEntry[];
|
|
293
296
|
close(): void;
|
|
294
297
|
private initSchema;
|
|
298
|
+
private backfillPurchasePaymentAmountsFromPending;
|
|
299
|
+
private pendingPurchasePaymentSummary;
|
|
295
300
|
private ensureColumn;
|
|
296
301
|
private countRows;
|
|
297
302
|
/**
|
package/dist/src/buyer-store.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import { DatabaseSync } from "node:sqlite";
|
|
3
3
|
import * as crypto from "crypto";
|
|
4
4
|
import * as fs from "fs";
|
|
5
|
-
import * as os from "os";
|
|
6
5
|
import * as path from "path";
|
|
7
6
|
import { createModuleLogger } from "@tokenbuddy/logging";
|
|
7
|
+
import { resolveTokenBuddyWorkdir } from "./workdir.js";
|
|
8
8
|
const logger = createModuleLogger("tb-proxyd");
|
|
9
9
|
function nowIso() {
|
|
10
10
|
return new Date().toISOString();
|
|
@@ -26,7 +26,7 @@ function ensureDirForFile(filePath) {
|
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
28
|
* 解析 buyer store 的 DB 路径。
|
|
29
|
-
* 优先级:`dbPath` → `TOKENBUDDY_BUYER_STORE` env → `~/.tokenbuddy
|
|
29
|
+
* 优先级:`dbPath` → `TOKENBUDDY_BUYER_STORE` env → `TB_WORKDIR` env → `~/.config/tokenbuddy/buyer-store.db`。
|
|
30
30
|
*
|
|
31
31
|
* @param options 解析选项
|
|
32
32
|
* @returns DB 文件绝对路径
|
|
@@ -35,7 +35,7 @@ export function resolveBuyerStorePath(options = {}) {
|
|
|
35
35
|
if (options.dbPath) {
|
|
36
36
|
return options.dbPath;
|
|
37
37
|
}
|
|
38
|
-
const root = options.root || process.env.TOKENBUDDY_BUYER_STORE ||
|
|
38
|
+
const root = options.root || process.env.TOKENBUDDY_BUYER_STORE || resolveTokenBuddyWorkdir();
|
|
39
39
|
return path.join(root, "buyer-store.db");
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
@@ -251,11 +251,12 @@ export class BuyerStore {
|
|
|
251
251
|
}
|
|
252
252
|
recordPurchaseLedger(input) {
|
|
253
253
|
const createdAt = nowIso();
|
|
254
|
+
const pendingPayment = this.pendingPurchasePaymentSummary(input.purchaseId);
|
|
254
255
|
this.db.prepare(`INSERT INTO purchase_ledger (
|
|
255
256
|
purchase_id, seller_key, model_id, payment_method, status, credit_micros,
|
|
256
257
|
currency, payment_amount, payment_amount_minor, payment_currency,
|
|
257
258
|
payment_reference_hash, created_at, completed_at
|
|
258
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.purchaseId, input.sellerKey, input.modelId, input.paymentMethod, input.status, input.creditMicros, input.currency, input.paymentAmount ?? null, input.paymentAmountMinor ?? null, input.paymentCurrency ?? null, safeHash(input.paymentReference) || null, createdAt, input.completedAt || null);
|
|
259
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.purchaseId, input.sellerKey, input.modelId, input.paymentMethod, input.status, input.creditMicros, input.currency, input.paymentAmount ?? pendingPayment?.paymentAmount ?? null, input.paymentAmountMinor ?? pendingPayment?.paymentAmountMinor ?? null, input.paymentCurrency ?? pendingPayment?.paymentCurrency ?? null, safeHash(input.paymentReference) || null, createdAt, input.completedAt || null);
|
|
259
260
|
}
|
|
260
261
|
listPurchaseLedger() {
|
|
261
262
|
const rows = this.db.prepare(`SELECT purchase_id, seller_key, model_id, payment_method, status, credit_micros,
|
|
@@ -292,8 +293,8 @@ export class BuyerStore {
|
|
|
292
293
|
balance_snapshot_micros, balance_source,
|
|
293
294
|
prompt_hash, response_hash, created_at,
|
|
294
295
|
ttft_ms, fallback_count, route_reason, fallover_chain_json, upstream_status,
|
|
295
|
-
duration_ms, payment_method
|
|
296
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.requestId, input.sellerKey, input.modelId, input.endpoint, input.status, input.promptTokens, input.completionTokens, input.cacheReadTokens ?? 0, input.billedMicros, input.estimatedMicros ?? input.billedMicros, input.settledMicros ?? null, input.settledUsdMicros ?? null, input.priceVersion || null, input.inputPriceMicrosPer1m ?? null, input.outputPriceMicrosPer1m ?? null, input.cacheReadPriceMicrosPer1m ?? null, input.inputCostMicros ?? null, input.outputCostMicros ?? null, input.cacheReadCostMicros ?? null, input.originalUsdMicros ?? null, input.billingMultiplier ?? null, input.serviceTier ?? null, input.billingUnit ?? (input.endpoint === "/v1/images/generations" ? "images" : "tokens"), input.imageCount ?? null, input.imageSize ?? null, input.imageQuality ?? null, input.imageOutputFormat ?? null, input.imageOutputTokens ?? null, input.imageOutputCostMicros ?? null, input.imageCostMicrosPerImage ?? null, input.balanceSnapshotMicros ?? null, input.balanceSource || "unknown", safeHash(input.prompt) || null, safeHash(input.response) || null, nowIso(), input.ttftMs ?? null, input.fallbackCount ?? null, input.routeReason ?? null, input.falloverChain ? JSON.stringify(input.falloverChain) : null, input.upstreamStatus ?? null, input.durationMs ?? null, input.paymentMethod ?? null);
|
|
296
|
+
duration_ms, avg_output_tokens_per_second, payment_method
|
|
297
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.requestId, input.sellerKey, input.modelId, input.endpoint, input.status, input.promptTokens, input.completionTokens, input.cacheReadTokens ?? 0, input.billedMicros, input.estimatedMicros ?? input.billedMicros, input.settledMicros ?? null, input.settledUsdMicros ?? null, input.priceVersion || null, input.inputPriceMicrosPer1m ?? null, input.outputPriceMicrosPer1m ?? null, input.cacheReadPriceMicrosPer1m ?? null, input.inputCostMicros ?? null, input.outputCostMicros ?? null, input.cacheReadCostMicros ?? null, input.originalUsdMicros ?? null, input.billingMultiplier ?? null, input.serviceTier ?? null, input.billingUnit ?? (input.endpoint === "/v1/images/generations" ? "images" : "tokens"), input.imageCount ?? null, input.imageSize ?? null, input.imageQuality ?? null, input.imageOutputFormat ?? null, input.imageOutputTokens ?? null, input.imageOutputCostMicros ?? null, input.imageCostMicrosPerImage ?? null, input.balanceSnapshotMicros ?? null, input.balanceSource || "unknown", safeHash(input.prompt) || null, safeHash(input.response) || null, nowIso(), input.ttftMs ?? null, input.fallbackCount ?? null, input.routeReason ?? null, input.falloverChain ? JSON.stringify(input.falloverChain) : null, input.upstreamStatus ?? null, input.durationMs ?? null, input.avgOutputTokensPerSecond ?? null, input.paymentMethod ?? null);
|
|
297
298
|
}
|
|
298
299
|
listInferenceLedger() {
|
|
299
300
|
const rows = this.db.prepare(`SELECT request_id, seller_key, model_id, endpoint, status, prompt_tokens,
|
|
@@ -307,7 +308,7 @@ export class BuyerStore {
|
|
|
307
308
|
balance_snapshot_micros, balance_source,
|
|
308
309
|
prompt_hash, response_hash, created_at,
|
|
309
310
|
ttft_ms, fallback_count, route_reason, fallover_chain_json, upstream_status,
|
|
310
|
-
duration_ms, payment_method
|
|
311
|
+
duration_ms, avg_output_tokens_per_second, payment_method
|
|
311
312
|
FROM inference_ledger
|
|
312
313
|
ORDER BY id ASC`).all();
|
|
313
314
|
return rows.map(row => ({
|
|
@@ -352,6 +353,7 @@ export class BuyerStore {
|
|
|
352
353
|
falloverChain: row.fallover_chain_json ? JSON.parse(row.fallover_chain_json) : undefined,
|
|
353
354
|
upstreamStatus: row.upstream_status ?? undefined,
|
|
354
355
|
durationMs: row.duration_ms ?? undefined,
|
|
356
|
+
avgOutputTokensPerSecond: row.avg_output_tokens_per_second ?? undefined,
|
|
355
357
|
paymentMethod: row.payment_method ?? undefined
|
|
356
358
|
}));
|
|
357
359
|
}
|
|
@@ -454,6 +456,7 @@ export class BuyerStore {
|
|
|
454
456
|
fallover_chain_json TEXT,
|
|
455
457
|
upstream_status TEXT,
|
|
456
458
|
duration_ms INTEGER,
|
|
459
|
+
avg_output_tokens_per_second REAL,
|
|
457
460
|
payment_method TEXT
|
|
458
461
|
);
|
|
459
462
|
|
|
@@ -523,10 +526,46 @@ export class BuyerStore {
|
|
|
523
526
|
["fallover_chain_json", "TEXT"],
|
|
524
527
|
["upstream_status", "TEXT"],
|
|
525
528
|
["duration_ms", "INTEGER"],
|
|
529
|
+
["avg_output_tokens_per_second", "REAL"],
|
|
526
530
|
["payment_method", "TEXT"]
|
|
527
531
|
]) {
|
|
528
532
|
this.ensureColumn("inference_ledger", column, definition);
|
|
529
533
|
}
|
|
534
|
+
this.backfillPurchasePaymentAmountsFromPending();
|
|
535
|
+
}
|
|
536
|
+
backfillPurchasePaymentAmountsFromPending() {
|
|
537
|
+
this.db.prepare(`UPDATE purchase_ledger
|
|
538
|
+
SET payment_amount = (
|
|
539
|
+
SELECT printf('%.4f', pending_purchases.amount_usd_micros / 1000000.0)
|
|
540
|
+
FROM pending_purchases
|
|
541
|
+
WHERE pending_purchases.purchase_id = purchase_ledger.purchase_id
|
|
542
|
+
),
|
|
543
|
+
payment_amount_minor = (
|
|
544
|
+
SELECT CAST(ROUND(pending_purchases.amount_usd_micros / 10000.0) AS INTEGER)
|
|
545
|
+
FROM pending_purchases
|
|
546
|
+
WHERE pending_purchases.purchase_id = purchase_ledger.purchase_id
|
|
547
|
+
),
|
|
548
|
+
payment_currency = 'USD'
|
|
549
|
+
WHERE (payment_amount IS NULL OR payment_amount = '' OR payment_amount_minor IS NULL OR payment_currency IS NULL OR payment_currency = '')
|
|
550
|
+
AND EXISTS (
|
|
551
|
+
SELECT 1
|
|
552
|
+
FROM pending_purchases
|
|
553
|
+
WHERE pending_purchases.purchase_id = purchase_ledger.purchase_id
|
|
554
|
+
AND pending_purchases.amount_usd_micros >= 0
|
|
555
|
+
)`).run();
|
|
556
|
+
}
|
|
557
|
+
pendingPurchasePaymentSummary(purchaseId) {
|
|
558
|
+
const row = this.db.prepare(`SELECT amount_usd_micros
|
|
559
|
+
FROM pending_purchases
|
|
560
|
+
WHERE purchase_id = ?`).get(purchaseId);
|
|
561
|
+
if (!row || !Number.isFinite(row.amount_usd_micros) || row.amount_usd_micros < 0) {
|
|
562
|
+
return undefined;
|
|
563
|
+
}
|
|
564
|
+
return {
|
|
565
|
+
paymentAmount: (row.amount_usd_micros / 1_000_000).toFixed(4),
|
|
566
|
+
paymentAmountMinor: Math.round(row.amount_usd_micros / 10_000),
|
|
567
|
+
paymentCurrency: "USD"
|
|
568
|
+
};
|
|
530
569
|
}
|
|
531
570
|
ensureColumn(table, column, definition) {
|
|
532
571
|
const rows = this.db.prepare(`PRAGMA table_info(${table})`).all();
|
package/dist/src/cli.d.ts
CHANGED
package/dist/src/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import * as os from "os";
|
|
|
6
6
|
import { execFileSync, spawn } from "child_process";
|
|
7
7
|
import Table from "cli-table3";
|
|
8
8
|
import { BuyerStore } from "./buyer-store.js";
|
|
9
|
-
import { applyProviderInstall, detectProviders, getProviderModelSelectionKind, getProviderProtocolPreference, } from "./provider-install.js";
|
|
9
|
+
import { applyProviderInstall, detectProviders, getProviderModelSelectionKind, getProviderProtocolPreference, PROXY_ACCESS_TOKEN_PLACEHOLDER, } from "./provider-install.js";
|
|
10
10
|
import { createModuleLogger } from "@tokenbuddy/logging";
|
|
11
11
|
import * as crypto from "crypto";
|
|
12
12
|
import { fileURLToPath } from "url";
|
|
@@ -19,6 +19,7 @@ import { DEFAULT_CLAWTIP_BOOTSTRAP_URL, fetchClawtipBootstrap, } from "./clawtip
|
|
|
19
19
|
import { displayTerminalImage } from "./terminal-image.js";
|
|
20
20
|
import { checkPackageUpdate, readInstalledPackageManifest, runPackageUpdate, } from "./package-update.js";
|
|
21
21
|
import { DEFAULT_SELLER_REGISTRY_URL } from "./registry-trust.js";
|
|
22
|
+
import { resolveTokenBuddyWorkdir, resolveTokenBuddyWorkdirPath, TB_WORKDIR_ENV } from "./workdir.js";
|
|
22
23
|
// @ts-ignore
|
|
23
24
|
import qrcode from "qrcode-terminal";
|
|
24
25
|
const CONTROL_PORT = 17820;
|
|
@@ -119,7 +120,7 @@ function launchControlUi(controlPort, pathname = "/") {
|
|
|
119
120
|
return url;
|
|
120
121
|
}
|
|
121
122
|
function defaultProxydLogPath(kind) {
|
|
122
|
-
const logDir =
|
|
123
|
+
const logDir = resolveTokenBuddyWorkdir();
|
|
123
124
|
fs.mkdirSync(logDir, { recursive: true });
|
|
124
125
|
return path.join(logDir, `tb-proxyd.${kind}.log`);
|
|
125
126
|
}
|
|
@@ -164,6 +165,9 @@ export function buildLaunchdPlistContent(options) {
|
|
|
164
165
|
if (options.clawtipProofCommand?.trim()) {
|
|
165
166
|
env.TB_PROXYD_CLAWTIP_PROOF_COMMAND = options.clawtipProofCommand.trim();
|
|
166
167
|
}
|
|
168
|
+
if (options.workdir?.trim()) {
|
|
169
|
+
env[TB_WORKDIR_ENV] = options.workdir.trim();
|
|
170
|
+
}
|
|
167
171
|
if (options.clawtipProofTimeoutMs !== undefined) {
|
|
168
172
|
env.TB_PROXYD_CLAWTIP_PROOF_TIMEOUT_MS = String(options.clawtipProofTimeoutMs);
|
|
169
173
|
}
|
|
@@ -383,8 +387,9 @@ export async function runWebInitLauncher(deps = {}) {
|
|
|
383
387
|
if (platform === "darwin") {
|
|
384
388
|
const plistDir = path.join(home, "Library", "LaunchAgents");
|
|
385
389
|
const plistPath = path.join(plistDir, `${TOKENBUDDY_LAUNCHD_LABEL}.plist`);
|
|
386
|
-
const
|
|
387
|
-
const
|
|
390
|
+
const workdir = resolveTokenBuddyWorkdir({ homeDir: home });
|
|
391
|
+
const stdoutPath = deps.stdoutPath ?? resolveTokenBuddyWorkdirPath("tb-proxyd.stdout.log", { homeDir: home });
|
|
392
|
+
const stderrPath = deps.stderrPath ?? resolveTokenBuddyWorkdirPath("tb-proxyd.stderr.log", { homeDir: home });
|
|
388
393
|
try {
|
|
389
394
|
(deps.mkdirSync ?? fs.mkdirSync)(plistDir, { recursive: true });
|
|
390
395
|
(deps.mkdirSync ?? fs.mkdirSync)(path.dirname(stdoutPath), { recursive: true });
|
|
@@ -394,6 +399,7 @@ export async function runWebInitLauncher(deps = {}) {
|
|
|
394
399
|
nodePath: deps.nodePath ?? process.execPath,
|
|
395
400
|
scriptPath: deps.scriptPath ?? tbProxydScriptPath(),
|
|
396
401
|
pathEnv: deps.pathEnv,
|
|
402
|
+
workdir,
|
|
397
403
|
stdoutPath,
|
|
398
404
|
stderrPath,
|
|
399
405
|
controlPort,
|
|
@@ -1511,7 +1517,7 @@ export function buildCli() {
|
|
|
1511
1517
|
"✅ OpenAI-compatible Proxy",
|
|
1512
1518
|
" URL: http://127.0.0.1:17821/v1",
|
|
1513
1519
|
" Probe: http://127.0.0.1:17821/v1/models",
|
|
1514
|
-
|
|
1520
|
+
` Token: ${PROXY_ACCESS_TOKEN_PLACEHOLDER}`,
|
|
1515
1521
|
"",
|
|
1516
1522
|
"✅ Anthropic-compatible Proxy",
|
|
1517
1523
|
" URL: http://127.0.0.1:17821"
|
|
@@ -1799,8 +1805,9 @@ export function buildCli() {
|
|
|
1799
1805
|
const sellerRegistryUrl = sellerRegistryUrlForInit();
|
|
1800
1806
|
const nodePath = process.execPath;
|
|
1801
1807
|
const scriptPath = tbProxydScriptPath();
|
|
1802
|
-
const
|
|
1803
|
-
const
|
|
1808
|
+
const workdir = resolveTokenBuddyWorkdir({ homeDir: home });
|
|
1809
|
+
const stdoutPath = resolveTokenBuddyWorkdirPath("tb-proxyd.stdout.log", { homeDir: home });
|
|
1810
|
+
const stderrPath = resolveTokenBuddyWorkdirPath("tb-proxyd.stderr.log", { homeDir: home });
|
|
1804
1811
|
fs.mkdirSync(path.dirname(stdoutPath), { recursive: true });
|
|
1805
1812
|
fs.mkdirSync(path.dirname(stderrPath), { recursive: true });
|
|
1806
1813
|
const plistContent = buildLaunchdPlistContent({
|
|
@@ -1813,6 +1820,7 @@ export function buildCli() {
|
|
|
1813
1820
|
proxyPort,
|
|
1814
1821
|
sellerRegistryUrl,
|
|
1815
1822
|
pathEnv: process.env.PATH,
|
|
1823
|
+
workdir,
|
|
1816
1824
|
clawtipProofCommand: defaultClawtipProofCommand(),
|
|
1817
1825
|
clawtipProofTimeoutMs: process.env.TB_PROXYD_CLAWTIP_PROOF_TIMEOUT_MS
|
|
1818
1826
|
? Number(process.env.TB_PROXYD_CLAWTIP_PROOF_TIMEOUT_MS)
|
package/dist/src/daemon.d.ts
CHANGED
|
@@ -142,6 +142,7 @@ export declare class TokenbuddyDaemon {
|
|
|
142
142
|
private resolveClaudeRoleModel;
|
|
143
143
|
private resolveRouteModelId;
|
|
144
144
|
private applyResolvedModelToBody;
|
|
145
|
+
private withOpenAiStreamUsage;
|
|
145
146
|
private defaultPaymentMethod;
|
|
146
147
|
private selectManualProviderRoutes;
|
|
147
148
|
private selectSellerRoutes;
|
|
@@ -173,7 +174,11 @@ export declare class TokenbuddyDaemon {
|
|
|
173
174
|
private sellerCatalogWithRuntimeMetrics;
|
|
174
175
|
private refreshSellerRouteMetadata;
|
|
175
176
|
private routeMetricFromPoolEntry;
|
|
177
|
+
private routeStateFromPoolEntry;
|
|
178
|
+
private routeStateFromCatalogStatus;
|
|
176
179
|
private readUsage;
|
|
180
|
+
private usageSummaryFromData;
|
|
181
|
+
private readUsageFromSse;
|
|
177
182
|
private parseSellerSettlementSummary;
|
|
178
183
|
private recordReconciledInference;
|
|
179
184
|
private refreshSellerBalance;
|
|
@@ -190,6 +195,7 @@ export declare class TokenbuddyDaemon {
|
|
|
190
195
|
* `TB_PROXYD_REQUEST_DEADLINE_MS` (default 180s).
|
|
191
196
|
*/
|
|
192
197
|
private requestDeadlineMs;
|
|
198
|
+
private userInferenceTestTimeoutMs;
|
|
193
199
|
/**
|
|
194
200
|
* Safety margin subtracted from the cached token's `expiresAt` before
|
|
195
201
|
* deciding to reuse it. Buying a new token 60s before expiry gives the
|
|
@@ -206,6 +212,12 @@ export declare class TokenbuddyDaemon {
|
|
|
206
212
|
private manualProviderEndpointUrl;
|
|
207
213
|
private manualProviderEndpointUrlFromBase;
|
|
208
214
|
private probeManualProviderModels;
|
|
215
|
+
private probeManualProviderProtocols;
|
|
216
|
+
private probeManualProviderProtocol;
|
|
217
|
+
private probeManualProviderProtocolModel;
|
|
218
|
+
private testManualProviderInference;
|
|
219
|
+
private testSellerInference;
|
|
220
|
+
private recordManualProviderProbeResult;
|
|
209
221
|
private manualProviderErrorClass;
|
|
210
222
|
private shouldFailoverManualProvider;
|
|
211
223
|
private fetchManualProviderRoute;
|