tokenmix 0.2.4 → 0.3.1

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.
@@ -4,6 +4,7 @@ import { promptApiKey, confirm } from '../utils/prompt.js';
4
4
  import { openInBrowser } from '../utils/browser.js';
5
5
  import { verifyApiKey, startDeviceAuthorization, pollDeviceToken, DeviceFlowError, } from '../api/client.js';
6
6
  import { readConfig, updateConfig, apiBaseUrl } from '../config/store.js';
7
+ import { t } from '../i18n/index.js';
7
8
  export async function loginCommand(opts) {
8
9
  const cfg = await readConfig();
9
10
  const baseUrl = opts.url || apiBaseUrl(cfg);
@@ -16,7 +17,7 @@ export async function loginCommand(opts) {
16
17
  if (opts.paste) {
17
18
  const entered = await promptApiKey();
18
19
  if (!entered) {
19
- logger.error('No API key provided.');
20
+ logger.error(t('login.noKey'));
20
21
  process.exit(1);
21
22
  }
22
23
  await loginByKey(entered, baseUrl);
@@ -27,28 +28,28 @@ export async function loginCommand(opts) {
27
28
  }
28
29
  async function loginByKey(apiKey, baseUrl) {
29
30
  if (!apiKey.startsWith('sk-tm-')) {
30
- logger.error('API key should start with sk-tm-');
31
+ logger.error(t('login.keyMustStart'));
31
32
  process.exit(1);
32
33
  }
33
- logger.step(`Verifying API key against ${baseUrl} ...`);
34
+ logger.step(t('login.verifying', { baseUrl }));
34
35
  const ok = await verifyApiKey(apiKey, baseUrl);
35
36
  if (!ok) {
36
- logger.error('API key verification failed. Double-check at https://tokenmix.ai/dashboard/keys');
37
+ logger.error(t('login.verifyFailed'));
37
38
  process.exit(1);
38
39
  }
39
40
  await updateConfig({ apiKey, apiBaseUrl: baseUrl });
40
- logger.success('Logged in. Try `tokenmix opencode` to launch your first agent.');
41
+ logger.success(t('login.loggedInHint'));
41
42
  }
42
43
  async function loginByDeviceFlow(baseUrl) {
43
- logger.step('Requesting device authorization ...');
44
+ logger.step(t('login.requesting'));
44
45
  let auth;
45
46
  try {
46
47
  auth = await startDeviceAuthorization(baseUrl);
47
48
  }
48
49
  catch (err) {
49
50
  const msg = err instanceof Error ? err.message : String(err);
50
- logger.error(`Could not start device authorization: ${msg}`);
51
- logger.info('Falling back to manual paste. Get an API key at https://tokenmix.ai/dashboard/keys');
51
+ logger.error(t('login.couldNotStart', { msg }));
52
+ logger.info(t('login.fallbackPaste'));
52
53
  const entered = await promptApiKey();
53
54
  if (!entered)
54
55
  process.exit(1);
@@ -60,48 +61,48 @@ async function loginByDeviceFlow(baseUrl) {
60
61
  const verifyUrl = auth.verification_uri_complete || auth.verification_uri;
61
62
  // Display user_code prominently
62
63
  console.log();
63
- console.log(' ' + chalk.dim('Open the link below and confirm this code:'));
64
+ console.log(' ' + chalk.dim(t('login.openLinkConfirm')));
64
65
  console.log();
65
66
  console.log(' ' + chalk.bold.cyan(auth.user_code));
66
67
  console.log();
67
- console.log(' ' + chalk.dim('Link:'));
68
+ console.log(' ' + chalk.dim(t('login.link')));
68
69
  console.log(' ' + chalk.underline(verifyUrl));
69
70
  console.log();
70
71
  // Try to open browser, but proceed even if it fails (headless / SSH)
71
72
  try {
72
73
  await openInBrowser(verifyUrl);
73
- logger.dim(' (browser opened; if nothing happens, copy the link above)');
74
+ logger.dim(' ' + t('login.browserOpened'));
74
75
  }
75
76
  catch {
76
- logger.dim(' (could not open browser; copy the link above into one)');
77
+ logger.dim(' ' + t('login.browserFailed'));
77
78
  }
78
79
  console.log();
79
- logger.step(`Waiting for authorization (expires in ${auth.expires_in}s, polling every ${auth.interval}s) ...`);
80
+ logger.step(t('login.waiting', { expires: auth.expires_in, interval: auth.interval }));
80
81
  let lastReported = -1;
81
82
  try {
82
83
  const result = await pollDeviceToken(baseUrl, auth, (secondsRemaining) => {
83
84
  // Print a heartbeat at most every 15s so the terminal isn't silent
84
85
  if (lastReported < 0 || lastReported - secondsRemaining >= 15) {
85
86
  lastReported = secondsRemaining;
86
- logger.dim(` ... still waiting (${secondsRemaining}s remaining)`);
87
+ logger.dim(' ' + t('login.stillWaiting', { seconds: secondsRemaining }));
87
88
  }
88
89
  });
89
90
  await updateConfig({ apiKey: result.apiKey, apiBaseUrl: baseUrl });
90
91
  console.log();
91
92
  if (result.userEmail) {
92
- logger.success(`Logged in as ${chalk.bold(result.userEmail)} (API key #${result.apiKeyId})`);
93
+ logger.success(t('login.loggedInAs', { email: chalk.bold(result.userEmail), id: result.apiKeyId }));
93
94
  }
94
95
  else {
95
- logger.success(`Logged in (API key #${result.apiKeyId})`);
96
+ logger.success(t('login.loggedInId', { id: result.apiKeyId }));
96
97
  }
97
- logger.info('Try `tokenmix opencode` to launch your first agent.');
98
+ logger.info(t('login.tryFirstAgent'));
98
99
  }
99
100
  catch (err) {
100
101
  console.log();
101
102
  if (err instanceof DeviceFlowError) {
102
103
  logger.error(err.message);
103
104
  if (err.code === 'expired_token' || err.code === 'timeout') {
104
- const retry = await confirm('Try again?', true);
105
+ const retry = await confirm(t('login.tryAgain'), true);
105
106
  if (retry) {
106
107
  await loginByDeviceFlow(baseUrl);
107
108
  return;
@@ -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,9 +1,10 @@
1
1
  import { logger } from '../utils/logger.js';
2
2
  import { clearConfig } from '../config/store.js';
3
3
  import { AGENTS } from '../agents/registry.js';
4
+ import { t } from '../i18n/index.js';
4
5
  export async function logoutCommand() {
5
6
  await clearConfig();
6
- logger.success('Logged out. Credentials removed from this machine.');
7
+ logger.success(t('logout.done'));
7
8
  // Also revert the config we injected into agents, so they stop routing through
8
9
  // TokenMix with a key that's about to be gone. Best-effort and precise — each
9
10
  // agent only removes what it recognizes as its own tokenmix config.
@@ -13,7 +14,7 @@ export async function logoutCommand() {
13
14
  try {
14
15
  const r = await agent.cleanup();
15
16
  if (r.reverted) {
16
- logger.success(`Reverted ${agent.displayName} config${r.configPath ? ` (${r.configPath})` : ''}`);
17
+ logger.success(t('logout.reverted', { name: agent.displayName }) + (r.configPath ? ` (${r.configPath})` : ''));
17
18
  if (r.note)
18
19
  logger.dim(` ${r.note}`);
19
20
  }
@@ -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;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
+ {"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;AAC9C,OAAO,EAAE,CAAC,EAAE,MAAM,kBAAkB,CAAA;AAEpC,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,WAAW,EAAE,CAAA;IACnB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAA;IAEhC,+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,CAAC,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;gBAC9G,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,14 +1,26 @@
1
1
  import chalk from 'chalk';
2
2
  import { logger } from '../utils/logger.js';
3
3
  import { listPublicModels } from '../api/client.js';
4
- const TYPE_LABEL = {
5
- chat: 'Chat',
6
- embedding: 'Embedding',
7
- image: 'Image',
8
- audio: 'Audio',
9
- video: 'Video',
10
- completion: 'Completion',
11
- };
4
+ import { t } from '../i18n/index.js';
5
+ // Resolved at call time so it follows the active locale.
6
+ function typeLabel(type) {
7
+ switch (type) {
8
+ case 'chat':
9
+ return t('models.typeChat');
10
+ case 'embedding':
11
+ return t('models.typeEmbedding');
12
+ case 'image':
13
+ return t('models.typeImage');
14
+ case 'audio':
15
+ return t('models.typeAudio');
16
+ case 'video':
17
+ return t('models.typeVideo');
18
+ case 'completion':
19
+ return t('models.typeCompletion');
20
+ default:
21
+ return type;
22
+ }
23
+ }
12
24
  // Match the platform-wide formatter: 6 decimals, trim trailing zeros.
13
25
  function formatPrice(p) {
14
26
  if (!p)
@@ -19,7 +31,7 @@ export async function modelsCommand(opts) {
19
31
  const all = await listPublicModels();
20
32
  const filtered = opts.type ? all.filter((m) => m.model_type === opts.type) : all;
21
33
  if (filtered.length === 0) {
22
- logger.warn('No models match the filter.');
34
+ logger.warn(t('models.none'));
23
35
  return;
24
36
  }
25
37
  const grouped = new Map();
@@ -30,13 +42,13 @@ export async function modelsCommand(opts) {
30
42
  }
31
43
  for (const [type, list] of grouped) {
32
44
  console.log();
33
- console.log(chalk.bold(`${TYPE_LABEL[type] ?? type} (${list.length})`));
45
+ console.log(chalk.bold(`${typeLabel(type)} (${list.length})`));
34
46
  for (const m of list) {
35
47
  const id = chalk.cyan(m.short_id || m.model_id);
36
48
  const priceParts = [];
37
49
  if (type === 'chat' || type === 'embedding' || type === 'audio' || type === 'completion') {
38
- priceParts.push(`in $${formatPrice(m.input_price)}/M`);
39
- priceParts.push(`out $${formatPrice(m.output_price)}/M`);
50
+ priceParts.push(`${t('models.in')} $${formatPrice(m.input_price)}/M`);
51
+ priceParts.push(`${t('models.out')} $${formatPrice(m.output_price)}/M`);
40
52
  }
41
53
  else if (type === 'image') {
42
54
  priceParts.push(`$${formatPrice(m.image_price)}/img`);
@@ -1 +1 @@
1
- {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  import { logger } from '../utils/logger.js';
2
2
  import { openOrHint } from '../utils/browser.js';
3
+ import { t } from '../i18n/index.js';
3
4
  const TOPUP_URL = 'https://tokenmix.ai/dashboard/credits';
4
5
  export async function topupCommand() {
5
- logger.step(`Opening top-up page: ${TOPUP_URL}`);
6
+ logger.step(t('topup.opening', { url: TOPUP_URL }));
6
7
  await openOrHint(TOPUP_URL);
7
8
  }
8
9
  //# 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,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
+ {"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;AAChD,OAAO,EAAE,CAAC,EAAE,MAAM,kBAAkB,CAAA;AAEpC,MAAM,SAAS,GAAG,uCAAuC,CAAA;AAEzD,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,CAAA;IACnD,MAAM,UAAU,CAAC,SAAS,CAAC,CAAA;AAC7B,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { catalogs, en } from './messages.js';
2
+ let current = 'en';
3
+ // Resolve the UI language from the environment. Precedence:
4
+ // TOKENMIX_LANG (explicit override, e.g. `TOKENMIX_LANG=zh`)
5
+ // LC_ALL / LC_MESSAGES / LANG (the user's system locale, e.g. zh_CN.UTF-8)
6
+ // default: en
7
+ // Takes `env` for testability; defaults to process.env.
8
+ export function detectLocale(env = process.env) {
9
+ const raw = (env.TOKENMIX_LANG || env.LC_ALL || env.LC_MESSAGES || env.LANG || '')
10
+ .toLowerCase()
11
+ .trim();
12
+ if (raw.startsWith('zh') || raw.includes('zh_') || raw.includes('zh-'))
13
+ return 'zh';
14
+ return 'en';
15
+ }
16
+ export function setLocale(loc) {
17
+ current = loc;
18
+ }
19
+ export function getLocale() {
20
+ return current;
21
+ }
22
+ // Translate a key for the active locale, filling {placeholders} from params.
23
+ // Falls back to English, then to the raw key, so a partial catalog never throws.
24
+ export function t(key, params) {
25
+ let s = catalogs[current]?.[key] ?? en[key] ?? key;
26
+ if (params) {
27
+ for (const [k, v] of Object.entries(params)) {
28
+ s = s.split(`{${k}}`).join(String(v));
29
+ }
30
+ }
31
+ return s;
32
+ }
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/i18n/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAc,MAAM,eAAe,CAAA;AAIxD,IAAI,OAAO,GAAW,IAAI,CAAA;AAE1B,4DAA4D;AAC5D,gEAAgE;AAChE,8EAA8E;AAC9E,gBAAgB;AAChB,wDAAwD;AACxD,MAAM,UAAU,YAAY,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC/D,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;SAC/E,WAAW,EAAE;SACb,IAAI,EAAE,CAAA;IACT,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACnF,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,OAAO,GAAG,GAAG,CAAA;AACf,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,6EAA6E;AAC7E,iFAAiF;AACjF,MAAM,UAAU,CAAC,CAAC,GAAe,EAAE,MAAwC;IACzE,IAAI,CAAC,GAAW,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,CAAA;IAC1D,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5C,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC"}
@@ -0,0 +1,240 @@
1
+ // User-facing message catalogs. `en` is the source of truth; `zh` is typed as
2
+ // `typeof en`, so the compiler forces every key to be translated (no missing
3
+ // strings can ship). Add a new language by adding another `typeof en` catalog
4
+ // to `catalogs` below — nothing else needs to change.
5
+ //
6
+ // `{name}`-style placeholders are filled by t() at call time.
7
+ export const en = {
8
+ 'common.notLoggedIn': 'Not logged in. Run `tokenmix login` first.',
9
+ // login
10
+ 'login.keyMustStart': 'API key should start with sk-tm-',
11
+ 'login.verifying': 'Verifying API key against {baseUrl} ...',
12
+ 'login.verifyFailed': 'API key verification failed. Double-check at https://tokenmix.ai/dashboard/keys',
13
+ 'login.loggedInHint': 'Logged in. Try `tokenmix opencode` to launch your first agent.',
14
+ 'login.noKey': 'No API key provided.',
15
+ 'login.requesting': 'Requesting device authorization ...',
16
+ 'login.couldNotStart': 'Could not start device authorization: {msg}',
17
+ 'login.fallbackPaste': 'Falling back to manual paste. Get an API key at https://tokenmix.ai/dashboard/keys',
18
+ 'login.openLinkConfirm': 'Open the link below and confirm this code:',
19
+ 'login.link': 'Link:',
20
+ 'login.browserOpened': '(browser opened; if nothing happens, copy the link above)',
21
+ 'login.browserFailed': '(could not open browser; copy the link above into one)',
22
+ 'login.waiting': 'Waiting for authorization (expires in {expires}s, polling every {interval}s) ...',
23
+ 'login.stillWaiting': '... still waiting ({seconds}s remaining)',
24
+ 'login.loggedInAs': 'Logged in as {email} (API key #{id})',
25
+ 'login.loggedInId': 'Logged in (API key #{id})',
26
+ 'login.tryFirstAgent': 'Try `tokenmix opencode` to launch your first agent.',
27
+ 'login.tryAgain': 'Try again?',
28
+ // agent install / configure / launch
29
+ 'agent.notInstalled': '{name} is not installed.',
30
+ 'agent.notInstallable': '{name} is not installable from the CLI.',
31
+ 'agent.installPrompt': '{name} is not installed. Install now?',
32
+ 'agent.installing': 'Installing {name} ...',
33
+ 'agent.installed': '{name} installed.',
34
+ 'agent.installFailed': 'Could not install {name} automatically.',
35
+ 'agent.installFailHint1': 'This usually means npm cannot write to its global folder. Options:',
36
+ 'agent.installFailHint2': ' • Use a Node version manager (nvm / fnm / volta) — then global installs need no sudo, or',
37
+ 'agent.installFailHint3': ' • Install it yourself: {cmd}',
38
+ 'agent.installFailHint4': 'Then re-run this command — your TokenMix login is already saved.',
39
+ 'agent.configuring': 'Configuring {name} ...',
40
+ 'agent.wrote': 'Wrote {path}',
41
+ 'agent.configReady': '{name} configuration ready.',
42
+ 'agent.launching': 'Launching {name} ...',
43
+ // logout
44
+ 'logout.done': 'Logged out. Credentials removed from this machine.',
45
+ 'logout.reverted': 'Reverted {name} config',
46
+ // doctor
47
+ 'doctor.title': 'TokenMix CLI diagnostic',
48
+ 'doctor.credentials': 'Credentials:',
49
+ 'doctor.apiKeyLabel': 'API key:',
50
+ 'doctor.apiBaseLabel': 'API base:',
51
+ 'doctor.keyValid': 'API key is valid.',
52
+ 'doctor.keyInvalid': 'API key did NOT validate. Run `tokenmix login` again.',
53
+ 'doctor.notLoggedIn': 'Not logged in. Run `tokenmix login`.',
54
+ 'doctor.agentStatus': 'Agent install status:',
55
+ 'doctor.installed': 'installed',
56
+ 'doctor.notInstalled': 'not installed',
57
+ // list
58
+ 'list.title': 'Supported agents:',
59
+ 'list.usage': 'Usage: tokenmix <agent> [args...]',
60
+ 'list.modeAutoNpm': 'auto (npm)',
61
+ 'list.modeAutoPip': 'semi (pip)',
62
+ 'list.modeManualVscode': 'config-only (VSCode)',
63
+ 'list.modeManual': 'manual',
64
+ // models
65
+ 'models.none': 'No models match the filter.',
66
+ 'models.typeChat': 'Chat',
67
+ 'models.typeEmbedding': 'Embedding',
68
+ 'models.typeImage': 'Image',
69
+ 'models.typeAudio': 'Audio',
70
+ 'models.typeVideo': 'Video',
71
+ 'models.typeCompletion': 'Completion',
72
+ 'models.in': 'in',
73
+ 'models.out': 'out',
74
+ // prompt
75
+ 'prompt.pasteKey': 'Paste your TokenMix API key (sk-tm-...)',
76
+ // browser
77
+ 'balance.opening': 'Opening dashboard to view balance: {url}',
78
+ 'topup.opening': 'Opening top-up page: {url}',
79
+ 'browser.manual': 'Could not open a browser automatically. Open this URL manually:\n {url}',
80
+ // agent taglines (shown in `list`)
81
+ 'desc.opencode': 'sst/opencode — open source AI coding agent (TUI / Desktop / IDE)',
82
+ 'desc.claude': 'anthropics/claude-code — official Anthropic CLI coding agent',
83
+ 'desc.aider': 'Aider-AI/aider — paired-programming CLI (requires Python)',
84
+ 'desc.kilo': 'Kilo-Org/kilocode — VSCode extension (config-only)',
85
+ // install hints
86
+ 'install.willInstallVia': 'Will install via: {cmd}',
87
+ 'aider.hintNeedPython': 'Aider requires Python 3. Install Python 3 from https://python.org/downloads, then come back and run `tokenmix aider` again.',
88
+ 'aider.hintNotInstalled': 'Aider is not installed. Run this in another terminal:\n {cmd}\nThen come back and run `tokenmix aider` again — your TokenMix login is already saved, so it will pick up automatically.',
89
+ // opencode configure notes
90
+ 'opencode.noteModel': 'Default model set to tokenmix/{model}',
91
+ 'opencode.noteSwitch': 'To switch models, run `tokenmix models` or use `/connect` inside OpenCode.',
92
+ // claude configure notes
93
+ 'claude.noteModels': 'Available Claude models via tokenmix: claude-opus-4.7, claude-sonnet-4.6, claude-haiku-4.5',
94
+ 'claude.noteFullList': 'Run `tokenmix models --type chat` for the full list.',
95
+ 'claude.noteReplaced1': '⚠ Replaced your existing Anthropic settings in ~/.claude/settings.json.',
96
+ 'claude.noteReplaced2': " `tokenmix logout` removes TokenMix's entries (your old key cannot be auto-restored).",
97
+ 'claude.cleanupNote': 'If you had your own ANTHROPIC_API_KEY here before, re-add it.',
98
+ // aider configure notes
99
+ 'aider.noteUsing': 'Aider will use TokenMix via OpenAI-compatible endpoint.',
100
+ 'aider.noteModel': 'Default model: openai/{model} — override with --model.',
101
+ // kilo configure notes (prose only; technical lines stay verbatim)
102
+ 'kilo.noteNoLauncher': 'Kilo Code is a VSCode extension and does not have a CLI launcher.',
103
+ 'kilo.noteConfigWith': 'Configure Kilo Code with the following:',
104
+ 'kilo.notePasteJson': 'Or paste this JSON snippet into Kilo Code settings (Settings → Providers → JSON):',
105
+ 'kilo.noteKeepPrivate': 'Keep this API key private — anyone with it can spend your TokenMix balance.',
106
+ 'kilo.hintMarketplace': 'Install "Kilo Code" from the VSCode marketplace, then paste the snippet below into its settings.',
107
+ 'kilo.hintNoVscode': 'VSCode not detected on PATH. Install VSCode, then add the Kilo Code extension, then use the snippet below.',
108
+ // command / option descriptions (--help)
109
+ 'cmd.program': 'Zero-config CLI to use any open-source coding agent with TokenMix as the unified LLM backend.',
110
+ 'cmd.login': 'Log in to TokenMix (default: browser device authorization)',
111
+ 'cmd.loginKey': 'Paste an API key directly (skip browser flow, useful in CI)',
112
+ 'cmd.loginPaste': 'Force interactive paste prompt instead of browser flow',
113
+ 'cmd.loginUrl': 'Override API base URL (default: https://api.tokenmix.ai)',
114
+ 'cmd.logout': 'Remove stored credentials from this machine',
115
+ 'cmd.balance': 'Open the dashboard to view your balance',
116
+ 'cmd.topup': 'Open the browser to top up your account',
117
+ 'cmd.models': 'List available models with prices',
118
+ 'cmd.modelsType': 'Filter by type: chat | embedding | image | audio | video',
119
+ 'cmd.list': 'List supported coding agents',
120
+ 'cmd.doctor': 'Diagnose CLI configuration and agent installation',
121
+ 'cmd.agent': 'Configure and launch {name} via TokenMix',
122
+ };
123
+ export const zh = {
124
+ 'common.notLoggedIn': '未登录,请先运行 `tokenmix login`。',
125
+ // login
126
+ 'login.keyMustStart': 'API 密钥应以 sk-tm- 开头',
127
+ 'login.verifying': '正在通过 {baseUrl} 校验 API 密钥 ...',
128
+ 'login.verifyFailed': 'API 密钥校验失败。请到 https://tokenmix.ai/dashboard/keys 核对',
129
+ 'login.loggedInHint': '登录成功。试试 `tokenmix opencode` 启动你的第一个 agent。',
130
+ 'login.noKey': '未提供 API 密钥。',
131
+ 'login.requesting': '正在请求设备授权 ...',
132
+ 'login.couldNotStart': '无法发起设备授权:{msg}',
133
+ 'login.fallbackPaste': '改用手动粘贴。可在 https://tokenmix.ai/dashboard/keys 获取 API 密钥',
134
+ 'login.openLinkConfirm': '打开下方链接并确认此验证码:',
135
+ 'login.link': '链接:',
136
+ 'login.browserOpened': '(已打开浏览器;若无反应,请复制上面的链接)',
137
+ 'login.browserFailed': '(无法打开浏览器;请复制上面的链接到浏览器打开)',
138
+ 'login.waiting': '等待授权({expires}s 后过期,每 {interval}s 轮询一次)...',
139
+ 'login.stillWaiting': '... 仍在等待(剩余 {seconds}s)',
140
+ 'login.loggedInAs': '已登录:{email}(API 密钥 #{id})',
141
+ 'login.loggedInId': '登录成功(API 密钥 #{id})',
142
+ 'login.tryFirstAgent': '试试 `tokenmix opencode` 启动你的第一个 agent。',
143
+ 'login.tryAgain': '重试?',
144
+ // agent install / configure / launch
145
+ 'agent.notInstalled': '{name} 尚未安装。',
146
+ 'agent.notInstallable': '{name} 无法通过 CLI 安装。',
147
+ 'agent.installPrompt': '{name} 尚未安装。现在安装?',
148
+ 'agent.installing': '正在安装 {name} ...',
149
+ 'agent.installed': '{name} 安装完成。',
150
+ 'agent.installFailed': '无法自动安装 {name}。',
151
+ 'agent.installFailHint1': '这通常是 npm 无权写入全局目录。可选方案:',
152
+ 'agent.installFailHint2': ' • 使用 Node 版本管理器(nvm / fnm / volta)—— 全局安装即无需 sudo;或',
153
+ 'agent.installFailHint3': ' • 自行安装:{cmd}',
154
+ 'agent.installFailHint4': '随后重新运行本命令 —— 你的 TokenMix 登录已保存。',
155
+ 'agent.configuring': '正在配置 {name} ...',
156
+ 'agent.wrote': '已写入 {path}',
157
+ 'agent.configReady': '{name} 配置已就绪。',
158
+ 'agent.launching': '正在启动 {name} ...',
159
+ // logout
160
+ 'logout.done': '已登出。凭据已从本机移除。',
161
+ 'logout.reverted': '已还原 {name} 配置',
162
+ // doctor
163
+ 'doctor.title': 'TokenMix CLI 诊断',
164
+ 'doctor.credentials': '凭据:',
165
+ 'doctor.apiKeyLabel': 'API 密钥:',
166
+ 'doctor.apiBaseLabel': 'API 地址:',
167
+ 'doctor.keyValid': 'API 密钥有效。',
168
+ 'doctor.keyInvalid': 'API 密钥校验未通过。请重新运行 `tokenmix login`。',
169
+ 'doctor.notLoggedIn': '未登录。请运行 `tokenmix login`。',
170
+ 'doctor.agentStatus': 'Agent 安装状态:',
171
+ 'doctor.installed': '已安装',
172
+ 'doctor.notInstalled': '未安装',
173
+ // list
174
+ 'list.title': '支持的 agent:',
175
+ 'list.usage': '用法:tokenmix <agent> [参数...]',
176
+ 'list.modeAutoNpm': '自动 (npm)',
177
+ 'list.modeAutoPip': '半自动 (pip)',
178
+ 'list.modeManualVscode': '仅配置 (VSCode)',
179
+ 'list.modeManual': '手动',
180
+ // models
181
+ 'models.none': '没有匹配该筛选条件的模型。',
182
+ 'models.typeChat': '对话',
183
+ 'models.typeEmbedding': '向量',
184
+ 'models.typeImage': '图像',
185
+ 'models.typeAudio': '音频',
186
+ 'models.typeVideo': '视频',
187
+ 'models.typeCompletion': '补全',
188
+ 'models.in': '输入',
189
+ 'models.out': '输出',
190
+ // prompt
191
+ 'prompt.pasteKey': '粘贴你的 TokenMix API 密钥(sk-tm-...)',
192
+ // browser
193
+ 'balance.opening': '正在打开仪表盘查看余额:{url}',
194
+ 'topup.opening': '正在打开充值页面:{url}',
195
+ 'browser.manual': '无法自动打开浏览器。请手动打开此链接:\n {url}',
196
+ // agent taglines (shown in `list`)
197
+ 'desc.opencode': 'sst/opencode — 开源 AI 编程 agent(TUI / 桌面 / IDE)',
198
+ 'desc.claude': 'anthropics/claude-code — Anthropic 官方 CLI 编程 agent',
199
+ 'desc.aider': 'Aider-AI/aider — 结对编程 CLI(需要 Python)',
200
+ 'desc.kilo': 'Kilo-Org/kilocode — VSCode 扩展(仅配置)',
201
+ // install hints
202
+ 'install.willInstallVia': '将自动安装:{cmd}',
203
+ 'aider.hintNeedPython': 'Aider 需要 Python 3。请从 https://python.org/downloads 安装 Python 3,然后重新运行 `tokenmix aider`。',
204
+ 'aider.hintNotInstalled': 'Aider 尚未安装。请在另一个终端运行:\n {cmd}\n然后重新运行 `tokenmix aider` —— 你的 TokenMix 登录已保存,会自动生效。',
205
+ // opencode configure notes
206
+ 'opencode.noteModel': '默认模型已设为 tokenmix/{model}',
207
+ 'opencode.noteSwitch': '切换模型:运行 `tokenmix models`,或在 OpenCode 内使用 `/connect`。',
208
+ // claude configure notes
209
+ 'claude.noteModels': '可用的 Claude 模型(经 tokenmix):claude-opus-4.7、claude-sonnet-4.6、claude-haiku-4.5',
210
+ 'claude.noteFullList': '完整列表请运行 `tokenmix models --type chat`。',
211
+ 'claude.noteReplaced1': '⚠ 已替换你在 ~/.claude/settings.json 中原有的 Anthropic 配置。',
212
+ 'claude.noteReplaced2': ' `tokenmix logout` 可移除 TokenMix 写入的项(你的旧密钥无法自动恢复)。',
213
+ 'claude.cleanupNote': '如果你之前在此设置过自己的 ANTHROPIC_API_KEY,请重新添加。',
214
+ // aider configure notes
215
+ 'aider.noteUsing': 'Aider 将通过 OpenAI 兼容端点使用 TokenMix。',
216
+ 'aider.noteModel': '默认模型:openai/{model} —— 可用 --model 覆盖。',
217
+ // kilo configure notes (prose only; technical lines stay verbatim)
218
+ 'kilo.noteNoLauncher': 'Kilo Code 是 VSCode 扩展,没有 CLI 启动器。',
219
+ 'kilo.noteConfigWith': '请按以下信息配置 Kilo Code:',
220
+ 'kilo.notePasteJson': '或将以下 JSON 粘贴到 Kilo Code 设置(Settings → Providers → JSON):',
221
+ 'kilo.noteKeepPrivate': '请妥善保管此 API 密钥 —— 任何人拿到它都能消耗你的 TokenMix 余额。',
222
+ 'kilo.hintMarketplace': '从 VSCode 应用市场安装 "Kilo Code",然后将下面的片段粘贴到它的设置中。',
223
+ 'kilo.hintNoVscode': '未在 PATH 中检测到 VSCode。请先安装 VSCode,再添加 Kilo Code 扩展,然后使用下面的片段。',
224
+ // command / option descriptions (--help)
225
+ 'cmd.program': '零配置 CLI:以 TokenMix 作为统一 LLM 后端,驱动任意开源编程 agent。',
226
+ 'cmd.login': '登录 TokenMix(默认:浏览器设备授权)',
227
+ 'cmd.loginKey': '直接粘贴 API 密钥(跳过浏览器流程,适合 CI)',
228
+ 'cmd.loginPaste': '强制使用交互式粘贴,而非浏览器流程',
229
+ 'cmd.loginUrl': '覆盖 API 基础地址(默认:https://api.tokenmix.ai)',
230
+ 'cmd.logout': '从本机移除已保存的凭据',
231
+ 'cmd.balance': '打开仪表盘查看余额',
232
+ 'cmd.topup': '打开浏览器为账户充值',
233
+ 'cmd.models': '列出可用模型及价格',
234
+ 'cmd.modelsType': '按类型筛选:chat | embedding | image | audio | video',
235
+ 'cmd.list': '列出支持的编程 agent',
236
+ 'cmd.doctor': '诊断 CLI 配置与 agent 安装情况',
237
+ 'cmd.agent': '通过 TokenMix 配置并启动 {name}',
238
+ };
239
+ export const catalogs = { en, zh };
240
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/i18n/messages.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,6EAA6E;AAC7E,8EAA8E;AAC9E,sDAAsD;AACtD,EAAE;AACF,8DAA8D;AAE9D,MAAM,CAAC,MAAM,EAAE,GAAG;IAChB,oBAAoB,EAAE,4CAA4C;IAElE,QAAQ;IACR,oBAAoB,EAAE,kCAAkC;IACxD,iBAAiB,EAAE,yCAAyC;IAC5D,oBAAoB,EAAE,iFAAiF;IACvG,oBAAoB,EAAE,gEAAgE;IACtF,aAAa,EAAE,sBAAsB;IACrC,kBAAkB,EAAE,qCAAqC;IACzD,qBAAqB,EAAE,6CAA6C;IACpE,qBAAqB,EAAE,oFAAoF;IAC3G,uBAAuB,EAAE,4CAA4C;IACrE,YAAY,EAAE,OAAO;IACrB,qBAAqB,EAAE,2DAA2D;IAClF,qBAAqB,EAAE,wDAAwD;IAC/E,eAAe,EAAE,kFAAkF;IACnG,oBAAoB,EAAE,0CAA0C;IAChE,kBAAkB,EAAE,sCAAsC;IAC1D,kBAAkB,EAAE,2BAA2B;IAC/C,qBAAqB,EAAE,qDAAqD;IAC5E,gBAAgB,EAAE,YAAY;IAE9B,qCAAqC;IACrC,oBAAoB,EAAE,0BAA0B;IAChD,sBAAsB,EAAE,yCAAyC;IACjE,qBAAqB,EAAE,uCAAuC;IAC9D,kBAAkB,EAAE,uBAAuB;IAC3C,iBAAiB,EAAE,mBAAmB;IACtC,qBAAqB,EAAE,yCAAyC;IAChE,wBAAwB,EAAE,oEAAoE;IAC9F,wBAAwB,EAAE,4FAA4F;IACtH,wBAAwB,EAAE,gCAAgC;IAC1D,wBAAwB,EAAE,kEAAkE;IAC5F,mBAAmB,EAAE,wBAAwB;IAC7C,aAAa,EAAE,cAAc;IAC7B,mBAAmB,EAAE,6BAA6B;IAClD,iBAAiB,EAAE,sBAAsB;IAEzC,SAAS;IACT,aAAa,EAAE,oDAAoD;IACnE,iBAAiB,EAAE,wBAAwB;IAE3C,SAAS;IACT,cAAc,EAAE,yBAAyB;IACzC,oBAAoB,EAAE,cAAc;IACpC,oBAAoB,EAAE,UAAU;IAChC,qBAAqB,EAAE,WAAW;IAClC,iBAAiB,EAAE,mBAAmB;IACtC,mBAAmB,EAAE,uDAAuD;IAC5E,oBAAoB,EAAE,sCAAsC;IAC5D,oBAAoB,EAAE,uBAAuB;IAC7C,kBAAkB,EAAE,WAAW;IAC/B,qBAAqB,EAAE,eAAe;IAEtC,OAAO;IACP,YAAY,EAAE,mBAAmB;IACjC,YAAY,EAAE,mCAAmC;IACjD,kBAAkB,EAAE,YAAY;IAChC,kBAAkB,EAAE,YAAY;IAChC,uBAAuB,EAAE,sBAAsB;IAC/C,iBAAiB,EAAE,QAAQ;IAE3B,SAAS;IACT,aAAa,EAAE,6BAA6B;IAC5C,iBAAiB,EAAE,MAAM;IACzB,sBAAsB,EAAE,WAAW;IACnC,kBAAkB,EAAE,OAAO;IAC3B,kBAAkB,EAAE,OAAO;IAC3B,kBAAkB,EAAE,OAAO;IAC3B,uBAAuB,EAAE,YAAY;IACrC,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,KAAK;IAEnB,SAAS;IACT,iBAAiB,EAAE,yCAAyC;IAE5D,UAAU;IACV,iBAAiB,EAAE,0CAA0C;IAC7D,eAAe,EAAE,4BAA4B;IAC7C,gBAAgB,EAAE,0EAA0E;IAE5F,mCAAmC;IACnC,eAAe,EAAE,kEAAkE;IACnF,aAAa,EAAE,8DAA8D;IAC7E,YAAY,EAAE,2DAA2D;IACzE,WAAW,EAAE,oDAAoD;IAEjE,gBAAgB;IAChB,wBAAwB,EAAE,yBAAyB;IACnD,sBAAsB,EAAE,6HAA6H;IACrJ,wBAAwB,EAAE,2LAA2L;IAErN,2BAA2B;IAC3B,oBAAoB,EAAE,uCAAuC;IAC7D,qBAAqB,EAAE,4EAA4E;IAEnG,yBAAyB;IACzB,mBAAmB,EAAE,4FAA4F;IACjH,qBAAqB,EAAE,sDAAsD;IAC7E,sBAAsB,EAAE,yEAAyE;IACjG,sBAAsB,EAAE,wFAAwF;IAChH,oBAAoB,EAAE,+DAA+D;IAErF,wBAAwB;IACxB,iBAAiB,EAAE,yDAAyD;IAC5E,iBAAiB,EAAE,wDAAwD;IAE3E,mEAAmE;IACnE,qBAAqB,EAAE,mEAAmE;IAC1F,qBAAqB,EAAE,yCAAyC;IAChE,oBAAoB,EAAE,mFAAmF;IACzG,sBAAsB,EAAE,6EAA6E;IACrG,sBAAsB,EAAE,kGAAkG;IAC1H,mBAAmB,EAAE,4GAA4G;IAEjI,yCAAyC;IACzC,aAAa,EAAE,+FAA+F;IAC9G,WAAW,EAAE,4DAA4D;IACzE,cAAc,EAAE,6DAA6D;IAC7E,gBAAgB,EAAE,wDAAwD;IAC1E,cAAc,EAAE,0DAA0D;IAC1E,YAAY,EAAE,6CAA6C;IAC3D,aAAa,EAAE,yCAAyC;IACxD,WAAW,EAAE,yCAAyC;IACtD,YAAY,EAAE,mCAAmC;IACjD,gBAAgB,EAAE,0DAA0D;IAC5E,UAAU,EAAE,8BAA8B;IAC1C,YAAY,EAAE,mDAAmD;IACjE,WAAW,EAAE,0CAA0C;CACxD,CAAA;AAID,MAAM,CAAC,MAAM,EAAE,GAAc;IAC3B,oBAAoB,EAAE,4BAA4B;IAElD,QAAQ;IACR,oBAAoB,EAAE,oBAAoB;IAC1C,iBAAiB,EAAE,8BAA8B;IACjD,oBAAoB,EAAE,qDAAqD;IAC3E,oBAAoB,EAAE,4CAA4C;IAClE,aAAa,EAAE,aAAa;IAC5B,kBAAkB,EAAE,cAAc;IAClC,qBAAqB,EAAE,gBAAgB;IACvC,qBAAqB,EAAE,wDAAwD;IAC/E,uBAAuB,EAAE,gBAAgB;IACzC,YAAY,EAAE,KAAK;IACnB,qBAAqB,EAAE,wBAAwB;IAC/C,qBAAqB,EAAE,0BAA0B;IACjD,eAAe,EAAE,4CAA4C;IAC7D,oBAAoB,EAAE,yBAAyB;IAC/C,kBAAkB,EAAE,2BAA2B;IAC/C,kBAAkB,EAAE,oBAAoB;IACxC,qBAAqB,EAAE,uCAAuC;IAC9D,gBAAgB,EAAE,KAAK;IAEvB,qCAAqC;IACrC,oBAAoB,EAAE,cAAc;IACpC,sBAAsB,EAAE,qBAAqB;IAC7C,qBAAqB,EAAE,mBAAmB;IAC1C,kBAAkB,EAAE,iBAAiB;IACrC,iBAAiB,EAAE,cAAc;IACjC,qBAAqB,EAAE,gBAAgB;IACvC,wBAAwB,EAAE,yBAAyB;IACnD,wBAAwB,EAAE,uDAAuD;IACjF,wBAAwB,EAAE,gBAAgB;IAC1C,wBAAwB,EAAE,iCAAiC;IAC3D,mBAAmB,EAAE,iBAAiB;IACtC,aAAa,EAAE,YAAY;IAC3B,mBAAmB,EAAE,eAAe;IACpC,iBAAiB,EAAE,iBAAiB;IAEpC,SAAS;IACT,aAAa,EAAE,eAAe;IAC9B,iBAAiB,EAAE,eAAe;IAElC,SAAS;IACT,cAAc,EAAE,iBAAiB;IACjC,oBAAoB,EAAE,KAAK;IAC3B,oBAAoB,EAAE,SAAS;IAC/B,qBAAqB,EAAE,SAAS;IAChC,iBAAiB,EAAE,WAAW;IAC9B,mBAAmB,EAAE,qCAAqC;IAC1D,oBAAoB,EAAE,2BAA2B;IACjD,oBAAoB,EAAE,aAAa;IACnC,kBAAkB,EAAE,KAAK;IACzB,qBAAqB,EAAE,KAAK;IAE5B,OAAO;IACP,YAAY,EAAE,YAAY;IAC1B,YAAY,EAAE,6BAA6B;IAC3C,kBAAkB,EAAE,UAAU;IAC9B,kBAAkB,EAAE,WAAW;IAC/B,uBAAuB,EAAE,cAAc;IACvC,iBAAiB,EAAE,IAAI;IAEvB,SAAS;IACT,aAAa,EAAE,eAAe;IAC9B,iBAAiB,EAAE,IAAI;IACvB,sBAAsB,EAAE,IAAI;IAC5B,kBAAkB,EAAE,IAAI;IACxB,kBAAkB,EAAE,IAAI;IACxB,kBAAkB,EAAE,IAAI;IACxB,uBAAuB,EAAE,IAAI;IAC7B,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,IAAI;IAElB,SAAS;IACT,iBAAiB,EAAE,iCAAiC;IAEpD,UAAU;IACV,iBAAiB,EAAE,mBAAmB;IACtC,eAAe,EAAE,gBAAgB;IACjC,gBAAgB,EAAE,8BAA8B;IAEhD,mCAAmC;IACnC,eAAe,EAAE,+CAA+C;IAChE,aAAa,EAAE,oDAAoD;IACnE,YAAY,EAAE,sCAAsC;IACpD,WAAW,EAAE,oCAAoC;IAEjD,gBAAgB;IAChB,wBAAwB,EAAE,aAAa;IACvC,sBAAsB,EAAE,wFAAwF;IAChH,wBAAwB,EAAE,uFAAuF;IAEjH,2BAA2B;IAC3B,oBAAoB,EAAE,0BAA0B;IAChD,qBAAqB,EAAE,uDAAuD;IAE9E,yBAAyB;IACzB,mBAAmB,EAAE,8EAA8E;IACnG,qBAAqB,EAAE,wCAAwC;IAC/D,sBAAsB,EAAE,oDAAoD;IAC5E,sBAAsB,EAAE,qDAAqD;IAC7E,oBAAoB,EAAE,wCAAwC;IAE9D,wBAAwB;IACxB,iBAAiB,EAAE,mCAAmC;IACtD,iBAAiB,EAAE,uCAAuC;IAE1D,mEAAmE;IACnE,qBAAqB,EAAE,mCAAmC;IAC1D,qBAAqB,EAAE,qBAAqB;IAC5C,oBAAoB,EAAE,0DAA0D;IAChF,sBAAsB,EAAE,4CAA4C;IACpE,sBAAsB,EAAE,+CAA+C;IACvE,mBAAmB,EAAE,6DAA6D;IAElF,yCAAyC;IACzC,aAAa,EAAE,gDAAgD;IAC/D,WAAW,EAAE,yBAAyB;IACtC,cAAc,EAAE,4BAA4B;IAC5C,gBAAgB,EAAE,mBAAmB;IACrC,cAAc,EAAE,yCAAyC;IACzD,YAAY,EAAE,aAAa;IAC3B,aAAa,EAAE,WAAW;IAC1B,WAAW,EAAE,YAAY;IACzB,YAAY,EAAE,WAAW;IACzB,gBAAgB,EAAE,gDAAgD;IAClE,UAAU,EAAE,eAAe;IAC3B,YAAY,EAAE,uBAAuB;IACrC,WAAW,EAAE,0BAA0B;CACxC,CAAA;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAA"}
package/dist/program.js CHANGED
@@ -8,6 +8,7 @@ import { modelsCommand } from './commands/models.js';
8
8
  import { listCommand } from './commands/list.js';
9
9
  import { doctorCommand } from './commands/doctor.js';
10
10
  import { registerAgentCommands } from './commands/agent-runner.js';
11
+ import { t } from './i18n/index.js';
11
12
  // Read version from package.json so we never have to bump it in two places.
12
13
  const pkg = createRequire(import.meta.url)('../package.json');
13
14
  // Build the fully-wired commander program WITHOUT parsing argv.
@@ -20,39 +21,39 @@ export function buildProgram(deps = {}) {
20
21
  program.enablePositionalOptions();
21
22
  program
22
23
  .name('tokenmix')
23
- .description('Zero-config CLI to use any open-source coding agent with TokenMix as the unified LLM backend.')
24
+ .description(t('cmd.program'))
24
25
  .version(pkg.version);
25
26
  program
26
27
  .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)')
28
+ .description(t('cmd.login'))
29
+ .option('-k, --key <apiKey>', t('cmd.loginKey'))
30
+ .option('-p, --paste', t('cmd.loginPaste'))
31
+ .option('-u, --url <baseUrl>', t('cmd.loginUrl'))
31
32
  .action(loginCommand);
32
33
  program
33
34
  .command('logout')
34
- .description('Remove stored credentials from this machine')
35
+ .description(t('cmd.logout'))
35
36
  .action(logoutCommand);
36
37
  program
37
38
  .command('balance')
38
- .description('Open the dashboard to view your balance')
39
+ .description(t('cmd.balance'))
39
40
  .action(balanceCommand);
40
41
  program
41
42
  .command('topup')
42
- .description('Open the browser to top up your account')
43
+ .description(t('cmd.topup'))
43
44
  .action(topupCommand);
44
45
  program
45
46
  .command('models')
46
- .description('List available models with prices')
47
- .option('-t, --type <type>', 'Filter by type: chat | embedding | image | audio | video')
47
+ .description(t('cmd.models'))
48
+ .option('-t, --type <type>', t('cmd.modelsType'))
48
49
  .action(modelsCommand);
49
50
  program
50
51
  .command('list')
51
- .description('List supported coding agents')
52
+ .description(t('cmd.list'))
52
53
  .action(listCommand);
53
54
  program
54
55
  .command('doctor')
55
- .description('Diagnose CLI configuration and agent installation')
56
+ .description(t('cmd.doctor'))
56
57
  .action(doctorCommand);
57
58
  // Register one subcommand per supported agent (opencode, claude, aider, kilo, ...).
58
59
  registerAgentCommands(program, deps.runAgent);