tokenmix 0.4.7 → 0.4.8
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/README.md +9 -0
- package/dist/commands/models.js +14 -1
- package/dist/i18n/messages.js +6 -0
- package/dist/program.js +1 -0
- package/dist/utils/logger.js +11 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,15 @@ Zero-config CLI to use any open-source coding agent with [TokenMix](https://toke
|
|
|
4
4
|
|
|
5
5
|
One account, one balance, 160+ models routed automatically across Claude / GPT / Gemini / DeepSeek / Qwen / Moonshot / ...
|
|
6
6
|
|
|
7
|
+
## Why TokenMix
|
|
8
|
+
|
|
9
|
+
Behind the zero-config CLI is a gateway built to be the **honest, transparent** LLM backend for BYOK coding agents:
|
|
10
|
+
|
|
11
|
+
- **Transparent, real-time billing.** `tokenmix balance` shows your actual balance, gift credit, and total spent — to micro-USD precision, not opaque "credits". `tokenmix models` lists every model's real price (free models show `$0`, not a dash).
|
|
12
|
+
- **Prompt caching that saves you money — automatically.** Cache hits bill at the discounted rate with nothing to configure: OpenAI / DeepSeek / Gemini / Qwen via their `cached_tokens`, Anthropic via `cache_control` pass-through (cache reads ≈10% of the input price). The savings are yours, and you can see them.
|
|
13
|
+
- **One key, every protocol.** OpenAI Chat Completions, Anthropic Messages, and the Responses API — all on one account, which is why every agent below (terminal and editor alike) runs on a single balance.
|
|
14
|
+
- **Non-invasive by design.** Configuring an agent never clobbers your setup: your Claude settings are backed up and restored, Codex's provider is injected at launch (your `~/.codex/config.toml` stays untouched), and `tokenmix logout` reverts everything. Credentials are stored locally at `0600`.
|
|
15
|
+
|
|
7
16
|
## Quick Start
|
|
8
17
|
|
|
9
18
|
```bash
|
package/dist/commands/models.js
CHANGED
|
@@ -31,9 +31,20 @@ export function formatPrice(p) {
|
|
|
31
31
|
return '0';
|
|
32
32
|
return p.toFixed(6).replace(/\.?0+$/, '');
|
|
33
33
|
}
|
|
34
|
+
// Apply --type and --search filters. Exported for unit testing.
|
|
35
|
+
export function filterModels(all, opts) {
|
|
36
|
+
let r = all;
|
|
37
|
+
if (opts.type)
|
|
38
|
+
r = r.filter((m) => m.model_type === opts.type);
|
|
39
|
+
if (opts.search) {
|
|
40
|
+
const kw = opts.search.toLowerCase();
|
|
41
|
+
r = r.filter((m) => (m.short_id || m.model_id || '').toLowerCase().includes(kw));
|
|
42
|
+
}
|
|
43
|
+
return r;
|
|
44
|
+
}
|
|
34
45
|
export async function modelsCommand(opts) {
|
|
35
46
|
const all = await listPublicModels();
|
|
36
|
-
const filtered =
|
|
47
|
+
const filtered = filterModels(all, opts);
|
|
37
48
|
if (filtered.length === 0) {
|
|
38
49
|
logger.warn(t('models.none'));
|
|
39
50
|
return;
|
|
@@ -45,6 +56,8 @@ export async function modelsCommand(opts) {
|
|
|
45
56
|
grouped.set(m.model_type, list);
|
|
46
57
|
}
|
|
47
58
|
for (const [type, list] of grouped) {
|
|
59
|
+
// Stable, readable order within a type (the API order is arbitrary).
|
|
60
|
+
list.sort((a, b) => (a.short_id || a.model_id || '').localeCompare(b.short_id || b.model_id || ''));
|
|
48
61
|
console.log();
|
|
49
62
|
console.log(chalk.bold(`${typeLabel(type)} (${list.length})`));
|
|
50
63
|
for (const m of list) {
|
package/dist/i18n/messages.js
CHANGED
|
@@ -145,6 +145,7 @@ export const en = {
|
|
|
145
145
|
'cmd.topup': 'Open the browser to top up your account',
|
|
146
146
|
'cmd.models': 'List available models with prices',
|
|
147
147
|
'cmd.modelsType': 'Filter by type: chat | embedding | image | audio | video',
|
|
148
|
+
'cmd.modelsSearch': 'Filter models by name (substring match)',
|
|
148
149
|
'cmd.list': 'List supported coding agents',
|
|
149
150
|
'cmd.doctor': 'Diagnose CLI configuration and agent installation',
|
|
150
151
|
'cmd.agent': 'Configure and launch {name} via TokenMix',
|
|
@@ -294,6 +295,7 @@ export const zh = {
|
|
|
294
295
|
'cmd.topup': '打开浏览器为账户充值',
|
|
295
296
|
'cmd.models': '列出可用模型及价格',
|
|
296
297
|
'cmd.modelsType': '按类型筛选:chat | embedding | image | audio | video',
|
|
298
|
+
'cmd.modelsSearch': '按名称筛选模型(子串匹配)',
|
|
297
299
|
'cmd.list': '列出支持的编程 agent',
|
|
298
300
|
'cmd.doctor': '诊断 CLI 配置与 agent 安装情况',
|
|
299
301
|
'cmd.agent': '通过 TokenMix 配置并启动 {name}',
|
|
@@ -428,6 +430,7 @@ export const ja = {
|
|
|
428
430
|
'cmd.topup': 'ブラウザを開いてアカウントにチャージ',
|
|
429
431
|
'cmd.models': '利用可能なモデルと価格を一覧表示',
|
|
430
432
|
'cmd.modelsType': 'タイプで絞り込み:chat | embedding | image | audio | video',
|
|
433
|
+
'cmd.modelsSearch': '名前でモデルを絞り込み(部分一致)',
|
|
431
434
|
'cmd.list': '対応しているコーディング agent を一覧表示',
|
|
432
435
|
'cmd.doctor': 'CLI 設定と agent のインストール状況を診断',
|
|
433
436
|
'cmd.agent': 'TokenMix 経由で {name} を設定して起動',
|
|
@@ -562,6 +565,7 @@ export const ko = {
|
|
|
562
565
|
'cmd.topup': '브라우저를 열어 계정 충전',
|
|
563
566
|
'cmd.models': '사용 가능한 모델과 가격 목록 표시',
|
|
564
567
|
'cmd.modelsType': '유형으로 필터링: chat | embedding | image | audio | video',
|
|
568
|
+
'cmd.modelsSearch': '이름으로 모델 필터링 (부분 일치)',
|
|
565
569
|
'cmd.list': '지원하는 코딩 agent 목록 표시',
|
|
566
570
|
'cmd.doctor': 'CLI 구성과 agent 설치 상태 진단',
|
|
567
571
|
'cmd.agent': 'TokenMix를 통해 {name} 구성 및 실행',
|
|
@@ -696,6 +700,7 @@ export const es = {
|
|
|
696
700
|
'cmd.topup': 'Abre el navegador para recargar tu cuenta',
|
|
697
701
|
'cmd.models': 'Lista los modelos disponibles con precios',
|
|
698
702
|
'cmd.modelsType': 'Filtrar por tipo: chat | embedding | image | audio | video',
|
|
703
|
+
'cmd.modelsSearch': 'Filtrar modelos por nombre (coincidencia parcial)',
|
|
699
704
|
'cmd.list': 'Lista los agents de programación compatibles',
|
|
700
705
|
'cmd.doctor': 'Diagnostica la configuración de la CLI y la instalación de los agents',
|
|
701
706
|
'cmd.agent': 'Configura e inicia {name} vía TokenMix',
|
|
@@ -830,6 +835,7 @@ export const fr = {
|
|
|
830
835
|
'cmd.topup': 'Ouvrir le navigateur pour recharger votre compte',
|
|
831
836
|
'cmd.models': 'Lister les modèles disponibles avec les prix',
|
|
832
837
|
'cmd.modelsType': 'Filtrer par type : chat | embedding | image | audio | video',
|
|
838
|
+
'cmd.modelsSearch': 'Filtrer les modèles par nom (correspondance partielle)',
|
|
833
839
|
'cmd.list': 'Lister les agents de codage pris en charge',
|
|
834
840
|
'cmd.doctor': 'Diagnostiquer la configuration de la CLI et l’installation des agents',
|
|
835
841
|
'cmd.agent': 'Configurer et lancer {name} via TokenMix',
|
package/dist/program.js
CHANGED
|
@@ -46,6 +46,7 @@ export function buildProgram(deps = {}) {
|
|
|
46
46
|
.command('models')
|
|
47
47
|
.description(t('cmd.models'))
|
|
48
48
|
.option('-t, --type <type>', t('cmd.modelsType'))
|
|
49
|
+
.option('-s, --search <keyword>', t('cmd.modelsSearch'))
|
|
49
50
|
.action(modelsCommand);
|
|
50
51
|
program
|
|
51
52
|
.command('list')
|
package/dist/utils/logger.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
// Minimal CLI logger. Symbols are ASCII-friendly Unicode, not emoji.
|
|
3
|
+
//
|
|
4
|
+
// Output-stream contract (deliberate — keep it this way):
|
|
5
|
+
// • step() → STDERR: progress narration ("Configuring…", "Launching…").
|
|
6
|
+
// Off stdout so `tokenmix kilo > config.txt`, piping an agent, or scripting
|
|
7
|
+
// `tokenmix balance` isn't polluted with our progress chatter.
|
|
8
|
+
// • error() → STDERR: failures.
|
|
9
|
+
// • success()/info()/warn()/dim() → STDOUT: these carry user-facing OUTPUT,
|
|
10
|
+
// not just chatter — `balance` prints figures via success(), `doctor` prints
|
|
11
|
+
// its report (incl. "not logged in"/"not installed") via success()/warn().
|
|
12
|
+
// Moving those to stderr would split a command's report across two streams.
|
|
3
13
|
export const logger = {
|
|
4
14
|
info(msg) {
|
|
5
15
|
console.log(msg);
|
|
@@ -14,7 +24,7 @@ export const logger = {
|
|
|
14
24
|
console.error(chalk.red('✗'), msg);
|
|
15
25
|
},
|
|
16
26
|
step(msg) {
|
|
17
|
-
console.
|
|
27
|
+
console.error(chalk.cyan('→'), msg);
|
|
18
28
|
},
|
|
19
29
|
dim(msg) {
|
|
20
30
|
console.log(chalk.dim(msg));
|