tokenmix 0.2.2 → 0.3.0

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.
Files changed (42) hide show
  1. package/README.md +11 -2
  2. package/dist/agents/aider.js +24 -3
  3. package/dist/agents/aider.js.map +1 -1
  4. package/dist/agents/claude.js +59 -4
  5. package/dist/agents/claude.js.map +1 -1
  6. package/dist/agents/kilo.js +2 -0
  7. package/dist/agents/kilo.js.map +1 -1
  8. package/dist/agents/opencode.js +29 -0
  9. package/dist/agents/opencode.js.map +1 -1
  10. package/dist/api/client.js +12 -6
  11. package/dist/api/client.js.map +1 -1
  12. package/dist/cli.js +5 -55
  13. package/dist/cli.js.map +1 -1
  14. package/dist/commands/agent-runner.js +60 -23
  15. package/dist/commands/agent-runner.js.map +1 -1
  16. package/dist/commands/balance.js +5 -4
  17. package/dist/commands/balance.js.map +1 -1
  18. package/dist/commands/doctor.js +11 -10
  19. package/dist/commands/doctor.js.map +1 -1
  20. package/dist/commands/list.js +19 -9
  21. package/dist/commands/list.js.map +1 -1
  22. package/dist/commands/login.js +24 -20
  23. package/dist/commands/login.js.map +1 -1
  24. package/dist/commands/logout.js +21 -1
  25. package/dist/commands/logout.js.map +1 -1
  26. package/dist/commands/models.js +24 -12
  27. package/dist/commands/models.js.map +1 -1
  28. package/dist/commands/topup.js +4 -3
  29. package/dist/commands/topup.js.map +1 -1
  30. package/dist/config/store.js +1 -1
  31. package/dist/config/store.js.map +1 -1
  32. package/dist/i18n/index.js +33 -0
  33. package/dist/i18n/index.js.map +1 -0
  34. package/dist/i18n/messages.js +156 -0
  35. package/dist/i18n/messages.js.map +1 -0
  36. package/dist/program.js +61 -0
  37. package/dist/program.js.map +1 -0
  38. package/dist/utils/browser.js +12 -0
  39. package/dist/utils/browser.js.map +1 -1
  40. package/dist/utils/prompt.js +3 -2
  41. package/dist/utils/prompt.js.map +1 -1
  42. package/package.json +17 -8
@@ -3,6 +3,7 @@ import { logger } from '../utils/logger.js';
3
3
  import { readConfig, apiBaseUrl } from '../config/store.js';
4
4
  import { verifyApiKey } from '../api/client.js';
5
5
  import { AGENTS } from '../agents/registry.js';
6
+ import { t } from '../i18n/index.js';
6
7
  function maskKey(key) {
7
8
  if (key.length <= 12)
8
9
  return key;
@@ -10,35 +11,35 @@ function maskKey(key) {
10
11
  }
11
12
  export async function doctorCommand() {
12
13
  console.log();
13
- console.log(chalk.bold('TokenMix CLI diagnostic'));
14
+ console.log(chalk.bold(t('doctor.title')));
14
15
  console.log();
15
16
  const cfg = await readConfig();
16
- console.log(chalk.bold('Credentials:'));
17
+ console.log(chalk.bold(t('doctor.credentials')));
17
18
  if (cfg.apiKey) {
18
- logger.success(`API key: ${chalk.cyan(maskKey(cfg.apiKey))}`);
19
- logger.success(`API base: ${chalk.cyan(apiBaseUrl(cfg))}`);
19
+ logger.success(`${t('doctor.apiKeyLabel')} ${chalk.cyan(maskKey(cfg.apiKey))}`);
20
+ logger.success(`${t('doctor.apiBaseLabel')} ${chalk.cyan(apiBaseUrl(cfg))}`);
20
21
  const ok = await verifyApiKey(cfg.apiKey, apiBaseUrl(cfg));
21
22
  if (ok) {
22
- logger.success('API key is valid.');
23
+ logger.success(t('doctor.keyValid'));
23
24
  }
24
25
  else {
25
- logger.error('API key did NOT validate. Run `tokenmix login` again.');
26
+ logger.error(t('doctor.keyInvalid'));
26
27
  }
27
28
  }
28
29
  else {
29
- logger.warn('Not logged in. Run `tokenmix login`.');
30
+ logger.warn(t('doctor.notLoggedIn'));
30
31
  }
31
32
  console.log();
32
- console.log(chalk.bold('Agent install status:'));
33
+ console.log(chalk.bold(t('doctor.agentStatus')));
33
34
  for (const a of AGENTS) {
34
35
  const r = await a.installCheck();
35
36
  if (r.installed) {
36
- logger.success(`${a.displayName.padEnd(14)} installed${r.version ? ` (${chalk.dim(r.version)})` : ''}`);
37
+ logger.success(`${a.displayName.padEnd(14)} ${t('doctor.installed')}${r.version ? ` (${chalk.dim(r.version)})` : ''}`);
37
38
  if (r.hint)
38
39
  console.log(` ${chalk.dim(r.hint)}`);
39
40
  }
40
41
  else {
41
- logger.warn(`${a.displayName.padEnd(14)} not installed`);
42
+ logger.warn(`${a.displayName.padEnd(14)} ${t('doctor.notInstalled')}`);
42
43
  if (r.hint)
43
44
  console.log(` ${chalk.dim(r.hint)}`);
44
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -1,23 +1,33 @@
1
1
  import chalk from 'chalk';
2
2
  import { AGENTS } from '../agents/registry.js';
3
- const MODE_LABEL = {
4
- 'auto-npm': 'auto (npm)',
5
- 'auto-pip': 'semi (pip)',
6
- 'manual-vscode': 'config-only (VSCode)',
7
- manual: 'manual',
8
- };
3
+ import { t } from '../i18n/index.js';
4
+ // Resolved at call time so it follows the active locale.
5
+ function modeLabel(mode) {
6
+ switch (mode) {
7
+ case 'auto-npm':
8
+ return t('list.modeAutoNpm');
9
+ case 'auto-pip':
10
+ return t('list.modeAutoPip');
11
+ case 'manual-vscode':
12
+ return t('list.modeManualVscode');
13
+ case 'manual':
14
+ return t('list.modeManual');
15
+ default:
16
+ return mode;
17
+ }
18
+ }
9
19
  export async function listCommand() {
10
20
  console.log();
11
- console.log(chalk.bold('Supported agents:'));
21
+ console.log(chalk.bold(t('list.title')));
12
22
  console.log();
13
23
  for (const a of AGENTS) {
14
24
  const id = chalk.cyan(a.id.padEnd(10));
15
- const mode = chalk.dim(`[${MODE_LABEL[a.installMode] ?? a.installMode}]`);
25
+ const mode = chalk.dim(`[${modeLabel(a.installMode)}]`);
16
26
  console.log(` ${id} ${a.displayName.padEnd(14)} ${mode}`);
17
27
  console.log(` ${chalk.dim(a.description)}`);
18
28
  }
19
29
  console.log();
20
- console.log(chalk.dim('Usage: tokenmix <agent> [args...]'));
30
+ console.log(chalk.dim(t('list.usage')));
21
31
  console.log();
22
32
  }
23
33
  //# sourceMappingURL=list.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAE9C,MAAM,UAAU,GAA2B;IACzC,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,YAAY;IACxB,eAAe,EAAE,sBAAsB;IACvC,MAAM,EAAE,QAAQ;CACjB,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,OAAO,CAAC,GAAG,EAAE,CAAA;IACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAA;IAC5C,OAAO,CAAC,GAAG,EAAE,CAAA;IACb,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,WAAW,GAAG,CAAC,CAAA;QACzE,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;QAC1D,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;IAChD,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,CAAA;IACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAA;IAC3D,OAAO,CAAC,GAAG,EAAE,CAAA;AACf,CAAC"}
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAE,CAAC,EAAE,MAAM,kBAAkB,CAAA;AAEpC,yDAAyD;AACzD,SAAS,SAAS,CAAC,IAAY;IAC7B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU;YACb,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAA;QAC9B,KAAK,UAAU;YACb,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAA;QAC9B,KAAK,eAAe;YAClB,OAAO,CAAC,CAAC,uBAAuB,CAAC,CAAA;QACnC,KAAK,QAAQ;YACX,OAAO,CAAC,CAAC,iBAAiB,CAAC,CAAA;QAC7B;YACE,OAAO,IAAI,CAAA;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,OAAO,CAAC,GAAG,EAAE,CAAA;IACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IACxC,OAAO,CAAC,GAAG,EAAE,CAAA;IACb,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;QACvD,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;QAC1D,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;IAChD,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,CAAA;IACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IACvC,OAAO,CAAC,GAAG,EAAE,CAAA;AACf,CAAC"}
@@ -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,78 +28,81 @@ 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);
55
56
  await loginByKey(entered, baseUrl);
56
57
  return;
57
58
  }
59
+ // verification_uri_complete is optional per RFC 8628; fall back to the plain
60
+ // verification_uri (the user_code is shown separately just below either way).
61
+ const verifyUrl = auth.verification_uri_complete || auth.verification_uri;
58
62
  // Display user_code prominently
59
63
  console.log();
60
- console.log(' ' + chalk.dim('Open the link below and confirm this code:'));
64
+ console.log(' ' + chalk.dim(t('login.openLinkConfirm')));
61
65
  console.log();
62
66
  console.log(' ' + chalk.bold.cyan(auth.user_code));
63
67
  console.log();
64
- console.log(' ' + chalk.dim('Link:'));
65
- console.log(' ' + chalk.underline(auth.verification_uri_complete));
68
+ console.log(' ' + chalk.dim(t('login.link')));
69
+ console.log(' ' + chalk.underline(verifyUrl));
66
70
  console.log();
67
71
  // Try to open browser, but proceed even if it fails (headless / SSH)
68
72
  try {
69
- await openInBrowser(auth.verification_uri_complete);
70
- logger.dim(' (browser opened; if nothing happens, copy the link above)');
73
+ await openInBrowser(verifyUrl);
74
+ logger.dim(' ' + t('login.browserOpened'));
71
75
  }
72
76
  catch {
73
- logger.dim(' (could not open browser; copy the link above into one)');
77
+ logger.dim(' ' + t('login.browserFailed'));
74
78
  }
75
79
  console.log();
76
- 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 }));
77
81
  let lastReported = -1;
78
82
  try {
79
83
  const result = await pollDeviceToken(baseUrl, auth, (secondsRemaining) => {
80
84
  // Print a heartbeat at most every 15s so the terminal isn't silent
81
85
  if (lastReported < 0 || lastReported - secondsRemaining >= 15) {
82
86
  lastReported = secondsRemaining;
83
- logger.dim(` ... still waiting (${secondsRemaining}s remaining)`);
87
+ logger.dim(' ' + t('login.stillWaiting', { seconds: secondsRemaining }));
84
88
  }
85
89
  });
86
90
  await updateConfig({ apiKey: result.apiKey, apiBaseUrl: baseUrl });
87
91
  console.log();
88
92
  if (result.userEmail) {
89
- 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 }));
90
94
  }
91
95
  else {
92
- logger.success(`Logged in (API key #${result.apiKeyId})`);
96
+ logger.success(t('login.loggedInId', { id: result.apiKeyId }));
93
97
  }
94
- logger.info('Try `tokenmix opencode` to launch your first agent.');
98
+ logger.info(t('login.tryFirstAgent'));
95
99
  }
96
100
  catch (err) {
97
101
  console.log();
98
102
  if (err instanceof DeviceFlowError) {
99
103
  logger.error(err.message);
100
104
  if (err.code === 'expired_token' || err.code === 'timeout') {
101
- const retry = await confirm('Try again?', true);
105
+ const retry = await confirm(t('login.tryAgain'), true);
102
106
  if (retry) {
103
107
  await loginByDeviceFlow(baseUrl);
104
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,7 +1,27 @@
1
1
  import { logger } from '../utils/logger.js';
2
2
  import { clearConfig } from '../config/store.js';
3
+ import { AGENTS } from '../agents/registry.js';
4
+ import { t } from '../i18n/index.js';
3
5
  export async function logoutCommand() {
4
6
  await clearConfig();
5
- logger.success('Logged out. Credentials removed from this machine.');
7
+ logger.success(t('logout.done'));
8
+ // Also revert the config we injected into agents, so they stop routing through
9
+ // TokenMix with a key that's about to be gone. Best-effort and precise — each
10
+ // agent only removes what it recognizes as its own tokenmix config.
11
+ for (const agent of AGENTS) {
12
+ if (!agent.cleanup)
13
+ continue;
14
+ try {
15
+ const r = await agent.cleanup();
16
+ if (r.reverted) {
17
+ logger.success(t('logout.reverted', { name: agent.displayName }) + (r.configPath ? ` (${r.configPath})` : ''));
18
+ if (r.note)
19
+ logger.dim(` ${r.note}`);
20
+ }
21
+ }
22
+ catch {
23
+ // never block logout on agent cleanup
24
+ }
25
+ }
6
26
  }
7
27
  //# 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;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
- import { openInBrowser } from '../utils/browser.js';
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
- await openInBrowser(TOPUP_URL);
6
+ logger.step(t('topup.opening', { url: TOPUP_URL }));
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,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;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"}
@@ -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,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,156 @@
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
+ };
81
+ export const zh = {
82
+ 'common.notLoggedIn': '未登录,请先运行 `tokenmix login`。',
83
+ // login
84
+ 'login.keyMustStart': 'API 密钥应以 sk-tm- 开头',
85
+ 'login.verifying': '正在通过 {baseUrl} 校验 API 密钥 ...',
86
+ 'login.verifyFailed': 'API 密钥校验失败。请到 https://tokenmix.ai/dashboard/keys 核对',
87
+ 'login.loggedInHint': '登录成功。试试 `tokenmix opencode` 启动你的第一个 agent。',
88
+ 'login.noKey': '未提供 API 密钥。',
89
+ 'login.requesting': '正在请求设备授权 ...',
90
+ 'login.couldNotStart': '无法发起设备授权:{msg}',
91
+ 'login.fallbackPaste': '改用手动粘贴。可在 https://tokenmix.ai/dashboard/keys 获取 API 密钥',
92
+ 'login.openLinkConfirm': '打开下方链接并确认此验证码:',
93
+ 'login.link': '链接:',
94
+ 'login.browserOpened': '(已打开浏览器;若无反应,请复制上面的链接)',
95
+ 'login.browserFailed': '(无法打开浏览器;请复制上面的链接到浏览器打开)',
96
+ 'login.waiting': '等待授权({expires}s 后过期,每 {interval}s 轮询一次)...',
97
+ 'login.stillWaiting': '... 仍在等待(剩余 {seconds}s)',
98
+ 'login.loggedInAs': '已登录:{email}(API 密钥 #{id})',
99
+ 'login.loggedInId': '登录成功(API 密钥 #{id})',
100
+ 'login.tryFirstAgent': '试试 `tokenmix opencode` 启动你的第一个 agent。',
101
+ 'login.tryAgain': '重试?',
102
+ // agent install / configure / launch
103
+ 'agent.notInstalled': '{name} 尚未安装。',
104
+ 'agent.notInstallable': '{name} 无法通过 CLI 安装。',
105
+ 'agent.installPrompt': '{name} 尚未安装。现在安装?',
106
+ 'agent.installing': '正在安装 {name} ...',
107
+ 'agent.installed': '{name} 安装完成。',
108
+ 'agent.installFailed': '无法自动安装 {name}。',
109
+ 'agent.installFailHint1': '这通常是 npm 无权写入全局目录。可选方案:',
110
+ 'agent.installFailHint2': ' • 使用 Node 版本管理器(nvm / fnm / volta)—— 全局安装即无需 sudo;或',
111
+ 'agent.installFailHint3': ' • 自行安装:{cmd}',
112
+ 'agent.installFailHint4': '随后重新运行本命令 —— 你的 TokenMix 登录已保存。',
113
+ 'agent.configuring': '正在配置 {name} ...',
114
+ 'agent.wrote': '已写入 {path}',
115
+ 'agent.configReady': '{name} 配置已就绪。',
116
+ 'agent.launching': '正在启动 {name} ...',
117
+ // logout
118
+ 'logout.done': '已登出。凭据已从本机移除。',
119
+ 'logout.reverted': '已还原 {name} 配置',
120
+ // doctor
121
+ 'doctor.title': 'TokenMix CLI 诊断',
122
+ 'doctor.credentials': '凭据:',
123
+ 'doctor.apiKeyLabel': 'API 密钥:',
124
+ 'doctor.apiBaseLabel': 'API 地址:',
125
+ 'doctor.keyValid': 'API 密钥有效。',
126
+ 'doctor.keyInvalid': 'API 密钥校验未通过。请重新运行 `tokenmix login`。',
127
+ 'doctor.notLoggedIn': '未登录。请运行 `tokenmix login`。',
128
+ 'doctor.agentStatus': 'Agent 安装状态:',
129
+ 'doctor.installed': '已安装',
130
+ 'doctor.notInstalled': '未安装',
131
+ // list
132
+ 'list.title': '支持的 agent:',
133
+ 'list.usage': '用法:tokenmix <agent> [参数...]',
134
+ 'list.modeAutoNpm': '自动 (npm)',
135
+ 'list.modeAutoPip': '半自动 (pip)',
136
+ 'list.modeManualVscode': '仅配置 (VSCode)',
137
+ 'list.modeManual': '手动',
138
+ // models
139
+ 'models.none': '没有匹配该筛选条件的模型。',
140
+ 'models.typeChat': '对话',
141
+ 'models.typeEmbedding': '向量',
142
+ 'models.typeImage': '图像',
143
+ 'models.typeAudio': '音频',
144
+ 'models.typeVideo': '视频',
145
+ 'models.typeCompletion': '补全',
146
+ 'models.in': '输入',
147
+ 'models.out': '输出',
148
+ // prompt
149
+ 'prompt.pasteKey': '粘贴你的 TokenMix API 密钥(sk-tm-...)',
150
+ // browser
151
+ 'balance.opening': '正在打开仪表盘查看余额:{url}',
152
+ 'topup.opening': '正在打开充值页面:{url}',
153
+ 'browser.manual': '无法自动打开浏览器。请手动打开此链接:\n {url}',
154
+ };
155
+ export const catalogs = { en, zh };
156
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/i18n/messages.ts"],"names":[],"mappings":"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"}