tokenmix 0.4.7 → 0.4.9

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 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
@@ -19,6 +28,7 @@ npx tokenmix cline # print Cline VSCode configuration
19
28
  npx tokenmix roo # print Roo Code VSCode configuration
20
29
  npx tokenmix continue # print Continue config.yaml snippet
21
30
  npx tokenmix codex # install + configure + start Codex
31
+ npx tokenmix qwen # install + configure + start Qwen Code
22
32
  ```
23
33
 
24
34
  ### Alternative login modes
@@ -40,6 +50,7 @@ npx tokenmix login --key sk-tm-... # supply API key directly (for CI
40
50
  | [Roo Code](https://github.com/RooCodeInc/Roo-Code) | VSCode extension | config-only |
41
51
  | [Continue](https://github.com/continuedev/continue) | VSCode / JetBrains | config-only |
42
52
  | [Codex](https://github.com/openai/codex) | `npm i -g @openai/codex` | full auto |
53
+ | [Qwen Code](https://github.com/QwenLM/qwen-code) | `npm i -g @qwen-code/qwen-code` | full auto |
43
54
 
44
55
  ## Commands
45
56
 
@@ -60,6 +71,7 @@ tokenmix cline Print Cline configuration
60
71
  tokenmix roo Print Roo Code configuration
61
72
  tokenmix continue Print Continue config.yaml snippet
62
73
  tokenmix codex [args...] Launch Codex via TokenMix
74
+ tokenmix qwen [args...] Launch Qwen Code via TokenMix
63
75
  ```
64
76
 
65
77
  ## Language
@@ -73,6 +73,7 @@ export const CodexAgent = {
73
73
  displayName: 'Codex',
74
74
  description: 'openai/codex — OpenAI coding agent CLI',
75
75
  installMode: 'auto-npm',
76
+ minNode: 22,
76
77
  installCheck,
77
78
  install,
78
79
  configure,
@@ -0,0 +1,61 @@
1
+ import { commandExists, run, captureRun } from '../utils/exec.js';
2
+ import { t } from '../i18n/index.js';
3
+ const QWEN_BIN = 'qwen';
4
+ const QWEN_NPM_PACKAGE = '@qwen-code/qwen-code';
5
+ async function installCheck() {
6
+ const bin = await commandExists(QWEN_BIN);
7
+ if (!bin) {
8
+ const cmd = `npm install -g ${QWEN_NPM_PACKAGE}`;
9
+ return {
10
+ installed: false,
11
+ hint: t('install.willInstallVia', { cmd }),
12
+ installCmd: cmd,
13
+ };
14
+ }
15
+ try {
16
+ const v = await captureRun(QWEN_BIN, ['--version']);
17
+ return { installed: true, version: v.stdout.trim() };
18
+ }
19
+ catch {
20
+ return { installed: true };
21
+ }
22
+ }
23
+ async function install() {
24
+ await run('npm', ['install', '-g', `${QWEN_NPM_PACKAGE}@latest`]);
25
+ }
26
+ async function configure(apiKey, baseUrl, defaultModel) {
27
+ // Qwen Code (a Gemini CLI fork) reads OPENAI_API_KEY / OPENAI_BASE_URL /
28
+ // OPENAI_MODEL when launched with `--auth-type openai` — VERIFIED end-to-end
29
+ // against tokenmix (`qwen -p` replied via the gateway). We pass these via env
30
+ // at launch and never touch the user's ~/.qwen/settings.json.
31
+ return {
32
+ envVars: {
33
+ OPENAI_API_KEY: apiKey,
34
+ OPENAI_BASE_URL: `${baseUrl}/v1`,
35
+ OPENAI_MODEL: defaultModel,
36
+ },
37
+ notes: [t('qwen.noteUsing'), t('qwen.noteModel', { model: defaultModel })],
38
+ };
39
+ }
40
+ async function launch(args, env) {
41
+ // Info-only (`qwen --version` / `--help`) reaches launch with an empty env —
42
+ // just forward, don't force an auth mode.
43
+ if (!env.OPENAI_BASE_URL) {
44
+ await run(QWEN_BIN, args, { env });
45
+ return;
46
+ }
47
+ // Force OpenAI auth mode (Qwen OAuth was retired 2026-04-15) so it uses our env.
48
+ // Our flag goes first; user args follow and can override.
49
+ await run(QWEN_BIN, ['--auth-type', 'openai', ...args], { env });
50
+ }
51
+ export const QwenAgent = {
52
+ id: 'qwen',
53
+ displayName: 'Qwen Code',
54
+ description: 'QwenLM/qwen-code — terminal coding agent (OpenAI-compatible)',
55
+ installMode: 'auto-npm',
56
+ minNode: 22,
57
+ installCheck,
58
+ install,
59
+ configure,
60
+ launch,
61
+ };
@@ -6,6 +6,7 @@ import { ClineAgent } from './cline.js';
6
6
  import { RooAgent } from './roo.js';
7
7
  import { ContinueAgent } from './continue.js';
8
8
  import { CodexAgent } from './codex.js';
9
+ import { QwenAgent } from './qwen.js';
9
10
  // Ordered by historical ARPU on tokenmix (highest first). New agents go to the bottom.
10
11
  export const AGENTS = [
11
12
  OpenCodeAgent,
@@ -16,6 +17,7 @@ export const AGENTS = [
16
17
  RooAgent,
17
18
  ContinueAgent,
18
19
  CodexAgent,
20
+ QwenAgent,
19
21
  ];
20
22
  export function findAgent(id) {
21
23
  return AGENTS.find((a) => a.id === id);
@@ -4,6 +4,11 @@ import { confirm } from '../utils/prompt.js';
4
4
  import { AGENTS } from '../agents/registry.js';
5
5
  import { t } from '../i18n/index.js';
6
6
  const DEFAULT_MODEL = 'claude-sonnet-4.6';
7
+ // Major version of the running Node (e.g. 22 from "v22.9.0"). Gates agents whose
8
+ // binary needs a newer Node than this process (Codex / Qwen Code require 22).
9
+ export function nodeMajor() {
10
+ return parseInt(process.versions.node.split('.')[0], 10);
11
+ }
7
12
  // Flags that are pure information requests meant for the underlying agent binary.
8
13
  // For these we must NOT rewrite global config or require login — just forward them.
9
14
  const INFO_ONLY_FLAGS = new Set(['--version', '-V', '--help', '-h']);
@@ -58,6 +63,16 @@ export async function runAgent(agent, args) {
58
63
  }
59
64
  const baseUrl = apiBaseUrl(cfg);
60
65
  const defaultModel = cfg.defaultModel || DEFAULT_MODEL;
66
+ // Refuse early with a friendly message if the agent's binary needs a newer Node
67
+ // than we're running on (Codex/Qwen need 22) — avoids a cryptic npm/install error.
68
+ if (agent.minNode && nodeMajor() < agent.minNode) {
69
+ logger.error(t('agent.needsNode', {
70
+ name: agent.displayName,
71
+ min: agent.minNode,
72
+ cur: process.versions.node,
73
+ }));
74
+ process.exit(1);
75
+ }
61
76
  // 1. Check install status.
62
77
  const status = await agent.installCheck();
63
78
  if (!status.installed) {
@@ -35,6 +35,8 @@ function agentDesc(id, fallback) {
35
35
  return t('desc.continue');
36
36
  case 'codex':
37
37
  return t('desc.codex');
38
+ case 'qwen':
39
+ return t('desc.qwen');
38
40
  default:
39
41
  return fallback;
40
42
  }
@@ -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 = opts.type ? all.filter((m) => m.model_type === opts.type) : all;
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) {
@@ -28,6 +28,7 @@ export const en = {
28
28
  // agent install / configure / launch
29
29
  'agent.notInstalled': '{name} is not installed.',
30
30
  'agent.notInstallable': '{name} is not installable from the CLI.',
31
+ 'agent.needsNode': '{name} needs Node {min}+ (you have Node {cur}). Upgrade Node (nvm / fnm / volta), then re-run — your TokenMix login is saved.',
31
32
  'agent.installPrompt': '{name} is not installed. Install now?',
32
33
  'agent.installing': 'Installing {name} ...',
33
34
  'agent.installed': '{name} installed.',
@@ -86,6 +87,7 @@ export const en = {
86
87
  'desc.roo': 'RooCodeInc/Roo-Code — VSCode extension (config-only)',
87
88
  'desc.continue': 'continuedev/continue — VSCode/JetBrains extension (config file)',
88
89
  'desc.codex': 'openai/codex — OpenAI coding agent CLI',
90
+ 'desc.qwen': 'QwenLM/qwen-code — terminal coding agent (OpenAI-compatible)',
89
91
  // install hints
90
92
  'install.willInstallVia': 'Will install via: {cmd}',
91
93
  'aider.hintNeedPython': 'Aider requires Python 3. Install Python 3 from https://python.org/downloads, then come back and run `tokenmix aider` again.',
@@ -134,6 +136,9 @@ export const en = {
134
136
  // codex configure notes (auto-npm CLI; launched with --config provider injection)
135
137
  'codex.noteUsing': 'Codex will use TokenMix via an OpenAI-compatible provider — your ~/.codex/config.toml is left untouched.',
136
138
  'codex.noteModel': 'Default model: {model} — override with `--config model=...`.',
139
+ // qwen configure notes (env-based like aider; launched with --auth-type openai)
140
+ 'qwen.noteUsing': 'Qwen Code will use TokenMix via its OpenAI-compatible mode — your ~/.qwen/settings.json is left untouched.',
141
+ 'qwen.noteModel': 'Default model: {model} — override with OPENAI_MODEL or `qwen --model`.',
137
142
  // command / option descriptions (--help)
138
143
  'cmd.program': 'Zero-config CLI to use any open-source coding agent with TokenMix as the unified LLM backend.',
139
144
  'cmd.login': 'Log in to TokenMix (default: browser device authorization)',
@@ -145,6 +150,7 @@ export const en = {
145
150
  'cmd.topup': 'Open the browser to top up your account',
146
151
  'cmd.models': 'List available models with prices',
147
152
  'cmd.modelsType': 'Filter by type: chat | embedding | image | audio | video',
153
+ 'cmd.modelsSearch': 'Filter models by name (substring match)',
148
154
  'cmd.list': 'List supported coding agents',
149
155
  'cmd.doctor': 'Diagnose CLI configuration and agent installation',
150
156
  'cmd.agent': 'Configure and launch {name} via TokenMix',
@@ -181,6 +187,7 @@ export const zh = {
181
187
  // agent install / configure / launch
182
188
  'agent.notInstalled': '{name} 尚未安装。',
183
189
  'agent.notInstallable': '{name} 无法通过 CLI 安装。',
190
+ 'agent.needsNode': '{name} 需要 Node {min}+(你的是 Node {cur})。请升级 Node(nvm / fnm / volta)后重新运行 —— 你的 TokenMix 登录已保存。',
184
191
  'agent.installPrompt': '{name} 尚未安装。现在安装?',
185
192
  'agent.installing': '正在安装 {name} ...',
186
193
  'agent.installed': '{name} 安装完成。',
@@ -239,6 +246,7 @@ export const zh = {
239
246
  'desc.roo': 'RooCodeInc/Roo-Code — VSCode 扩展(仅配置)',
240
247
  'desc.continue': 'continuedev/continue — VSCode/JetBrains 扩展(配置文件)',
241
248
  'desc.codex': 'openai/codex — OpenAI 编程 agent CLI',
249
+ 'desc.qwen': 'QwenLM/qwen-code — 终端编程 agent(OpenAI 兼容)',
242
250
  // install hints
243
251
  'install.willInstallVia': '将自动安装:{cmd}',
244
252
  'aider.hintNeedPython': 'Aider 需要 Python 3。请从 https://python.org/downloads 安装 Python 3,然后重新运行 `tokenmix aider`。',
@@ -283,6 +291,8 @@ export const zh = {
283
291
  'continue.hintNoVscode': '未在 PATH 中检测到 VSCode。请先安装 VSCode,再添加 Continue 扩展,然后使用下面的配置。',
284
292
  'codex.noteUsing': 'Codex 将通过 OpenAI 兼容的 provider 使用 TokenMix —— 不会改动你的 ~/.codex/config.toml。',
285
293
  'codex.noteModel': '默认模型:{model} —— 可用 `--config model=...` 覆盖。',
294
+ 'qwen.noteUsing': 'Qwen Code 将通过其 OpenAI 兼容模式使用 TokenMix —— 不会改动你的 ~/.qwen/settings.json。',
295
+ 'qwen.noteModel': '默认模型:{model} —— 可用 OPENAI_MODEL 或 `qwen --model` 覆盖。',
286
296
  // command / option descriptions (--help)
287
297
  'cmd.program': '零配置 CLI:以 TokenMix 作为统一 LLM 后端,驱动任意开源编程 agent。',
288
298
  'cmd.login': '登录 TokenMix(默认:浏览器设备授权)',
@@ -294,6 +304,7 @@ export const zh = {
294
304
  'cmd.topup': '打开浏览器为账户充值',
295
305
  'cmd.models': '列出可用模型及价格',
296
306
  'cmd.modelsType': '按类型筛选:chat | embedding | image | audio | video',
307
+ 'cmd.modelsSearch': '按名称筛选模型(子串匹配)',
297
308
  'cmd.list': '列出支持的编程 agent',
298
309
  'cmd.doctor': '诊断 CLI 配置与 agent 安装情况',
299
310
  'cmd.agent': '通过 TokenMix 配置并启动 {name}',
@@ -328,6 +339,7 @@ export const ja = {
328
339
  'login.tryAgain': '再試行しますか?',
329
340
  'agent.notInstalled': '{name} はインストールされていません。',
330
341
  'agent.notInstallable': '{name} は CLI からインストールできません。',
342
+ 'agent.needsNode': '{name} には Node {min}+ が必要です(現在 Node {cur})。Node をアップグレード(nvm / fnm / volta)してから再実行してください —— TokenMix のログインは保存済みです。',
331
343
  'agent.installPrompt': '{name} はインストールされていません。今すぐインストールしますか?',
332
344
  'agent.installing': '{name} をインストールしています ...',
333
345
  'agent.installed': '{name} をインストールしました。',
@@ -379,6 +391,7 @@ export const ja = {
379
391
  'desc.roo': 'RooCodeInc/Roo-Code — VSCode 拡張機能(設定のみ)',
380
392
  'desc.continue': 'continuedev/continue — VSCode/JetBrains 拡張機能(設定ファイル)',
381
393
  'desc.codex': 'openai/codex — OpenAI のコーディング agent CLI',
394
+ 'desc.qwen': 'QwenLM/qwen-code — ターミナルのコーディング agent(OpenAI 互換)',
382
395
  'install.willInstallVia': '次の方法でインストールします:{cmd}',
383
396
  'aider.hintNeedPython': 'Aider には Python 3 が必要です。https://python.org/downloads から Python 3 をインストールし、再度 `tokenmix aider` を実行してください。',
384
397
  'aider.hintNotInstalled': 'Aider はインストールされていません。別のターミナルで次を実行してください:\n {cmd}\nその後 `tokenmix aider` を再実行してください — TokenMix のログインは保存済みなので自動的に反映されます。',
@@ -418,6 +431,8 @@ export const ja = {
418
431
  'continue.hintNoVscode': 'PATH に VSCode が見つかりません。VSCode をインストールし、Continue 拡張機能を追加してから、下の設定を使用してください。',
419
432
  'codex.noteUsing': 'Codex は OpenAI 互換プロバイダー経由で TokenMix を使用します — ~/.codex/config.toml は変更されません。',
420
433
  'codex.noteModel': 'デフォルトモデル:{model} — `--config model=...` で上書きできます。',
434
+ 'qwen.noteUsing': 'Qwen Code は OpenAI 互換モードで TokenMix を使用します —— ~/.qwen/settings.json は変更されません。',
435
+ 'qwen.noteModel': 'デフォルトモデル:{model} — OPENAI_MODEL または `qwen --model` で上書きできます。',
421
436
  'cmd.program': 'TokenMix を統一 LLM バックエンドとして、あらゆるオープンソースのコーディング agent を使うためのゼロ設定 CLI。',
422
437
  'cmd.login': 'TokenMix にログイン(デフォルト:ブラウザでのデバイス認証)',
423
438
  'cmd.loginKey': 'API キーを直接貼り付け(ブラウザ認証をスキップ、CI に便利)',
@@ -428,6 +443,7 @@ export const ja = {
428
443
  'cmd.topup': 'ブラウザを開いてアカウントにチャージ',
429
444
  'cmd.models': '利用可能なモデルと価格を一覧表示',
430
445
  'cmd.modelsType': 'タイプで絞り込み:chat | embedding | image | audio | video',
446
+ 'cmd.modelsSearch': '名前でモデルを絞り込み(部分一致)',
431
447
  'cmd.list': '対応しているコーディング agent を一覧表示',
432
448
  'cmd.doctor': 'CLI 設定と agent のインストール状況を診断',
433
449
  'cmd.agent': 'TokenMix 経由で {name} を設定して起動',
@@ -462,6 +478,7 @@ export const ko = {
462
478
  'login.tryAgain': '다시 시도할까요?',
463
479
  'agent.notInstalled': '{name}이(가) 설치되어 있지 않습니다.',
464
480
  'agent.notInstallable': '{name}은(는) CLI에서 설치할 수 없습니다.',
481
+ 'agent.needsNode': '{name}에는 Node {min}+ 가 필요합니다(현재 Node {cur}). Node를 업그레이드(nvm / fnm / volta)한 뒤 다시 실행하세요 —— TokenMix 로그인은 저장되어 있습니다.',
465
482
  'agent.installPrompt': '{name}이(가) 설치되어 있지 않습니다. 지금 설치할까요?',
466
483
  'agent.installing': '{name} 설치 중 ...',
467
484
  'agent.installed': '{name} 설치 완료.',
@@ -513,6 +530,7 @@ export const ko = {
513
530
  'desc.roo': 'RooCodeInc/Roo-Code — VSCode 확장 (설정 전용)',
514
531
  'desc.continue': 'continuedev/continue — VSCode/JetBrains 확장 (설정 파일)',
515
532
  'desc.codex': 'openai/codex — OpenAI 코딩 agent CLI',
533
+ 'desc.qwen': 'QwenLM/qwen-code — 터미널 코딩 agent (OpenAI 호환)',
516
534
  'install.willInstallVia': '다음 방법으로 설치합니다: {cmd}',
517
535
  'aider.hintNeedPython': 'Aider에는 Python 3가 필요합니다. https://python.org/downloads 에서 Python 3를 설치한 뒤 다시 `tokenmix aider`를 실행하세요.',
518
536
  'aider.hintNotInstalled': 'Aider가 설치되어 있지 않습니다. 다른 터미널에서 다음을 실행하세요:\n {cmd}\n그런 다음 다시 `tokenmix aider`를 실행하세요 — TokenMix 로그인이 이미 저장되어 있어 자동으로 적용됩니다.',
@@ -552,6 +570,8 @@ export const ko = {
552
570
  'continue.hintNoVscode': 'PATH에서 VSCode를 찾을 수 없습니다. VSCode를 설치하고 Continue 확장을 추가한 뒤 아래 설정을 사용하세요.',
553
571
  'codex.noteUsing': 'Codex는 OpenAI 호환 provider를 통해 TokenMix를 사용합니다 — ~/.codex/config.toml은 변경되지 않습니다.',
554
572
  'codex.noteModel': '기본 모델: {model} — `--config model=...`으로 재정의할 수 있습니다.',
573
+ 'qwen.noteUsing': 'Qwen Code는 OpenAI 호환 모드로 TokenMix를 사용합니다 — ~/.qwen/settings.json은 변경되지 않습니다.',
574
+ 'qwen.noteModel': '기본 모델: {model} — OPENAI_MODEL 또는 `qwen --model`으로 재정의할 수 있습니다.',
555
575
  'cmd.program': 'TokenMix를 통합 LLM 백엔드로 사용하여 모든 오픈소스 코딩 agent를 쓰는 제로 설정 CLI.',
556
576
  'cmd.login': 'TokenMix에 로그인 (기본값: 브라우저 기기 인증)',
557
577
  'cmd.loginKey': 'API 키를 직접 붙여넣기 (브라우저 절차 생략, CI에 유용)',
@@ -562,6 +582,7 @@ export const ko = {
562
582
  'cmd.topup': '브라우저를 열어 계정 충전',
563
583
  'cmd.models': '사용 가능한 모델과 가격 목록 표시',
564
584
  'cmd.modelsType': '유형으로 필터링: chat | embedding | image | audio | video',
585
+ 'cmd.modelsSearch': '이름으로 모델 필터링 (부분 일치)',
565
586
  'cmd.list': '지원하는 코딩 agent 목록 표시',
566
587
  'cmd.doctor': 'CLI 구성과 agent 설치 상태 진단',
567
588
  'cmd.agent': 'TokenMix를 통해 {name} 구성 및 실행',
@@ -596,6 +617,7 @@ export const es = {
596
617
  'login.tryAgain': '¿Reintentar?',
597
618
  'agent.notInstalled': '{name} no está instalado.',
598
619
  'agent.notInstallable': '{name} no se puede instalar desde la CLI.',
620
+ 'agent.needsNode': '{name} necesita Node {min}+ (tienes Node {cur}). Actualiza Node (nvm / fnm / volta) y vuelve a ejecutar —— tu sesión de TokenMix está guardada.',
599
621
  'agent.installPrompt': '{name} no está instalado. ¿Instalar ahora?',
600
622
  'agent.installing': 'Instalando {name} ...',
601
623
  'agent.installed': '{name} instalado.',
@@ -647,6 +669,7 @@ export const es = {
647
669
  'desc.roo': 'RooCodeInc/Roo-Code — extensión de VSCode (solo configuración)',
648
670
  'desc.continue': 'continuedev/continue — extensión de VSCode/JetBrains (archivo de configuración)',
649
671
  'desc.codex': 'openai/codex — CLI del agente de programación de OpenAI',
672
+ 'desc.qwen': 'QwenLM/qwen-code — agente de programación de terminal (compatible con OpenAI)',
650
673
  'install.willInstallVia': 'Se instalará mediante: {cmd}',
651
674
  'aider.hintNeedPython': 'Aider requiere Python 3. Instala Python 3 desde https://python.org/downloads y vuelve a ejecutar `tokenmix aider`.',
652
675
  'aider.hintNotInstalled': 'Aider no está instalado. Ejecuta esto en otra terminal:\n {cmd}\nLuego vuelve a ejecutar `tokenmix aider`: tu sesión de TokenMix ya está guardada, así que se detectará automáticamente.',
@@ -686,6 +709,8 @@ export const es = {
686
709
  'continue.hintNoVscode': 'No se detectó VSCode en el PATH. Instala VSCode, añade la extensión Continue y luego usa la configuración de abajo.',
687
710
  'codex.noteUsing': 'Codex usará TokenMix mediante un proveedor compatible con OpenAI: tu ~/.codex/config.toml no se modifica.',
688
711
  'codex.noteModel': 'Modelo por defecto: {model} — anúlalo con `--config model=...`.',
712
+ 'qwen.noteUsing': 'Qwen Code usará TokenMix mediante su modo compatible con OpenAI: tu ~/.qwen/settings.json no se modifica.',
713
+ 'qwen.noteModel': 'Modelo por defecto: {model} — anúlalo con OPENAI_MODEL o `qwen --model`.',
689
714
  'cmd.program': 'CLI sin configuración para usar cualquier agent de programación de código abierto con TokenMix como backend LLM unificado.',
690
715
  'cmd.login': 'Inicia sesión en TokenMix (predeterminado: autorización de dispositivo por navegador)',
691
716
  'cmd.loginKey': 'Pega una clave de API directamente (omite el navegador, útil para CI)',
@@ -696,6 +721,7 @@ export const es = {
696
721
  'cmd.topup': 'Abre el navegador para recargar tu cuenta',
697
722
  'cmd.models': 'Lista los modelos disponibles con precios',
698
723
  'cmd.modelsType': 'Filtrar por tipo: chat | embedding | image | audio | video',
724
+ 'cmd.modelsSearch': 'Filtrar modelos por nombre (coincidencia parcial)',
699
725
  'cmd.list': 'Lista los agents de programación compatibles',
700
726
  'cmd.doctor': 'Diagnostica la configuración de la CLI y la instalación de los agents',
701
727
  'cmd.agent': 'Configura e inicia {name} vía TokenMix',
@@ -730,6 +756,7 @@ export const fr = {
730
756
  'login.tryAgain': 'Réessayer ?',
731
757
  'agent.notInstalled': '{name} n’est pas installé.',
732
758
  'agent.notInstallable': '{name} ne peut pas être installé depuis la CLI.',
759
+ 'agent.needsNode': '{name} nécessite Node {min}+ (vous avez Node {cur}). Mettez Node à jour (nvm / fnm / volta), puis relancez —— votre connexion TokenMix est enregistrée.',
733
760
  'agent.installPrompt': '{name} n’est pas installé. Installer maintenant ?',
734
761
  'agent.installing': 'Installation de {name} ...',
735
762
  'agent.installed': '{name} installé.',
@@ -781,6 +808,7 @@ export const fr = {
781
808
  'desc.roo': 'RooCodeInc/Roo-Code — extension VSCode (configuration seule)',
782
809
  'desc.continue': 'continuedev/continue — extension VSCode/JetBrains (fichier de configuration)',
783
810
  'desc.codex': 'openai/codex — CLI de l’agent de codage d’OpenAI',
811
+ 'desc.qwen': 'QwenLM/qwen-code — agent de codage en terminal (compatible OpenAI)',
784
812
  'install.willInstallVia': 'Sera installé via : {cmd}',
785
813
  'aider.hintNeedPython': 'Aider nécessite Python 3. Installez Python 3 depuis https://python.org/downloads, puis relancez `tokenmix aider`.',
786
814
  'aider.hintNotInstalled': 'Aider n’est pas installé. Exécutez ceci dans un autre terminal :\n {cmd}\nPuis relancez `tokenmix aider` — votre connexion TokenMix est déjà enregistrée, elle sera donc prise en compte automatiquement.',
@@ -820,6 +848,8 @@ export const fr = {
820
848
  'continue.hintNoVscode': 'VSCode introuvable dans le PATH. Installez VSCode, ajoutez l’extension Continue, puis utilisez la configuration ci-dessous.',
821
849
  'codex.noteUsing': 'Codex utilisera TokenMix via un fournisseur compatible OpenAI — votre ~/.codex/config.toml n’est pas modifié.',
822
850
  'codex.noteModel': 'Modèle par défaut : {model} — remplacez-le avec `--config model=...`.',
851
+ 'qwen.noteUsing': 'Qwen Code utilisera TokenMix via son mode compatible OpenAI — votre ~/.qwen/settings.json n’est pas modifié.',
852
+ 'qwen.noteModel': 'Modèle par défaut : {model} — remplacez-le avec OPENAI_MODEL ou `qwen --model`.',
823
853
  'cmd.program': 'CLI sans configuration pour utiliser n’importe quel agent de codage open source avec TokenMix comme backend LLM unifié.',
824
854
  'cmd.login': 'Se connecter à TokenMix (par défaut : autorisation de l’appareil via le navigateur)',
825
855
  'cmd.loginKey': 'Coller directement une clé API (ignore le navigateur, utile pour la CI)',
@@ -830,6 +860,7 @@ export const fr = {
830
860
  'cmd.topup': 'Ouvrir le navigateur pour recharger votre compte',
831
861
  'cmd.models': 'Lister les modèles disponibles avec les prix',
832
862
  'cmd.modelsType': 'Filtrer par type : chat | embedding | image | audio | video',
863
+ 'cmd.modelsSearch': 'Filtrer les modèles par nom (correspondance partielle)',
833
864
  'cmd.list': 'Lister les agents de codage pris en charge',
834
865
  'cmd.doctor': 'Diagnostiquer la configuration de la CLI et l’installation des agents',
835
866
  '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')
@@ -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.log(chalk.cyan('→'), msg);
27
+ console.error(chalk.cyan('→'), msg);
18
28
  },
19
29
  dim(msg) {
20
30
  console.log(chalk.dim(msg));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokenmix",
3
- "version": "0.4.7",
3
+ "version": "0.4.9",
4
4
  "description": "Zero-config CLI to use any open-source coding agent with TokenMix as the unified LLM backend.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31,6 +31,7 @@
31
31
  "roo-code",
32
32
  "continue",
33
33
  "codex",
34
+ "qwen-code",
34
35
  "coding-agent"
35
36
  ],
36
37
  "license": "MIT",