tokenmix 0.2.1 → 0.2.4

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Zero-config CLI to use any open-source coding agent with [TokenMix](https://tokenmix.ai) as the unified LLM backend.
4
4
 
5
- One account, one balance, 75+ models routed automatically across Claude / GPT / Gemini / DeepSeek / Qwen / Moonshot / ...
5
+ One account, one balance, 160+ models routed automatically across Claude / GPT / Gemini / DeepSeek / Qwen / Moonshot / ...
6
6
 
7
7
  ## Quick Start
8
8
 
@@ -37,7 +37,7 @@ npx tokenmix login --key sk-tm-... # supply API key directly (for CI
37
37
 
38
38
  ```
39
39
  tokenmix login [--key sk-tm-xxx] Log in
40
- tokenmix logout Remove credentials
40
+ tokenmix logout Remove credentials (and revert injected agent config)
41
41
  tokenmix balance Open dashboard to view balance
42
42
  tokenmix topup Open browser to top up
43
43
  tokenmix models [--type chat] List available models with prices
@@ -4,15 +4,17 @@ async function installCheck() {
4
4
  const bin = await commandExists(AIDER_BIN);
5
5
  if (!bin) {
6
6
  const py = (await commandExists('python3')) || (await commandExists('python'));
7
+ const pipx = await commandExists('pipx');
7
8
  if (!py) {
8
9
  return {
9
10
  installed: false,
10
- hint: 'Aider requires Python 3. Install Python first, then `pipx install aider-chat`.',
11
+ hint: 'Aider requires Python 3. Install Python 3 from https://python.org/downloads, then come back and run `tokenmix aider` again.',
11
12
  };
12
13
  }
14
+ const installCmd = pipx ? 'pipx install aider-chat' : 'pip install aider-chat';
13
15
  return {
14
16
  installed: false,
15
- hint: 'Run `pipx install aider-chat` (preferred) or `pip install aider-chat` to install Aider.',
17
+ hint: `Aider is not installed. Run this in another terminal:\n ${installCmd}\nThen come back and run \`tokenmix aider\` again your TokenMix login is already saved, so it will pick up automatically.`,
16
18
  };
17
19
  }
18
20
  try {
@@ -38,10 +40,31 @@ async function configure(apiKey, baseUrl, defaultModel) {
38
40
  ],
39
41
  };
40
42
  }
43
+ // Aider lets you pick a model with --model OR one of its built-in alias flags
44
+ // (--sonnet, --opus, ...). If the user used any of them, we must not inject our
45
+ // own --model on top, which would be a conflicting second model specifier.
46
+ const AIDER_MODEL_ALIAS_FLAGS = new Set([
47
+ '--sonnet',
48
+ '--opus',
49
+ '--haiku',
50
+ '--4o',
51
+ '--4',
52
+ '--mini',
53
+ '--35turbo',
54
+ '--deepseek',
55
+ '--o1',
56
+ '--o1-mini',
57
+ '--o3',
58
+ '--o3-mini',
59
+ '--gemini',
60
+ '--gemini-exp',
61
+ ]);
62
+ export function userSelectedModel(args) {
63
+ return args.some((a) => a === '--model' || a.startsWith('--model=') || AIDER_MODEL_ALIAS_FLAGS.has(a));
64
+ }
41
65
  async function launch(args, env) {
42
- // Inject --model only if user didn't supply one.
43
- const hasModel = args.some((a) => a === '--model' || a.startsWith('--model='));
44
- const finalArgs = hasModel
66
+ // Inject our default --model only if the user didn't already pick a model.
67
+ const finalArgs = userSelectedModel(args)
45
68
  ? args
46
69
  : ['--model', `openai/${env.TOKENMIX_DEFAULT_MODEL ?? 'claude-sonnet-4.6'}`, ...args];
47
70
  await run(AIDER_BIN, finalArgs, { env });
@@ -1 +1 @@
1
- {"version":3,"file":"aider.js","sourceRoot":"","sources":["../../src/agents/aider.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAEjE,MAAM,SAAS,GAAG,OAAO,CAAA;AAEzB,KAAK,UAAU,YAAY;IACzB,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAA;IAC1C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,EAAE,GAAG,CAAC,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAA;QAC9E,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,OAAO;gBACL,SAAS,EAAE,KAAK;gBAChB,IAAI,EAAE,gFAAgF;aACvF,CAAA;QACH,CAAC;QACD,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,yFAAyF;SAChG,CAAA;IACH,CAAC;IACD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,UAAU,CAAC,SAAS,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;QACpD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAA;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;IAC5B,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,MAAc,EACd,OAAe,EACf,YAAoB;IAEpB,4EAA4E;IAC5E,sFAAsF;IACtF,OAAO;QACL,OAAO,EAAE;YACP,cAAc,EAAE,MAAM;YACtB,eAAe,EAAE,GAAG,OAAO,KAAK;YAChC,sBAAsB,EAAE,YAAY;SACrC;QACD,KAAK,EAAE;YACL,yDAAyD;YACzD,yBAAyB,YAAY,2BAA2B;SACjE;KACF,CAAA;AACH,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAc,EAAE,GAA2B;IAC/D,iDAAiD;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAA;IAC9E,MAAM,SAAS,GAAG,QAAQ;QACxB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,SAAS,EAAE,UAAU,GAAG,CAAC,sBAAsB,IAAI,mBAAmB,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;IACvF,MAAM,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;AAC1C,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAoB;IACzC,EAAE,EAAE,OAAO;IACX,WAAW,EAAE,OAAO;IACpB,WAAW,EAAE,2DAA2D;IACxE,WAAW,EAAE,UAAU;IACvB,YAAY;IACZ,SAAS;IACT,MAAM;CACP,CAAA"}
1
+ {"version":3,"file":"aider.js","sourceRoot":"","sources":["../../src/agents/aider.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,14 @@ async function configure(apiKey, baseUrl, _defaultModel) {
38
38
  // first run
39
39
  }
40
40
  const existingEnv = existing.env || {};
41
+ // Detect that we're about to overwrite a user's OWN (non-tokenmix) Anthropic
42
+ // setup — e.g. a Claude Pro/Max OAuth or a personal sk-ant- key. We still
43
+ // proceed (they explicitly asked to use Claude Code via TokenMix), but warn
44
+ // so it isn't a silent hijack of their primary tool.
45
+ const prevKey = existingEnv.ANTHROPIC_API_KEY;
46
+ const prevBase = existingEnv.ANTHROPIC_BASE_URL;
47
+ const replacingForeign = (typeof prevKey === 'string' && prevKey.length > 0 && !prevKey.startsWith('sk-tm-')) ||
48
+ (typeof prevBase === 'string' && prevBase.length > 0 && !/tokenmix/i.test(prevBase));
41
49
  const next = {
42
50
  ...existing,
43
51
  env: {
@@ -54,21 +62,67 @@ async function configure(apiKey, baseUrl, _defaultModel) {
54
62
  catch {
55
63
  // ignore
56
64
  }
65
+ const notes = [
66
+ 'Available Claude models via tokenmix: claude-opus-4.7, claude-sonnet-4.6, claude-haiku-4.5',
67
+ 'Run `tokenmix models --type chat` for the full list.',
68
+ ];
69
+ if (replacingForeign) {
70
+ notes.unshift('⚠ Replaced your existing Anthropic settings in ~/.claude/settings.json.', ' `tokenmix logout` removes TokenMix\'s entries (your old key cannot be auto-restored).', '');
71
+ }
57
72
  return {
58
73
  configPath: settingsPath,
59
74
  envVars: {
60
75
  ANTHROPIC_BASE_URL: baseUrl,
61
76
  ANTHROPIC_API_KEY: apiKey,
62
77
  },
63
- notes: [
64
- 'Available Claude models via tokenmix: claude-opus-4.7, claude-sonnet-4.6, claude-haiku-4.5',
65
- 'Run `tokenmix models --type chat` for the full list.',
66
- ],
78
+ notes,
67
79
  };
68
80
  }
69
81
  async function launch(args, env) {
70
82
  await run(CLAUDE_BIN, args, { env });
71
83
  }
84
+ // Remove the ANTHROPIC_* env we injected, leaving everything else in
85
+ // settings.json untouched. Only acts when the config looks like ours (tokenmix
86
+ // key or base URL) so we never clobber a user's own Anthropic credentials.
87
+ async function cleanup() {
88
+ const settingsPath = path.join(os.homedir(), '.claude', 'settings.json');
89
+ let existing;
90
+ try {
91
+ existing = JSON.parse(await fs.readFile(settingsPath, 'utf-8'));
92
+ }
93
+ catch {
94
+ return { reverted: false };
95
+ }
96
+ const env = existing.env;
97
+ if (!env || typeof env !== 'object') {
98
+ return { reverted: false, configPath: settingsPath };
99
+ }
100
+ const key = env.ANTHROPIC_API_KEY;
101
+ const base = env.ANTHROPIC_BASE_URL;
102
+ const ours = (typeof key === 'string' && key.startsWith('sk-tm-')) ||
103
+ (typeof base === 'string' && /tokenmix/i.test(base));
104
+ if (!ours) {
105
+ return { reverted: false, configPath: settingsPath };
106
+ }
107
+ delete env.ANTHROPIC_API_KEY;
108
+ delete env.ANTHROPIC_BASE_URL;
109
+ if (Object.keys(env).length === 0)
110
+ delete existing.env;
111
+ else
112
+ existing.env = env;
113
+ await fs.writeFile(settingsPath, JSON.stringify(existing, null, 2));
114
+ try {
115
+ await fs.chmod(settingsPath, 0o600);
116
+ }
117
+ catch {
118
+ // ignore
119
+ }
120
+ return {
121
+ reverted: true,
122
+ configPath: settingsPath,
123
+ note: 'If you had your own ANTHROPIC_API_KEY here before, re-add it.',
124
+ };
125
+ }
72
126
  export const ClaudeCodeAgent = {
73
127
  id: 'claude',
74
128
  displayName: 'Claude Code',
@@ -78,5 +132,6 @@ export const ClaudeCodeAgent = {
78
132
  install,
79
133
  configure,
80
134
  launch,
135
+ cleanup,
81
136
  };
82
137
  //# sourceMappingURL=claude.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,15 @@
1
1
  import { commandExists } from '../utils/exec.js';
2
2
  async function installCheck() {
3
+ // Kilo Code is a config-only agent (VSCode extension). The CLI cannot install
4
+ // the extension on the user's behalf, so we always proceed to `configure()` and
5
+ // print the snippet — even if VSCode isn't installed locally yet, the user
6
+ // may be copying the config for another machine.
3
7
  const code = await commandExists('code');
4
- if (!code) {
5
- return {
6
- installed: false,
7
- hint: 'Kilo Code is a VSCode extension. Install VSCode first, then install "Kilo Code" from the marketplace.',
8
- };
9
- }
10
8
  return {
11
9
  installed: true,
12
- hint: 'If you have not installed the Kilo Code extension yet, search "Kilo Code" in the VSCode marketplace.',
10
+ hint: code
11
+ ? 'Install "Kilo Code" from the VSCode marketplace, then paste the snippet below into its settings.'
12
+ : 'VSCode not detected on PATH. Install VSCode, then add the Kilo Code extension, then use the snippet below.',
13
13
  };
14
14
  }
15
15
  async function configure(apiKey, baseUrl, defaultModel) {
@@ -33,6 +33,8 @@ async function configure(apiKey, baseUrl, defaultModel) {
33
33
  openAiApiKey: apiKey,
34
34
  defaultModelId: defaultModel,
35
35
  }, null, 2),
36
+ '',
37
+ 'Keep this API key private — anyone with it can spend your TokenMix balance.',
36
38
  ],
37
39
  };
38
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"kilo.js","sourceRoot":"","sources":["../../src/agents/kilo.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAEhD,KAAK,UAAU,YAAY;IACzB,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAA;IACxC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,uGAAuG;SAC9G,CAAA;IACH,CAAC;IACD,OAAO;QACL,SAAS,EAAE,IAAI;QACf,IAAI,EAAE,sGAAsG;KAC7G,CAAA;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,MAAc,EACd,OAAe,EACf,YAAoB;IAEpB,6DAA6D;IAC7D,8EAA8E;IAC9E,OAAO;QACL,KAAK,EAAE;YACL,mEAAmE;YACnE,yCAAyC;YACzC,EAAE;YACF,oCAAoC;YACpC,oBAAoB,OAAO,KAAK;YAChC,oBAAoB,MAAM,EAAE;YAC5B,oBAAoB,YAAY,EAAE;YAClC,EAAE;YACF,mFAAmF;YACnF,EAAE;YACF,IAAI,CAAC,SAAS,CACZ;gBACE,QAAQ,EAAE,mBAAmB;gBAC7B,aAAa,EAAE,GAAG,OAAO,KAAK;gBAC9B,YAAY,EAAE,MAAM;gBACpB,cAAc,EAAE,YAAY;aAC7B,EACD,IAAI,EACJ,CAAC,CACF;SACF;KACF,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAoB;IACxC,EAAE,EAAE,MAAM;IACV,WAAW,EAAE,WAAW;IACxB,WAAW,EAAE,oDAAoD;IACjE,WAAW,EAAE,eAAe;IAC5B,YAAY;IACZ,SAAS;CACV,CAAA"}
1
+ {"version":3,"file":"kilo.js","sourceRoot":"","sources":["../../src/agents/kilo.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAEhD,KAAK,UAAU,YAAY;IACzB,8EAA8E;IAC9E,gFAAgF;IAChF,2EAA2E;IAC3E,iDAAiD;IACjD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAA;IACxC,OAAO;QACL,SAAS,EAAE,IAAI;QACf,IAAI,EAAE,IAAI;YACR,CAAC,CAAC,kGAAkG;YACpG,CAAC,CAAC,4GAA4G;KACjH,CAAA;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,MAAc,EACd,OAAe,EACf,YAAoB;IAEpB,6DAA6D;IAC7D,8EAA8E;IAC9E,OAAO;QACL,KAAK,EAAE;YACL,mEAAmE;YACnE,yCAAyC;YACzC,EAAE;YACF,oCAAoC;YACpC,oBAAoB,OAAO,KAAK;YAChC,oBAAoB,MAAM,EAAE;YAC5B,oBAAoB,YAAY,EAAE;YAClC,EAAE;YACF,mFAAmF;YACnF,EAAE;YACF,IAAI,CAAC,SAAS,CACZ;gBACE,QAAQ,EAAE,mBAAmB;gBAC7B,aAAa,EAAE,GAAG,OAAO,KAAK;gBAC9B,YAAY,EAAE,MAAM;gBACpB,cAAc,EAAE,YAAY;aAC7B,EACD,IAAI,EACJ,CAAC,CACF;YACD,EAAE;YACF,6EAA6E;SAC9E;KACF,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAoB;IACxC,EAAE,EAAE,MAAM;IACV,WAAW,EAAE,WAAW;IACxB,WAAW,EAAE,oDAAoD;IACjE,WAAW,EAAE,eAAe;IAC5B,YAAY;IACZ,SAAS;CACV,CAAA"}
@@ -78,6 +78,34 @@ async function configure(apiKey, baseUrl, defaultModel) {
78
78
  async function launch(args) {
79
79
  await run(OPENCODE_BIN, args);
80
80
  }
81
+ // Remove the tokenmix provider (and our default model pin) from opencode.json,
82
+ // preserving any other providers or a user-chosen model.
83
+ async function cleanup() {
84
+ const filePath = configPath();
85
+ let existing;
86
+ try {
87
+ existing = JSON.parse(await fs.readFile(filePath, 'utf-8'));
88
+ }
89
+ catch {
90
+ return { reverted: false };
91
+ }
92
+ let changed = false;
93
+ const provider = existing.provider;
94
+ if (provider && 'tokenmix' in provider) {
95
+ delete provider.tokenmix;
96
+ changed = true;
97
+ if (Object.keys(provider).length === 0)
98
+ delete existing.provider;
99
+ }
100
+ if (typeof existing.model === 'string' && existing.model.startsWith('tokenmix/')) {
101
+ delete existing.model;
102
+ changed = true;
103
+ }
104
+ if (!changed)
105
+ return { reverted: false, configPath: filePath };
106
+ await fs.writeFile(filePath, JSON.stringify(existing, null, 2));
107
+ return { reverted: true, configPath: filePath };
108
+ }
81
109
  export const OpenCodeAgent = {
82
110
  id: 'opencode',
83
111
  displayName: 'OpenCode',
@@ -87,5 +115,6 @@ export const OpenCodeAgent = {
87
115
  install,
88
116
  configure,
89
117
  launch,
118
+ cleanup,
90
119
  };
91
120
  //# sourceMappingURL=opencode.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/agents/opencode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,MAAM,UAAU,CAAA;AAMzB,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAEjE,MAAM,YAAY,GAAG,UAAU,CAAA;AAC/B,MAAM,oBAAoB,GAAG,aAAa,CAAA;AAE1C,6DAA6D;AAC7D,sDAAsD;AACtD,qBAAqB;AACrB,8BAA8B;AAC9B,sCAAsC;AACtC,SAAS,UAAU;IACjB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAA;IACjF,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC,CAAA;AACxD,CAAC;AAED,KAAK,UAAU,YAAY;IACzB,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC,CAAA;IAC7C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,oCAAoC,oBAAoB,EAAE;SACjE,CAAA;IACH,CAAC;IACD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,UAAU,CAAC,YAAY,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;QACvD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAA;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;IAC5B,CAAC;AACH,CAAC;AAED,KAAK,UAAU,OAAO;IACpB,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAA;AAC3D,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,MAAc,EACd,OAAe,EACf,YAAoB;IAEpB,MAAM,QAAQ,GAAG,UAAU,EAAE,CAAA;IAC7B,IAAI,QAAQ,GAA4B,EAAE,CAAA;IAC1C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QAChD,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;IAED,sDAAsD;IACtD,+EAA+E;IAC/E,MAAM,gBAAgB,GAAG;QACvB,GAAG,EAAE,2BAA2B;QAChC,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE;YACP,OAAO,EAAE,GAAG,OAAO,KAAK;YACxB,MAAM;SACP;QACD,sFAAsF;QACtF,MAAM,EAAE;YACN,CAAC,YAAY,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE;SACvC;KACF,CAAA;IAED,MAAM,gBAAgB,GAAI,QAAQ,CAAC,QAAoC,IAAI,EAAE,CAAA;IAE7E,MAAM,IAAI,GAAG;QACX,GAAG,QAAQ;QACX,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,YAAY,YAAY,EAAE;QACnD,QAAQ,EAAE;YACR,GAAG,gBAAgB;YACnB,QAAQ,EAAE,gBAAgB;SAC3B;KACF,CAAA;IAED,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC1C,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAE3D,OAAO;QACL,UAAU,EAAE,QAAQ;QACpB,KAAK,EAAE;YACL,iCAAiC,YAAY,EAAE;YAC/C,gFAAgF;SACjF;KACF,CAAA;AACH,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAc;IAClC,MAAM,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAoB;IAC5C,EAAE,EAAE,UAAU;IACd,WAAW,EAAE,UAAU;IACvB,WAAW,EAAE,kEAAkE;IAC/E,WAAW,EAAE,UAAU;IACvB,YAAY;IACZ,OAAO;IACP,SAAS;IACT,MAAM;CACP,CAAA"}
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/agents/opencode.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import { readConfig, apiBaseUrl } from '../config/store.js';
2
+ import { readConfig, apiBaseUrl, DEFAULT_API_BASE } from '../config/store.js';
3
3
  export class ApiError extends Error {
4
4
  status;
5
5
  constructor(status, message) {
@@ -7,7 +7,7 @@ export class ApiError extends Error {
7
7
  this.status = status;
8
8
  }
9
9
  }
10
- function unwrap(resp) {
10
+ export function unwrap(resp) {
11
11
  const body = resp.data;
12
12
  if (body && typeof body.code === 'number' && body.code !== 0) {
13
13
  throw new ApiError(0, body.message || 'API error');
@@ -22,7 +22,7 @@ function handleAxios(err) {
22
22
  e.message;
23
23
  throw new ApiError(e.response.status, msg);
24
24
  }
25
- throw new ApiError(0, e.message || 'network error');
25
+ throw new ApiError(0, `Could not reach the TokenMix API (${e.message || 'network error'}). Check your internet connection.`);
26
26
  }
27
27
  // Public endpoint, no auth required.
28
28
  // Note: backend pagination uses `per_page` (NOT `page_size`); max 500 (anything >500 falls back to 20).
@@ -45,7 +45,7 @@ export async function listPublicModels(cfg) {
45
45
  // A 200 implies the key is valid and not revoked/expired/over-quota.
46
46
  export async function verifyApiKey(apiKey, baseUrl) {
47
47
  try {
48
- const r = await axios.get(`${baseUrl || 'https://api.tokenmix.ai'}/v1/models`, {
48
+ const r = await axios.get(`${baseUrl || DEFAULT_API_BASE}/v1/models`, {
49
49
  headers: { Authorization: `Bearer ${apiKey}` },
50
50
  timeout: 15000,
51
51
  });
@@ -71,12 +71,18 @@ export async function startDeviceAuthorization(baseUrl, clientName = 'tokenmix-c
71
71
  handleAxios(err);
72
72
  }
73
73
  }
74
+ // RFC 8628 defaults, used when the server omits these fields — and to guard
75
+ // against a missing/0/NaN interval that would otherwise busy-loop, or a missing
76
+ // expires_in that would make the loop time out immediately.
77
+ const DEFAULT_POLL_INTERVAL_S = 5;
78
+ const DEFAULT_EXPIRES_IN_S = 900;
74
79
  // Poll until approved, denied, or expired. Returns the API key when approved.
75
80
  // Throws DeviceFlowError with code ∈ {expired_token, access_denied, api_key_limit_reached, timeout} on terminal failures.
76
81
  // onTick is called once per polling iteration with the seconds remaining (for progress display).
77
82
  export async function pollDeviceToken(baseUrl, auth, onTick) {
78
- let intervalMs = Math.max(1, auth.interval) * 1000;
79
- const deadline = Date.now() + auth.expires_in * 1000;
83
+ let intervalMs = Math.max(1, Number(auth.interval) || DEFAULT_POLL_INTERVAL_S) * 1000;
84
+ const expiresIn = Number(auth.expires_in) > 0 ? Number(auth.expires_in) : DEFAULT_EXPIRES_IN_S;
85
+ const deadline = Date.now() + expiresIn * 1000;
80
86
  while (Date.now() < deadline) {
81
87
  await new Promise((r) => setTimeout(r, intervalMs));
82
88
  if (onTick) {
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -1,54 +1,5 @@
1
- import { createRequire } from 'node:module';
2
- import { Command } from 'commander';
3
- import { loginCommand } from './commands/login.js';
4
- import { logoutCommand } from './commands/logout.js';
5
- import { balanceCommand } from './commands/balance.js';
6
- import { topupCommand } from './commands/topup.js';
7
- import { modelsCommand } from './commands/models.js';
8
- import { listCommand } from './commands/list.js';
9
- import { doctorCommand } from './commands/doctor.js';
10
- import { registerAgentCommands } from './commands/agent-runner.js';
11
- // Read version from package.json so we never have to bump it in two places.
12
- const pkg = createRequire(import.meta.url)('../package.json');
13
- const program = new Command();
14
- program
15
- .name('tokenmix')
16
- .description('Zero-config CLI to use any open-source coding agent with TokenMix as the unified LLM backend.')
17
- .version(pkg.version);
18
- program
19
- .command('login')
20
- .description('Log in to TokenMix (default: browser device authorization)')
21
- .option('-k, --key <apiKey>', 'Paste an API key directly (skip browser flow, useful in CI)')
22
- .option('-p, --paste', 'Force interactive paste prompt instead of browser flow')
23
- .option('-u, --url <baseUrl>', 'Override API base URL (default: https://api.tokenmix.ai)')
24
- .action(loginCommand);
25
- program
26
- .command('logout')
27
- .description('Remove stored credentials from this machine')
28
- .action(logoutCommand);
29
- program
30
- .command('balance')
31
- .description('Open the dashboard to view your balance')
32
- .action(balanceCommand);
33
- program
34
- .command('topup')
35
- .description('Open the browser to top up your account')
36
- .action(topupCommand);
37
- program
38
- .command('models')
39
- .description('List available models with prices')
40
- .option('-t, --type <type>', 'Filter by type: chat | embedding | image | audio | video')
41
- .action(modelsCommand);
42
- program
43
- .command('list')
44
- .description('List supported coding agents')
45
- .action(listCommand);
46
- program
47
- .command('doctor')
48
- .description('Diagnose CLI configuration and agent installation')
49
- .action(doctorCommand);
50
- // Register one subcommand per supported agent (opencode, claude, aider, kilo, ...).
51
- registerAgentCommands(program);
1
+ import { buildProgram } from './program.js';
2
+ const program = buildProgram();
52
3
  program.parseAsync(process.argv).catch((err) => {
53
4
  const e = err;
54
5
  console.error(e?.message ?? err);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAElE,4EAA4E;AAC5E,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAwB,CAAA;AAEpF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,+FAA+F,CAAC;KAC5G,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;AAEvB,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,4DAA4D,CAAC;KACzE,MAAM,CAAC,oBAAoB,EAAE,6DAA6D,CAAC;KAC3F,MAAM,CAAC,aAAa,EAAE,wDAAwD,CAAC;KAC/E,MAAM,CAAC,qBAAqB,EAAE,0DAA0D,CAAC;KACzF,MAAM,CAAC,YAAY,CAAC,CAAA;AAEvB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,aAAa,CAAC,CAAA;AAExB,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,cAAc,CAAC,CAAA;AAEzB,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,YAAY,CAAC,CAAA;AAEvB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,mCAAmC,CAAC;KAChD,MAAM,CAAC,mBAAmB,EAAE,0DAA0D,CAAC;KACvF,MAAM,CAAC,aAAa,CAAC,CAAA;AAExB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,8BAA8B,CAAC;KAC3C,MAAM,CAAC,WAAW,CAAC,CAAA;AAEtB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,mDAAmD,CAAC;KAChE,MAAM,CAAC,aAAa,CAAC,CAAA;AAExB,oFAAoF;AACpF,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAE9B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtD,MAAM,CAAC,GAAG,GAA2B,CAAA;IACrC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,IAAI,GAAG,CAAC,CAAA;IAChC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,MAAM,OAAO,GAAG,YAAY,EAAE,CAAA;AAE9B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtD,MAAM,CAAC,GAAG,GAA2B,CAAA;IACrC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,IAAI,GAAG,CAAC,CAAA;IAChC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
@@ -3,7 +3,26 @@ import { readConfig, apiBaseUrl } from '../config/store.js';
3
3
  import { confirm } from '../utils/prompt.js';
4
4
  import { AGENTS } from '../agents/registry.js';
5
5
  const DEFAULT_MODEL = 'claude-sonnet-4.6';
6
- export function registerAgentCommands(program) {
6
+ // Flags that are pure information requests meant for the underlying agent binary.
7
+ // For these we must NOT rewrite global config or require login — just forward them.
8
+ const INFO_ONLY_FLAGS = new Set(['--version', '-V', '--help', '-h']);
9
+ export function isInfoOnlyInvocation(args) {
10
+ return args.length > 0 && args.every((a) => INFO_ONLY_FLAGS.has(a));
11
+ }
12
+ // Forward to the agent binary, mirroring its exit code; re-throw non-exec errors.
13
+ async function launchOrExit(launch, args, env) {
14
+ try {
15
+ await launch(args, env);
16
+ }
17
+ catch (err) {
18
+ const e = err;
19
+ if (typeof e.exitCode === 'number' && e.exitCode !== 0) {
20
+ process.exit(e.exitCode);
21
+ }
22
+ throw err;
23
+ }
24
+ }
25
+ export function registerAgentCommands(program, runner = runAgent) {
7
26
  for (const agent of AGENTS) {
8
27
  if (agent.registerCommand) {
9
28
  agent.registerCommand(program);
@@ -13,12 +32,24 @@ export function registerAgentCommands(program) {
13
32
  .command(`${agent.id} [args...]`)
14
33
  .description(`Configure and launch ${agent.displayName} via TokenMix`)
15
34
  .allowUnknownOption(true)
35
+ .passThroughOptions(true) // forward --version / --help / --any to the underlying agent
16
36
  .action(async (args = []) => {
17
- await runAgent(agent, args);
37
+ await runner(agent, args);
18
38
  });
19
39
  }
20
40
  }
21
- async function runAgent(agent, args) {
41
+ export async function runAgent(agent, args) {
42
+ // `tokenmix <agent> --version|--help`: forward straight to the binary without
43
+ // rewriting global config or requiring login — a query must not have side effects.
44
+ if (agent.launch && isInfoOnlyInvocation(args)) {
45
+ const status = await agent.installCheck();
46
+ if (!status.installed) {
47
+ logger.warn(status.hint || `${agent.displayName} is not installed.`);
48
+ process.exit(1);
49
+ }
50
+ await launchOrExit(agent.launch, args, {});
51
+ return;
52
+ }
22
53
  const cfg = await readConfig();
23
54
  if (!cfg.apiKey) {
24
55
  logger.error('Not logged in. Run `tokenmix login` first.');
@@ -37,7 +68,21 @@ async function runAgent(agent, args) {
37
68
  process.exit(1);
38
69
  }
39
70
  logger.step(`Installing ${agent.displayName} ...`);
40
- await agent.install();
71
+ try {
72
+ await agent.install();
73
+ }
74
+ catch {
75
+ // The most common global-install failure worldwide is npm lacking
76
+ // permission to write to the global prefix. Give actionable guidance
77
+ // instead of dumping execa's raw error.
78
+ logger.error(`Could not install ${agent.displayName} automatically.`);
79
+ logger.info('This usually means npm cannot write to its global folder. Options:');
80
+ logger.info(' • Use a Node version manager (nvm / fnm / volta) — then global installs need no sudo, or');
81
+ if (status.hint)
82
+ logger.info(` • Install it yourself: ${status.hint.replace(/^Will install via:\s*/, '')}`);
83
+ logger.info('Then re-run this command — your TokenMix login is already saved.');
84
+ process.exit(1);
85
+ }
41
86
  logger.success(`${agent.displayName} installed.`);
42
87
  }
43
88
  else {
@@ -70,15 +115,6 @@ async function runAgent(agent, args) {
70
115
  ...(result.envVars ?? {}),
71
116
  TOKENMIX_DEFAULT_MODEL: defaultModel,
72
117
  };
73
- try {
74
- await agent.launch(args, env);
75
- }
76
- catch (err) {
77
- const e = err;
78
- if (typeof e.exitCode === 'number' && e.exitCode !== 0) {
79
- process.exit(e.exitCode);
80
- }
81
- throw err;
82
- }
118
+ await launchOrExit(agent.launch, args, env);
83
119
  }
84
120
  //# sourceMappingURL=agent-runner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-runner.js","sourceRoot":"","sources":["../../src/commands/agent-runner.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAG9C,MAAM,aAAa,GAAG,mBAAmB,CAAA;AAOzC,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;YAC1B,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;YAC9B,SAAQ;QACV,CAAC;QACD,OAAO;aACJ,OAAO,CAAC,GAAG,KAAK,CAAC,EAAE,YAAY,CAAC;aAChC,WAAW,CAAC,wBAAwB,KAAK,CAAC,WAAW,eAAe,CAAC;aACrE,kBAAkB,CAAC,IAAI,CAAC;aACxB,MAAM,CAAC,KAAK,EAAE,OAAiB,EAAE,EAAE,EAAE;YACpC,MAAM,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QAC7B,CAAC,CAAC,CAAA;IACN,CAAC;AACH,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,KAAsB,EAAE,IAAc;IAC5D,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAA;IAC9B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAA;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,CAAA;IAC/B,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,IAAI,aAAa,CAAA;IAEtD,2BAA2B;IAC3B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,YAAY,EAAE,CAAA;IACzC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,aAAa,GAAG,MAAM,OAAO,CACjC,GAAG,KAAK,CAAC,WAAW,iCAAiC,EACrD,IAAI,CACL,CAAA;YACD,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,IAAI,MAAM,CAAC,IAAI;oBAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;gBACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,WAAW,MAAM,CAAC,CAAA;YAClD,MAAM,KAAK,CAAC,OAAO,EAAE,CAAA;YACrB,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,WAAW,aAAa,CAAC,CAAA;QACnD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,KAAK,CAAC,WAAW,mCAAmC,CAAC,CAAA;YACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,MAAM,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,WAAW,MAAM,CAAC,CAAA;IACnD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;IACvE,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,CAAC,OAAO,CAAC,SAAS,MAAM,CAAC,UAAU,EAAE,CAAC,CAAA;IAC9C,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAChC,IAAI,IAAI,KAAK,EAAE;gBAAE,OAAO,CAAC,GAAG,EAAE,CAAA;;gBACzB,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;QAC/B,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAA;IACf,CAAC;IAED,wDAAwD;IACxD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,WAAW,uBAAuB,CAAC,CAAA;QACxD,OAAM;IACR,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,WAAW,MAAM,CAAC,CAAA;IACjD,MAAM,GAAG,GAA2B;QAClC,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;QACzB,sBAAsB,EAAE,YAAY;KACrC,CAAA;IACD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC/B,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAAqB,CAAA;QAC/B,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;QAC1B,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"agent-runner.js","sourceRoot":"","sources":["../../src/commands/agent-runner.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { logger } from '../utils/logger.js';
2
- import { openInBrowser } from '../utils/browser.js';
2
+ import { openOrHint } from '../utils/browser.js';
3
3
  import { readConfig } from '../config/store.js';
4
4
  // v0.1: balance lookup over API requires a user JWT, which we do not yet have
5
5
  // (the CLI uses an API Key today). We open the dashboard instead.
@@ -12,6 +12,6 @@ export async function balanceCommand() {
12
12
  process.exit(1);
13
13
  }
14
14
  logger.step(`Opening dashboard to view balance: ${DASHBOARD_URL}`);
15
- await openInBrowser(DASHBOARD_URL);
15
+ await openOrHint(DASHBOARD_URL);
16
16
  }
17
17
  //# sourceMappingURL=balance.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"balance.js","sourceRoot":"","sources":["../../src/commands/balance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAE/C,8EAA8E;AAC9E,kEAAkE;AAClE,4FAA4F;AAC5F,MAAM,aAAa,GAAG,+BAA+B,CAAA;AAErD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAA;IAC9B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAA;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,sCAAsC,aAAa,EAAE,CAAC,CAAA;IAClE,MAAM,aAAa,CAAC,aAAa,CAAC,CAAA;AACpC,CAAC"}
1
+ {"version":3,"file":"balance.js","sourceRoot":"","sources":["../../src/commands/balance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAE/C,8EAA8E;AAC9E,kEAAkE;AAClE,4FAA4F;AAC5F,MAAM,aAAa,GAAG,+BAA+B,CAAA;AAErD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAA;IAC9B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAA;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,sCAAsC,aAAa,EAAE,CAAC,CAAA;IAClE,MAAM,UAAU,CAAC,aAAa,CAAC,CAAA;AACjC,CAAC"}
@@ -55,6 +55,9 @@ async function loginByDeviceFlow(baseUrl) {
55
55
  await loginByKey(entered, baseUrl);
56
56
  return;
57
57
  }
58
+ // verification_uri_complete is optional per RFC 8628; fall back to the plain
59
+ // verification_uri (the user_code is shown separately just below either way).
60
+ const verifyUrl = auth.verification_uri_complete || auth.verification_uri;
58
61
  // Display user_code prominently
59
62
  console.log();
60
63
  console.log(' ' + chalk.dim('Open the link below and confirm this code:'));
@@ -62,11 +65,11 @@ async function loginByDeviceFlow(baseUrl) {
62
65
  console.log(' ' + chalk.bold.cyan(auth.user_code));
63
66
  console.log();
64
67
  console.log(' ' + chalk.dim('Link:'));
65
- console.log(' ' + chalk.underline(auth.verification_uri_complete));
68
+ console.log(' ' + chalk.underline(verifyUrl));
66
69
  console.log();
67
70
  // Try to open browser, but proceed even if it fails (headless / SSH)
68
71
  try {
69
- await openInBrowser(auth.verification_uri_complete);
72
+ await openInBrowser(verifyUrl);
70
73
  logger.dim(' (browser opened; if nothing happens, copy the link above)');
71
74
  }
72
75
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,26 @@
1
1
  import { logger } from '../utils/logger.js';
2
2
  import { clearConfig } from '../config/store.js';
3
+ import { AGENTS } from '../agents/registry.js';
3
4
  export async function logoutCommand() {
4
5
  await clearConfig();
5
6
  logger.success('Logged out. Credentials removed from this machine.');
7
+ // Also revert the config we injected into agents, so they stop routing through
8
+ // TokenMix with a key that's about to be gone. Best-effort and precise — each
9
+ // agent only removes what it recognizes as its own tokenmix config.
10
+ for (const agent of AGENTS) {
11
+ if (!agent.cleanup)
12
+ continue;
13
+ try {
14
+ const r = await agent.cleanup();
15
+ if (r.reverted) {
16
+ logger.success(`Reverted ${agent.displayName} config${r.configPath ? ` (${r.configPath})` : ''}`);
17
+ if (r.note)
18
+ logger.dim(` ${r.note}`);
19
+ }
20
+ }
21
+ catch {
22
+ // never block logout on agent cleanup
23
+ }
24
+ }
6
25
  }
7
26
  //# sourceMappingURL=logout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,WAAW,EAAE,CAAA;IACnB,MAAM,CAAC,OAAO,CAAC,oDAAoD,CAAC,CAAA;AACtE,CAAC"}
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAE9C,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,WAAW,EAAE,CAAA;IACnB,MAAM,CAAC,OAAO,CAAC,oDAAoD,CAAC,CAAA;IAEpE,+EAA+E;IAC/E,8EAA8E;IAC9E,oEAAoE;IACpE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,SAAQ;QAC5B,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAA;YAC/B,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;gBACf,MAAM,CAAC,OAAO,CAAC,YAAY,KAAK,CAAC,WAAW,UAAU,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;gBACjG,IAAI,CAAC,CAAC,IAAI;oBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;YACvC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,sCAAsC;QACxC,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -1,8 +1,8 @@
1
1
  import { logger } from '../utils/logger.js';
2
- import { openInBrowser } from '../utils/browser.js';
2
+ import { openOrHint } from '../utils/browser.js';
3
3
  const TOPUP_URL = 'https://tokenmix.ai/dashboard/credits';
4
4
  export async function topupCommand() {
5
5
  logger.step(`Opening top-up page: ${TOPUP_URL}`);
6
- await openInBrowser(TOPUP_URL);
6
+ await openOrHint(TOPUP_URL);
7
7
  }
8
8
  //# sourceMappingURL=topup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"topup.js","sourceRoot":"","sources":["../../src/commands/topup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAEnD,MAAM,SAAS,GAAG,uCAAuC,CAAA;AAEzD,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,CAAC,IAAI,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAA;IAChD,MAAM,aAAa,CAAC,SAAS,CAAC,CAAA;AAChC,CAAC"}
1
+ {"version":3,"file":"topup.js","sourceRoot":"","sources":["../../src/commands/topup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEhD,MAAM,SAAS,GAAG,uCAAuC,CAAA;AAEzD,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,CAAC,IAAI,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAA;IAChD,MAAM,UAAU,CAAC,SAAS,CAAC,CAAA;AAC7B,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import fs from 'fs-extra';
2
2
  import { configDir, configFile } from './paths.js';
3
- const DEFAULT_API_BASE = 'https://api.tokenmix.ai';
3
+ export const DEFAULT_API_BASE = 'https://api.tokenmix.ai';
4
4
  export async function readConfig() {
5
5
  try {
6
6
  const raw = await fs.readFile(configFile(), 'utf-8');
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/config/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAA;AACzB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAUlD,MAAM,gBAAgB,GAAG,yBAAyB,CAAA;AAElD,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAA;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAA;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAe;IAC/C,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,CAAA;IAC/B,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAC9D,8DAA8D;IAC9D,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,KAAK,CAAC,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,iDAAiD;IACnD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAA0B;IAC3D,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAA;IAClC,MAAM,IAAI,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,EAAE,CAAA;IACrC,MAAM,WAAW,CAAC,IAAI,CAAC,CAAA;IACvB,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAA;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAoC;IAC7D,OAAO,GAAG,EAAE,UAAU,IAAI,gBAAgB,CAAA;AAC5C,CAAC"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/config/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAA;AACzB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAUlD,MAAM,CAAC,MAAM,gBAAgB,GAAG,yBAAyB,CAAA;AAEzD,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAA;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAA;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAe;IAC/C,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,CAAA;IAC/B,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAC9D,8DAA8D;IAC9D,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,KAAK,CAAC,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,iDAAiD;IACnD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAA0B;IAC3D,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAA;IAClC,MAAM,IAAI,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,EAAE,CAAA;IACrC,MAAM,WAAW,CAAC,IAAI,CAAC,CAAA;IACvB,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAA;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAoC;IAC7D,OAAO,GAAG,EAAE,UAAU,IAAI,gBAAgB,CAAA;AAC5C,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { createRequire } from 'node:module';
2
+ import { Command } from 'commander';
3
+ import { loginCommand } from './commands/login.js';
4
+ import { logoutCommand } from './commands/logout.js';
5
+ import { balanceCommand } from './commands/balance.js';
6
+ import { topupCommand } from './commands/topup.js';
7
+ import { modelsCommand } from './commands/models.js';
8
+ import { listCommand } from './commands/list.js';
9
+ import { doctorCommand } from './commands/doctor.js';
10
+ import { registerAgentCommands } from './commands/agent-runner.js';
11
+ // Read version from package.json so we never have to bump it in two places.
12
+ const pkg = createRequire(import.meta.url)('../package.json');
13
+ // Build the fully-wired commander program WITHOUT parsing argv.
14
+ // Keeping construction separate from execution makes the CLI unit-testable.
15
+ export function buildProgram(deps = {}) {
16
+ const program = new Command();
17
+ // Required so that agent subcommands can use passThroughOptions() to forward
18
+ // --version / --help / --any to the underlying agent binary instead of having
19
+ // tokenmix consume them.
20
+ program.enablePositionalOptions();
21
+ program
22
+ .name('tokenmix')
23
+ .description('Zero-config CLI to use any open-source coding agent with TokenMix as the unified LLM backend.')
24
+ .version(pkg.version);
25
+ program
26
+ .command('login')
27
+ .description('Log in to TokenMix (default: browser device authorization)')
28
+ .option('-k, --key <apiKey>', 'Paste an API key directly (skip browser flow, useful in CI)')
29
+ .option('-p, --paste', 'Force interactive paste prompt instead of browser flow')
30
+ .option('-u, --url <baseUrl>', 'Override API base URL (default: https://api.tokenmix.ai)')
31
+ .action(loginCommand);
32
+ program
33
+ .command('logout')
34
+ .description('Remove stored credentials from this machine')
35
+ .action(logoutCommand);
36
+ program
37
+ .command('balance')
38
+ .description('Open the dashboard to view your balance')
39
+ .action(balanceCommand);
40
+ program
41
+ .command('topup')
42
+ .description('Open the browser to top up your account')
43
+ .action(topupCommand);
44
+ program
45
+ .command('models')
46
+ .description('List available models with prices')
47
+ .option('-t, --type <type>', 'Filter by type: chat | embedding | image | audio | video')
48
+ .action(modelsCommand);
49
+ program
50
+ .command('list')
51
+ .description('List supported coding agents')
52
+ .action(listCommand);
53
+ program
54
+ .command('doctor')
55
+ .description('Diagnose CLI configuration and agent installation')
56
+ .action(doctorCommand);
57
+ // Register one subcommand per supported agent (opencode, claude, aider, kilo, ...).
58
+ registerAgentCommands(program, deps.runAgent);
59
+ return program;
60
+ }
61
+ //# sourceMappingURL=program.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.js","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,qBAAqB,EAAe,MAAM,4BAA4B,CAAA;AAE/E,4EAA4E;AAC5E,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAwB,CAAA;AAOpF,gEAAgE;AAChE,4EAA4E;AAC5E,MAAM,UAAU,YAAY,CAAC,OAAoB,EAAE;IACjD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;IAE7B,6EAA6E;IAC7E,8EAA8E;IAC9E,yBAAyB;IACzB,OAAO,CAAC,uBAAuB,EAAE,CAAA;IAEjC,OAAO;SACJ,IAAI,CAAC,UAAU,CAAC;SAChB,WAAW,CAAC,+FAA+F,CAAC;SAC5G,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAEvB,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,4DAA4D,CAAC;SACzE,MAAM,CAAC,oBAAoB,EAAE,6DAA6D,CAAC;SAC3F,MAAM,CAAC,aAAa,EAAE,wDAAwD,CAAC;SAC/E,MAAM,CAAC,qBAAqB,EAAE,0DAA0D,CAAC;SACzF,MAAM,CAAC,YAAY,CAAC,CAAA;IAEvB,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,6CAA6C,CAAC;SAC1D,MAAM,CAAC,aAAa,CAAC,CAAA;IAExB,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,yCAAyC,CAAC;SACtD,MAAM,CAAC,cAAc,CAAC,CAAA;IAEzB,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,yCAAyC,CAAC;SACtD,MAAM,CAAC,YAAY,CAAC,CAAA;IAEvB,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,mCAAmC,CAAC;SAChD,MAAM,CAAC,mBAAmB,EAAE,0DAA0D,CAAC;SACvF,MAAM,CAAC,aAAa,CAAC,CAAA;IAExB,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,8BAA8B,CAAC;SAC3C,MAAM,CAAC,WAAW,CAAC,CAAA;IAEtB,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,mDAAmD,CAAC;SAChE,MAAM,CAAC,aAAa,CAAC,CAAA;IAExB,oFAAoF;IACpF,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;IAE7C,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -1,5 +1,16 @@
1
1
  import open from 'open';
2
+ import { logger } from './logger.js';
2
3
  export async function openInBrowser(url) {
3
4
  await open(url);
4
5
  }
6
+ // Try to open the browser; on failure (headless / SSH / no desktop environment),
7
+ // print the URL so the user can open it manually instead of crashing.
8
+ export async function openOrHint(url) {
9
+ try {
10
+ await open(url);
11
+ }
12
+ catch {
13
+ logger.info(`Could not open a browser automatically. Open this URL manually:\n ${url}`);
14
+ }
15
+ }
5
16
  //# sourceMappingURL=browser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/utils/browser.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,MAAM,IAAI,CAAC,GAAG,CAAC,CAAA;AACjB,CAAC"}
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/utils/browser.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,MAAM,IAAI,CAAC,GAAG,CAAC,CAAA;AACjB,CAAC;AAED,iFAAiF;AACjF,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,GAAG,CAAC,CAAA;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,IAAI,CAAC,sEAAsE,GAAG,EAAE,CAAC,CAAA;IAC1F,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,11 +1,20 @@
1
1
  {
2
2
  "name": "tokenmix",
3
- "version": "0.2.1",
3
+ "version": "0.2.4",
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": {
7
7
  "tokenmix": "./bin/tokenmix.js"
8
8
  },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "tsx src/cli.ts",
12
+ "start": "node bin/tokenmix.js",
13
+ "typecheck": "tsc --noEmit",
14
+ "test": "vitest run",
15
+ "test:watch": "vitest",
16
+ "prepublishOnly": "pnpm build"
17
+ },
9
18
  "engines": {
10
19
  "node": ">=18"
11
20
  },
@@ -48,12 +57,12 @@
48
57
  "@types/prompts": "^2.4.9",
49
58
  "@types/which": "^3.0.4",
50
59
  "tsx": "^4.19.2",
51
- "typescript": "^5.6.3"
60
+ "typescript": "^5.6.3",
61
+ "vitest": "^4.1.7"
52
62
  },
53
- "scripts": {
54
- "build": "tsc",
55
- "dev": "tsx src/cli.ts",
56
- "start": "node bin/tokenmix.js",
57
- "typecheck": "tsc --noEmit"
63
+ "pnpm": {
64
+ "onlyBuiltDependencies": [
65
+ "esbuild"
66
+ ]
58
67
  }
59
- }
68
+ }