tokenmix 0.4.10 → 0.4.12

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
@@ -8,6 +8,7 @@ One account, one balance, 160+ models routed automatically across Claude / GPT /
8
8
 
9
9
  Behind the zero-config CLI is a gateway built to be the **honest, transparent** LLM backend for BYOK coding agents:
10
10
 
11
+ - **The model you pick is the model you get.** Your request routes to the real upstream model you named — no silent downgrade to a cheaper one (the grey market's classic "sold Opus, served Haiku"). Model aliases are name normalization only, never a swap.
11
12
  - **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
13
  - **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
14
  - **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.
@@ -30,6 +31,7 @@ npx tokenmix continue # print Continue config.yaml snippet
30
31
  npx tokenmix codex # install + configure + start Codex
31
32
  npx tokenmix qwen # install + configure + start Qwen Code
32
33
  npx tokenmix goose # configure + start Goose (install it first)
34
+ npx tokenmix openhands # configure + start OpenHands (install it first)
33
35
  ```
34
36
 
35
37
  ### Alternative login modes
@@ -53,6 +55,7 @@ npx tokenmix login --key sk-tm-... # supply API key directly (for CI
53
55
  | [Codex](https://github.com/openai/codex) | `npm i -g @openai/codex` | full auto |
54
56
  | [Qwen Code](https://github.com/QwenLM/qwen-code) | `npm i -g @qwen-code/qwen-code` | full auto |
55
57
  | [Goose](https://github.com/block/goose) | [install script](https://block.github.io/goose) | semi auto |
58
+ | [OpenHands](https://github.com/All-Hands-AI/OpenHands) | `uv tool install openhands` (Python 3.12+) | semi auto |
56
59
 
57
60
  ## Commands
58
61
 
@@ -75,6 +78,7 @@ tokenmix continue Print Continue config.yaml snippet
75
78
  tokenmix codex [args...] Launch Codex via TokenMix
76
79
  tokenmix qwen [args...] Launch Qwen Code via TokenMix
77
80
  tokenmix goose [args...] Launch Goose via TokenMix
81
+ tokenmix openhands [args...] Launch OpenHands via TokenMix
78
82
  ```
79
83
 
80
84
  ## Language
@@ -87,6 +91,17 @@ TOKENMIX_LANG=ja npx tokenmix doctor # 日本語
87
91
  TOKENMIX_LANG=fr npx tokenmix doctor # Français
88
92
  ```
89
93
 
94
+ ## Default model
95
+
96
+ Agents default to `claude-sonnet-4.6`. Override it for any launch with the `TOKENMIX_DEFAULT_MODEL` environment variable — handy for a cheaper/faster default or for scripting:
97
+
98
+ ```bash
99
+ TOKENMIX_DEFAULT_MODEL=claude-haiku-4.5 npx tokenmix opencode
100
+ TOKENMIX_DEFAULT_MODEL=qwen-flash npx tokenmix aider
101
+ ```
102
+
103
+ (`tokenmix claude` and `tokenmix codex` speak the Anthropic / Responses protocols, so they need a Claude-family model; the other agents accept any chat model.)
104
+
90
105
  ## Configuration Location
91
106
 
92
107
  Your TokenMix credentials are stored locally at:
@@ -0,0 +1,55 @@
1
+ import { commandExists, run, captureRun } from '../utils/exec.js';
2
+ import { t } from '../i18n/index.js';
3
+ const OPENHANDS_BIN = 'openhands';
4
+ // OpenHands needs Python 3.12+; `uv` pulls a matching Python automatically. We
5
+ // print this rather than auto-running it (it installs a toolchain + Python).
6
+ const OPENHANDS_INSTALL = 'uv tool install openhands --python 3.12';
7
+ async function installCheck() {
8
+ const bin = await commandExists(OPENHANDS_BIN);
9
+ if (!bin) {
10
+ return {
11
+ installed: false,
12
+ hint: t('openhands.hintInstall', { cmd: OPENHANDS_INSTALL }),
13
+ installCmd: OPENHANDS_INSTALL,
14
+ };
15
+ }
16
+ try {
17
+ const v = await captureRun(OPENHANDS_BIN, ['--version']);
18
+ return { installed: true, version: v.stdout.trim() };
19
+ }
20
+ catch {
21
+ return { installed: true };
22
+ }
23
+ }
24
+ async function configure(apiKey, baseUrl, defaultModel) {
25
+ // OpenHands reads LLM_API_KEY/LLM_MODEL/LLM_BASE_URL but ONLY when launched with
26
+ // --override-with-envs (injected in launch()). LLM_MODEL needs a LiteLLM provider
27
+ // prefix — `openai/` routes to the OpenAI-compatible path. Verified end-to-end.
28
+ return {
29
+ envVars: {
30
+ LLM_API_KEY: apiKey,
31
+ LLM_MODEL: `openai/${defaultModel}`,
32
+ LLM_BASE_URL: `${baseUrl}/v1`,
33
+ OPENHANDS_SUPPRESS_BANNER: '1',
34
+ },
35
+ notes: [t('openhands.noteUsing'), t('openhands.noteModel', { model: defaultModel })],
36
+ };
37
+ }
38
+ async function launch(args, env) {
39
+ // Info-only (`openhands --version`) arrives with an empty env — just forward.
40
+ if (!env.LLM_BASE_URL) {
41
+ await run(OPENHANDS_BIN, args, { env });
42
+ return;
43
+ }
44
+ // OpenHands ignores the LLM_* env vars unless --override-with-envs is passed.
45
+ await run(OPENHANDS_BIN, ['--override-with-envs', ...args], { env });
46
+ }
47
+ export const OpenHandsAgent = {
48
+ id: 'openhands',
49
+ displayName: 'OpenHands',
50
+ description: 'All-Hands-AI/OpenHands — autonomous coding agent (OpenAI-compatible)',
51
+ installMode: 'manual',
52
+ installCheck,
53
+ configure,
54
+ launch,
55
+ };
@@ -8,6 +8,7 @@ import { ContinueAgent } from './continue.js';
8
8
  import { CodexAgent } from './codex.js';
9
9
  import { QwenAgent } from './qwen.js';
10
10
  import { GooseAgent } from './goose.js';
11
+ import { OpenHandsAgent } from './openhands.js';
11
12
  // Ordered by historical ARPU on tokenmix (highest first). New agents go to the bottom.
12
13
  export const AGENTS = [
13
14
  OpenCodeAgent,
@@ -20,6 +21,7 @@ export const AGENTS = [
20
21
  CodexAgent,
21
22
  QwenAgent,
22
23
  GooseAgent,
24
+ OpenHandsAgent,
23
25
  ];
24
26
  export function findAgent(id) {
25
27
  return AGENTS.find((a) => a.id === id);
@@ -62,7 +62,9 @@ export async function runAgent(agent, args) {
62
62
  process.exit(1);
63
63
  }
64
64
  const baseUrl = apiBaseUrl(cfg);
65
- const defaultModel = cfg.defaultModel || DEFAULT_MODEL;
65
+ // TOKENMIX_DEFAULT_MODEL env overrides the model — handy for CI/scripts that want a
66
+ // cheap model, or as a power-user default. Falls back to stored config, then built-in.
67
+ const defaultModel = process.env.TOKENMIX_DEFAULT_MODEL || cfg.defaultModel || DEFAULT_MODEL;
66
68
  // Refuse early with a friendly message if the agent's binary needs a newer Node
67
69
  // than we're running on (Codex/Qwen need 22) — avoids a cryptic npm/install error.
68
70
  if (agent.minNode && nodeMajor() < agent.minNode) {
@@ -39,6 +39,8 @@ function agentDesc(id, fallback) {
39
39
  return t('desc.qwen');
40
40
  case 'goose':
41
41
  return t('desc.goose');
42
+ case 'openhands':
43
+ return t('desc.openhands');
42
44
  default:
43
45
  return fallback;
44
46
  }
@@ -89,6 +89,7 @@ export const en = {
89
89
  'desc.codex': 'openai/codex — OpenAI coding agent CLI',
90
90
  'desc.qwen': 'QwenLM/qwen-code — terminal coding agent (OpenAI-compatible)',
91
91
  'desc.goose': 'block/goose — on-machine AI agent (OpenAI-compatible)',
92
+ 'desc.openhands': 'All-Hands-AI/OpenHands — autonomous coding agent (OpenAI-compatible)',
92
93
  // install hints
93
94
  'install.willInstallVia': 'Will install via: {cmd}',
94
95
  'aider.hintNeedPython': 'Aider requires Python 3. Install Python 3 from https://python.org/downloads, then come back and run `tokenmix aider` again.',
@@ -143,6 +144,10 @@ export const en = {
143
144
  // goose configure notes (env-based; Goose appends /v1/chat/completions to OPENAI_HOST)
144
145
  'goose.noteUsing': 'Goose will use TokenMix as its OpenAI provider — its keyring/config is left untouched.',
145
146
  'goose.noteModel': 'Default model: {model} — override with GOOSE_MODEL.',
147
+ // openhands configure notes (env via --override-with-envs; LLM_MODEL needs openai/ prefix)
148
+ 'openhands.noteUsing': 'OpenHands will use TokenMix via LiteLLM (--override-with-envs) — your saved config is left untouched.',
149
+ 'openhands.noteModel': 'Default model: openai/{model} — override with LLM_MODEL (keep the openai/ prefix).',
150
+ 'openhands.hintInstall': 'OpenHands is not installed (needs Python 3.12+). Install it, then re-run `tokenmix openhands`:\n {cmd}',
146
151
  'goose.hintInstall': 'Goose is not installed. Install it (see https://block.github.io/goose), then re-run `tokenmix goose`:\n {cmd}',
147
152
  // command / option descriptions (--help)
148
153
  'cmd.program': 'Zero-config CLI to use any open-source coding agent with TokenMix as the unified LLM backend.',
@@ -253,6 +258,7 @@ export const zh = {
253
258
  'desc.codex': 'openai/codex — OpenAI 编程 agent CLI',
254
259
  'desc.qwen': 'QwenLM/qwen-code — 终端编程 agent(OpenAI 兼容)',
255
260
  'desc.goose': 'block/goose — 本机 AI agent(OpenAI 兼容)',
261
+ 'desc.openhands': 'All-Hands-AI/OpenHands — 自主编程 agent(OpenAI 兼容)',
256
262
  // install hints
257
263
  'install.willInstallVia': '将自动安装:{cmd}',
258
264
  'aider.hintNeedPython': 'Aider 需要 Python 3。请从 https://python.org/downloads 安装 Python 3,然后重新运行 `tokenmix aider`。',
@@ -301,6 +307,9 @@ export const zh = {
301
307
  'qwen.noteModel': '默认模型:{model} —— 可用 OPENAI_MODEL 或 `qwen --model` 覆盖。',
302
308
  'goose.noteUsing': 'Goose 将以 TokenMix 作为其 OpenAI provider —— 不会改动它的 keyring/配置。',
303
309
  'goose.noteModel': '默认模型:{model} —— 可用 GOOSE_MODEL 覆盖。',
310
+ 'openhands.noteUsing': 'OpenHands 将通过 LiteLLM(--override-with-envs)使用 TokenMix —— 不会改动你已保存的配置。',
311
+ 'openhands.noteModel': '默认模型:openai/{model} —— 可用 LLM_MODEL 覆盖(保留 openai/ 前缀)。',
312
+ 'openhands.hintInstall': 'OpenHands 未安装(需要 Python 3.12+)。请先安装,然后重新运行 `tokenmix openhands`:\n {cmd}',
304
313
  'goose.hintInstall': 'Goose 未安装。请先安装(见 https://block.github.io/goose),然后重新运行 `tokenmix goose`:\n {cmd}',
305
314
  // command / option descriptions (--help)
306
315
  'cmd.program': '零配置 CLI:以 TokenMix 作为统一 LLM 后端,驱动任意开源编程 agent。',
@@ -402,6 +411,7 @@ export const ja = {
402
411
  'desc.codex': 'openai/codex — OpenAI のコーディング agent CLI',
403
412
  'desc.qwen': 'QwenLM/qwen-code — ターミナルのコーディング agent(OpenAI 互換)',
404
413
  'desc.goose': 'block/goose — オンマシン AI agent(OpenAI 互換)',
414
+ 'desc.openhands': 'All-Hands-AI/OpenHands — 自律型コーディング agent(OpenAI 互換)',
405
415
  'install.willInstallVia': '次の方法でインストールします:{cmd}',
406
416
  'aider.hintNeedPython': 'Aider には Python 3 が必要です。https://python.org/downloads から Python 3 をインストールし、再度 `tokenmix aider` を実行してください。',
407
417
  'aider.hintNotInstalled': 'Aider はインストールされていません。別のターミナルで次を実行してください:\n {cmd}\nその後 `tokenmix aider` を再実行してください — TokenMix のログインは保存済みなので自動的に反映されます。',
@@ -445,6 +455,9 @@ export const ja = {
445
455
  'qwen.noteModel': 'デフォルトモデル:{model} — OPENAI_MODEL または `qwen --model` で上書きできます。',
446
456
  'goose.noteUsing': 'Goose は TokenMix を OpenAI プロバイダーとして使用します —— keyring/設定は変更されません。',
447
457
  'goose.noteModel': 'デフォルトモデル:{model} — GOOSE_MODEL で上書きできます。',
458
+ 'openhands.noteUsing': 'OpenHands は LiteLLM(--override-with-envs)経由で TokenMix を使用します —— 保存済みの設定は変更されません。',
459
+ 'openhands.noteModel': 'デフォルトモデル:openai/{model} — LLM_MODEL で上書きできます(openai/ プレフィックスは残してください)。',
460
+ 'openhands.hintInstall': 'OpenHands がインストールされていません(Python 3.12+ が必要)。インストールしてから `tokenmix openhands` を再実行してください:\n {cmd}',
448
461
  'goose.hintInstall': 'Goose がインストールされていません。インストール(https://block.github.io/goose 参照)してから `tokenmix goose` を再実行してください:\n {cmd}',
449
462
  'cmd.program': 'TokenMix を統一 LLM バックエンドとして、あらゆるオープンソースのコーディング agent を使うためのゼロ設定 CLI。',
450
463
  'cmd.login': 'TokenMix にログイン(デフォルト:ブラウザでのデバイス認証)',
@@ -545,6 +558,7 @@ export const ko = {
545
558
  'desc.codex': 'openai/codex — OpenAI 코딩 agent CLI',
546
559
  'desc.qwen': 'QwenLM/qwen-code — 터미널 코딩 agent (OpenAI 호환)',
547
560
  'desc.goose': 'block/goose — 온디바이스 AI agent (OpenAI 호환)',
561
+ 'desc.openhands': 'All-Hands-AI/OpenHands — 자율 코딩 agent (OpenAI 호환)',
548
562
  'install.willInstallVia': '다음 방법으로 설치합니다: {cmd}',
549
563
  'aider.hintNeedPython': 'Aider에는 Python 3가 필요합니다. https://python.org/downloads 에서 Python 3를 설치한 뒤 다시 `tokenmix aider`를 실행하세요.',
550
564
  'aider.hintNotInstalled': 'Aider가 설치되어 있지 않습니다. 다른 터미널에서 다음을 실행하세요:\n {cmd}\n그런 다음 다시 `tokenmix aider`를 실행하세요 — TokenMix 로그인이 이미 저장되어 있어 자동으로 적용됩니다.',
@@ -588,6 +602,9 @@ export const ko = {
588
602
  'qwen.noteModel': '기본 모델: {model} — OPENAI_MODEL 또는 `qwen --model`으로 재정의할 수 있습니다.',
589
603
  'goose.noteUsing': 'Goose는 TokenMix를 OpenAI provider로 사용합니다 — keyring/설정은 변경되지 않습니다.',
590
604
  'goose.noteModel': '기본 모델: {model} — GOOSE_MODEL로 재정의할 수 있습니다.',
605
+ 'openhands.noteUsing': 'OpenHands는 LiteLLM(--override-with-envs)을 통해 TokenMix를 사용합니다 — 저장된 설정은 변경되지 않습니다.',
606
+ 'openhands.noteModel': '기본 모델: openai/{model} — LLM_MODEL로 재정의할 수 있습니다(openai/ 접두사 유지).',
607
+ 'openhands.hintInstall': 'OpenHands가 설치되어 있지 않습니다(Python 3.12+ 필요). 설치 후 `tokenmix openhands`를 다시 실행하세요:\n {cmd}',
591
608
  'goose.hintInstall': 'Goose가 설치되어 있지 않습니다. 설치(https://block.github.io/goose 참조) 후 `tokenmix goose`를 다시 실행하세요:\n {cmd}',
592
609
  'cmd.program': 'TokenMix를 통합 LLM 백엔드로 사용하여 모든 오픈소스 코딩 agent를 쓰는 제로 설정 CLI.',
593
610
  'cmd.login': 'TokenMix에 로그인 (기본값: 브라우저 기기 인증)',
@@ -688,6 +705,7 @@ export const es = {
688
705
  'desc.codex': 'openai/codex — CLI del agente de programación de OpenAI',
689
706
  'desc.qwen': 'QwenLM/qwen-code — agente de programación de terminal (compatible con OpenAI)',
690
707
  'desc.goose': 'block/goose — agente de IA en tu máquina (compatible con OpenAI)',
708
+ 'desc.openhands': 'All-Hands-AI/OpenHands — agente de programación autónomo (compatible con OpenAI)',
691
709
  'install.willInstallVia': 'Se instalará mediante: {cmd}',
692
710
  'aider.hintNeedPython': 'Aider requiere Python 3. Instala Python 3 desde https://python.org/downloads y vuelve a ejecutar `tokenmix aider`.',
693
711
  '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.',
@@ -731,6 +749,9 @@ export const es = {
731
749
  'qwen.noteModel': 'Modelo por defecto: {model} — anúlalo con OPENAI_MODEL o `qwen --model`.',
732
750
  'goose.noteUsing': 'Goose usará TokenMix como su proveedor de OpenAI: su keyring/configuración no se modifica.',
733
751
  'goose.noteModel': 'Modelo por defecto: {model} — anúlalo con GOOSE_MODEL.',
752
+ 'openhands.noteUsing': 'OpenHands usará TokenMix mediante LiteLLM (--override-with-envs): tu configuración guardada no se modifica.',
753
+ 'openhands.noteModel': 'Modelo por defecto: openai/{model} — anúlalo con LLM_MODEL (mantén el prefijo openai/).',
754
+ 'openhands.hintInstall': 'OpenHands no está instalado (requiere Python 3.12+). Instálalo y vuelve a ejecutar `tokenmix openhands`:\n {cmd}',
734
755
  'goose.hintInstall': 'Goose no está instalado. Instálalo (consulta https://block.github.io/goose) y vuelve a ejecutar `tokenmix goose`:\n {cmd}',
735
756
  'cmd.program': 'CLI sin configuración para usar cualquier agent de programación de código abierto con TokenMix como backend LLM unificado.',
736
757
  'cmd.login': 'Inicia sesión en TokenMix (predeterminado: autorización de dispositivo por navegador)',
@@ -831,6 +852,7 @@ export const fr = {
831
852
  'desc.codex': 'openai/codex — CLI de l’agent de codage d’OpenAI',
832
853
  'desc.qwen': 'QwenLM/qwen-code — agent de codage en terminal (compatible OpenAI)',
833
854
  'desc.goose': 'block/goose — agent IA sur votre machine (compatible OpenAI)',
855
+ 'desc.openhands': 'All-Hands-AI/OpenHands — agent de codage autonome (compatible OpenAI)',
834
856
  'install.willInstallVia': 'Sera installé via : {cmd}',
835
857
  'aider.hintNeedPython': 'Aider nécessite Python 3. Installez Python 3 depuis https://python.org/downloads, puis relancez `tokenmix aider`.',
836
858
  '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.',
@@ -874,6 +896,9 @@ export const fr = {
874
896
  'qwen.noteModel': 'Modèle par défaut : {model} — remplacez-le avec OPENAI_MODEL ou `qwen --model`.',
875
897
  'goose.noteUsing': 'Goose utilisera TokenMix comme fournisseur OpenAI — son keyring/sa configuration n’est pas modifié.',
876
898
  'goose.noteModel': 'Modèle par défaut : {model} — remplacez-le avec GOOSE_MODEL.',
899
+ 'openhands.noteUsing': 'OpenHands utilisera TokenMix via LiteLLM (--override-with-envs) — votre configuration enregistrée n’est pas modifiée.',
900
+ 'openhands.noteModel': 'Modèle par défaut : openai/{model} — remplacez-le avec LLM_MODEL (gardez le préfixe openai/).',
901
+ 'openhands.hintInstall': 'OpenHands n’est pas installé (nécessite Python 3.12+). Installez-le, puis relancez `tokenmix openhands` :\n {cmd}',
877
902
  'goose.hintInstall': 'Goose n’est pas installé. Installez-le (voir https://block.github.io/goose), puis relancez `tokenmix goose` :\n {cmd}',
878
903
  'cmd.program': 'CLI sans configuration pour utiliser n’importe quel agent de codage open source avec TokenMix comme backend LLM unifié.',
879
904
  'cmd.login': 'Se connecter à TokenMix (par défaut : autorisation de l’appareil via le navigateur)',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokenmix",
3
- "version": "0.4.10",
3
+ "version": "0.4.12",
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": {
@@ -33,6 +33,7 @@
33
33
  "codex",
34
34
  "qwen-code",
35
35
  "goose",
36
+ "openhands",
36
37
  "coding-agent"
37
38
  ],
38
39
  "license": "MIT",