natureco-cli 5.53.0 → 5.55.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "5.53.0",
3
+ "version": "5.55.0",
4
4
  "description": "OpenClaw'dan daha güvenli, daha hızlı, daha ucuz AI agent CLI. Multi-agent, self-evolving skills, audit log, maliyet optimizasyonu ve NatureCo platform-native.",
5
5
  "bin": {
6
6
  "natureco": "bin/natureco.js"
@@ -1,11 +1,15 @@
1
1
  const inquirer = require('../utils/inquirer-wrapper');
2
2
  const chalk = require('chalk');
3
3
  const acc = require('../utils/natureco-account');
4
+ const { getLang } = require('../utils/i18n');
5
+
6
+ const L = (tr, en) => (getLang() === 'en' ? en : tr);
4
7
 
5
8
  /**
6
- * `natureco account [login|logout|whoami]` — tek NatureCo hesabı (SSO).
7
- * developers.natureco.me API-KEY girişinden (`natureco login`) AYRIDIR:
8
- * bu, natureco.me hesabınla kişi kimliği; ekosistem geneli paylaşılır.
9
+ * `natureco account [login|logout|whoami]` — one NatureCo account (SSO).
10
+ * Separate from the developers.natureco.me API-KEY login (`natureco login`):
11
+ * this is your personal identity with your natureco.me account, shared
12
+ * across the whole ecosystem.
9
13
  */
10
14
  async function account(action) {
11
15
  const sub = (action || 'whoami').toLowerCase();
@@ -20,42 +24,42 @@ async function doLogin() {
20
24
  console.log(chalk.green.bold(' (•ᴥ•)'));
21
25
  console.log(chalk.green(' />🌿'));
22
26
  console.log('');
23
- console.log(chalk.green.bold(' NatureCo Hesabı — Giriş'));
24
- console.log(chalk.gray(' natureco.me hesabınla ekosistemin her yerinde tek kimlik.\n'));
27
+ console.log(chalk.green.bold(' ' + L('NatureCo Hesabı — Giriş', 'NatureCo Account — Sign in')));
28
+ console.log(chalk.gray(' ' + L('natureco.me hesabınla ekosistemin her yerinde tek kimlik.', 'One identity across the whole ecosystem with your natureco.me account.') + '\n'));
25
29
  console.log(chalk.gray(' ' + '─'.repeat(48)) + '\n');
26
30
 
27
31
  const { email } = await inquirer.prompt([{
28
32
  type: 'input',
29
33
  name: 'email',
30
- message: ' E-posta:',
31
- validate: (v) => (/.+@.+\..+/.test((v || '').trim()) ? true : 'Geçerli bir e-posta gir'),
34
+ message: L(' E-posta:', ' Email:'),
35
+ validate: (v) => (/.+@.+\..+/.test((v || '').trim()) ? true : L('Geçerli bir e-posta gir', 'Enter a valid email')),
32
36
  }]);
33
37
 
34
38
  const { method } = await inquirer.prompt([{
35
39
  type: 'list',
36
40
  name: 'method',
37
- message: ' Giriş yöntemi:',
41
+ message: L(' Giriş yöntemi:', ' Sign-in method:'),
38
42
  choices: [
39
- { name: 'Şifre', value: 'password' },
40
- { name: 'E-postama kod gönder (OTP)', value: 'otp' },
43
+ { name: L('Şifre', 'Password'), value: 'password' },
44
+ { name: L('E-postama kod gönder (OTP)', 'Email me a code (OTP)'), value: 'otp' },
41
45
  ],
42
46
  }]);
43
47
 
44
48
  try {
45
49
  if (method === 'password') {
46
- const { password } = await inquirer.prompt([{ type: 'password', name: 'password', message: ' Şifre:', mask: '*' }]);
47
- console.log(chalk.gray('\n Doğrulanıyor...'));
50
+ const { password } = await inquirer.prompt([{ type: 'password', name: 'password', message: L(' Şifre:', ' Password:'), mask: '*' }]);
51
+ console.log(chalk.gray('\n ' + L('Doğrulanıyor...', 'Verifying...')));
48
52
  await acc.loginWithPassword(email.trim(), password);
49
53
  } else {
50
- console.log(chalk.gray('\n Gönderiliyor...'));
54
+ console.log(chalk.gray('\n ' + L('Gönderiliyor...', 'Sending...')));
51
55
  await acc.sendOtp(email.trim());
52
- console.log(chalk.gray(' ') + chalk.cyan(email.trim()) + chalk.gray(' adresine e-posta gönderildi.'));
53
- console.log(chalk.gray(' 6 haneli kod geldiyse kodu, giriş linki geldiyse linki yapıştır.'));
56
+ console.log(chalk.gray(' ') + chalk.cyan(email.trim()) + chalk.gray(L(' adresine e-posta gönderildi.', ' — email sent.')));
57
+ console.log(chalk.gray(' ' + L('6 haneli kod geldiyse kodu, giriş linki geldiyse linki yapıştır.', 'Paste the 6-digit code, or the login link if you got one.')));
54
58
  const { token } = await inquirer.prompt([{
55
- type: 'input', name: 'token', message: ' Kod veya giriş linki:',
56
- validate: (v) => ((v || '').trim().length >= 6 ? true : 'Kodu ya da linki gir'),
59
+ type: 'input', name: 'token', message: L(' Kod veya giriş linki:', ' Code or login link:'),
60
+ validate: (v) => ((v || '').trim().length >= 6 ? true : L('Kodu ya da linki gir', 'Enter the code or link')),
57
61
  }]);
58
- console.log(chalk.gray('\n Doğrulanıyor...'));
62
+ console.log(chalk.gray('\n ' + L('Doğrulanıyor...', 'Verifying...')));
59
63
  const val = token.trim();
60
64
  if (/^https?:\/\//i.test(val) || val.includes('token')) {
61
65
  await acc.verifyLink(val);
@@ -64,41 +68,41 @@ async function doLogin() {
64
68
  }
65
69
  }
66
70
  } catch (err) {
67
- console.log(chalk.red(`\n ❌ ${err.message || 'Giriş başarısız'}\n`));
71
+ console.log(chalk.red(`\n ❌ ${err.message || L('Giriş başarısız', 'Sign-in failed')}\n`));
68
72
  process.exit(1);
69
73
  }
70
74
 
71
75
  const me = await acc.whoami();
72
- console.log(chalk.green('\n ✓ Giriş başarılı!'));
73
- if (me && me.email) console.log(chalk.gray(' Hoş geldin, ') + chalk.white(me.email));
74
- console.log(chalk.gray(' Oturum: ~/.natureco/auth.json'));
76
+ console.log(chalk.green('\n ✓ ' + L('Giriş başarılı!', 'Signed in!')));
77
+ if (me && me.email) console.log(chalk.gray(' ' + L('Hoş geldin, ', 'Welcome, ')) + chalk.white(me.email));
78
+ console.log(chalk.gray(' ' + L('Oturum: ', 'Session: ') + '~/.natureco/auth.json'));
75
79
  console.log('');
76
80
  }
77
81
 
78
82
  async function doLogout() {
79
83
  if (!acc.isLoggedIn()) {
80
- console.log(chalk.gray('\n Zaten giriş yapılmamış.\n'));
84
+ console.log(chalk.gray('\n ' + L('Zaten giriş yapılmamış.', 'Not signed in.') + '\n'));
81
85
  return;
82
86
  }
83
87
  const who = acc.currentEmail();
84
88
  acc.logout();
85
- console.log(chalk.green(`\n ✓ Çıkış yapıldı${who ? ' (' + who + ')' : ''}.\n`));
89
+ console.log(chalk.green('\n ✓ ' + L('Çıkış yapıldı', 'Signed out') + `${who ? ' (' + who + ')' : ''}.\n`));
86
90
  }
87
91
 
88
92
  async function doWhoami() {
89
93
  if (!acc.isLoggedIn()) {
90
- console.log(chalk.gray('\n NatureCo hesabına giriş yapılmamış.'));
91
- console.log(chalk.gray(' Giriş: ') + chalk.cyan('natureco account login') + '\n');
94
+ console.log(chalk.gray('\n ' + L('NatureCo hesabına giriş yapılmamış.', 'Not signed in to a NatureCo account.')));
95
+ console.log(chalk.gray(' ' + L('Giriş: ', 'Sign in: ')) + chalk.cyan('natureco account login') + '\n');
92
96
  return;
93
97
  }
94
- console.log(chalk.gray('\n Doğrulanıyor...'));
98
+ console.log(chalk.gray('\n ' + L('Doğrulanıyor...', 'Verifying...')));
95
99
  const me = await acc.whoami();
96
100
  if (!me) {
97
- console.log(chalk.yellow('\n ⚠ Oturum süresi dolmuş görünüyor. Tekrar giriş yap: ') + chalk.cyan('natureco account login') + '\n');
101
+ console.log(chalk.yellow('\n ⚠ ' + L('Oturum süresi dolmuş görünüyor. Tekrar giriş yap: ', 'Your session looks expired. Sign in again: ')) + chalk.cyan('natureco account login') + '\n');
98
102
  return;
99
103
  }
100
- console.log(chalk.green.bold('\n ⬡ NatureCo Hesabı'));
101
- console.log(chalk.gray(' E-posta: ') + chalk.white(me.email || '-'));
104
+ console.log(chalk.green.bold('\n ⬡ ' + L('NatureCo Hesabı', 'NatureCo Account')));
105
+ console.log(chalk.gray(' ' + L('E-posta: ', 'Email: ')) + chalk.white(me.email || '-'));
102
106
  console.log(chalk.gray(' ID: ') + chalk.gray(me.id || '-'));
103
107
  console.log('');
104
108
  }
@@ -1,4 +1,6 @@
1
- const chalk = require('chalk');
1
+ const chalk = require('chalk');
2
+ const { getLang: _getLang } = require('../utils/i18n');
3
+ const L = (tr, en) => (_getLang() === 'en' ? en : tr);
2
4
  const { getApiKey, getConfig } = require('../utils/config');
3
5
  const { getBots, sendMessage } = require('../utils/api');
4
6
  const { getSkillPrompts } = require('../utils/skills');
@@ -9,7 +11,7 @@ async function ask(question, options = {}) {
9
11
  const apiKey = getApiKey();
10
12
 
11
13
  if (!apiKey) {
12
- console.log(chalk.red('\n❌ Giriş yapılmamış. Önce "natureco login" çalıştırın.\n'));
14
+ console.log(chalk.red(L('\n❌ Giriş yapılmamış. Önce "natureco login" çalıştırın.\n', '\n❌ Not signed in. Run "natureco login" first.\n')));
13
15
  process.exit(1);
14
16
  }
15
17
 
@@ -26,7 +28,7 @@ async function ask(question, options = {}) {
26
28
  }
27
29
 
28
30
  if (!defaultBotId) {
29
- console.log(chalk.red('\n❌ Hiç bot bulunamadı. "natureco chat" ile yerel sağlayıcıyı kullanabilir ya da bir bot oluşturabilirsiniz.\n'));
31
+ console.log(chalk.red(L('\n❌ Hiç bot bulunamadı. "natureco chat" ile yerel sağlayıcıyı kullanabilir ya da bir bot oluşturabilirsiniz.\n', '\n❌ No bots found. Use "natureco chat" for the local provider, or create a bot.\n')));
30
32
  process.exit(1);
31
33
  }
32
34
 
@@ -5,7 +5,9 @@ const readline = require('readline');
5
5
  const inquirer = require('../utils/inquirer-wrapper');
6
6
  const TB = require('../utils/token-budget');
7
7
  const tui = require('../utils/tui');
8
- const chalk = require('chalk');
8
+ const chalk = require('chalk');
9
+ const { getLang: _getLang } = require('../utils/i18n');
10
+ const L = (tr, en) => (_getLang() === 'en' ? en : tr);
9
11
  const { getApiKey, getConfig } = require('../utils/config');
10
12
  const repl = require('./repl');
11
13
  const { getSkillPrompts, getSkills } = require('../utils/skills');
@@ -273,7 +275,7 @@ async function chat(botName, options = {}) {
273
275
  session = createSession(bot.id, bot.name);
274
276
  console.log(chalk.green(`Bot değişti: ${newBot.name}`));
275
277
  } else {
276
- console.log(chalk.red(`Bot bulunamadı: ${newName}`));
278
+ console.log(chalk.red(`${L('Bot bulunamadı', 'Bot not found')}: ${newName}`));
277
279
  }
278
280
  }
279
281
  console.log();
@@ -300,7 +302,7 @@ async function chat(botName, options = {}) {
300
302
  console.log();
301
303
  return;
302
304
  case 'help':
303
- console.log(chalk.yellow('Chat Komutları:'));
305
+ console.log(chalk.yellow(L('Chat Komutları:', 'Chat commands:')));
304
306
  [
305
307
  ['/clear', 'Ekranı temizle'],
306
308
  ['/bot [ad]', 'Bot değiştir'],
@@ -1,41 +1,44 @@
1
1
  /**
2
- * natureco cost — Maliyet takibi ve bütçe yönetimi (Phase 4)
2
+ * natureco cost — cost tracking and budget management (Phase 4)
3
3
  *
4
- * Kullanım:
5
- * natureco cost Bugünün maliyetini göster
6
- * natureco cost today Bugünkü maliyet
7
- * natureco cost week Bu haftaki maliyet
8
- * natureco cost month Bu ayki maliyet
9
- * natureco cost all Tüm zamanlar
10
- * natureco cost budget Bütçe durumu ve uyarılar
11
- * natureco cost set <key> <val> Bütçe ayarla (dailyLimit 5, monthlyLimit 100, warnAt 0.75)
12
- * natureco cost model <prompt> Bir prompt için önerilen modeli göster
13
- * natureco cost prices Tüm fiyatları listele
4
+ * Usage:
5
+ * natureco cost Show today's cost
6
+ * natureco cost today Today's cost
7
+ * natureco cost week This week's cost
8
+ * natureco cost month This month's cost
9
+ * natureco cost all All time
10
+ * natureco cost budget Budget status and warnings
11
+ * natureco cost set <key> <val> Set a budget (dailyLimit 5, monthlyLimit 100, warnAt 0.75)
12
+ * natureco cost model <prompt> Show the suggested model for a prompt
13
+ * natureco cost prices List all prices
14
14
  */
15
15
 
16
16
  const chalk = require('chalk');
17
17
  const tui = require('../utils/tui');
18
18
  const cost = require('../utils/cost-tracker');
19
19
  const audit = require('../utils/audit');
20
+ const { getLang } = require('../utils/i18n');
21
+
22
+ const L = (tr, en) => (getLang() === 'en' ? en : tr);
20
23
 
21
24
  function showPeriod(period) {
22
25
  const data = cost.totalForPeriod(period);
23
26
  const icon = { today: '📅', week: '📆', month: '🗓️', all: '♾️ ' }[period] || '💰';
24
- console.log(tui.styled(`\n ${icon} Maliyet Raporu · ${period.toUpperCase()}`, { color: tui.PALETTE.primary, bold: true }));
27
+ console.log(tui.styled(`\n ${icon} ${L('Maliyet Raporu', 'Cost Report')} · ${period.toUpperCase()}`, { color: tui.PALETTE.primary, bold: true }));
25
28
  console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
26
29
 
27
- // Üst metrik kartı
30
+ // Top metric card
28
31
  const cardWidth = 54;
29
32
  const cardLines = [];
30
33
  cardLines.push(tui.styled(' ╭' + '─'.repeat(cardWidth) + '╮', { color: tui.PALETTE.border }));
31
- cardLines.push(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted('Toplam maliyet:') + ' ' + tui.styled(cost.formatUSD(data.totalCost).padStart(12), { color: tui.PALETTE.primary, bold: true }) + ' ' + tui.styled('│', { color: tui.PALETTE.border }));
32
- cardLines.push(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted('Toplam token:') + ' ' + tui.C.text((data.totalInput + data.totalOutput).toLocaleString().padStart(8) + ` (${data.totalInput.toLocaleString()} in / ${data.totalOutput.toLocaleString()} out)`) + ' ' + tui.styled('│', { color: tui.PALETTE.border }));
33
- cardLines.push(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted('Çağrı sayısı:') + ' ' + tui.C.text(String(data.entries).padStart(8)) + ' ' + tui.styled('│', { color: tui.PALETTE.border }));
34
+ cardLines.push(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted(L('Toplam maliyet:', 'Total cost:')) + ' ' + tui.styled(cost.formatUSD(data.totalCost).padStart(12), { color: tui.PALETTE.primary, bold: true }) + ' ' + tui.styled('│', { color: tui.PALETTE.border }));
35
+ cardLines.push(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted(L('Toplam token:', 'Total tokens:')) + ' ' + tui.C.text((data.totalInput + data.totalOutput).toLocaleString().padStart(8) + ` (${data.totalInput.toLocaleString()} in / ${data.totalOutput.toLocaleString()} out)`) + ' ' + tui.styled('│', { color: tui.PALETTE.border }));
36
+ cardLines.push(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted(L('Çağrı sayısı:', 'Calls:')) + ' ' + tui.C.text(String(data.entries).padStart(8)) + ' ' + tui.styled('│', { color: tui.PALETTE.border }));
34
37
  cardLines.push(tui.styled(' ╰' + '─'.repeat(cardWidth) + '╯', { color: tui.PALETTE.border }));
35
38
  console.log(cardLines.join('\n'));
36
39
 
37
40
  if (Object.keys(data.byProvider).length > 0) {
38
- console.log('\n' + tui.styled(' 💵 Provider Bazlı Maliyet', { color: tui.PALETTE.secondary, bold: true }));
41
+ console.log('\n' + tui.styled(' 💵 ' + L('Provider Bazlı Maliyet', 'Cost by Provider'), { color: tui.PALETTE.secondary, bold: true }));
39
42
  const providerRows = Object.entries(data.byProvider)
40
43
  .sort((a, b) => b[1] - a[1])
41
44
  .map(([provider, amount]) => ({
@@ -45,13 +48,13 @@ function showPeriod(period) {
45
48
  }));
46
49
  console.log('\n' + tui.table(providerRows, [
47
50
  { key: 'provider', label: 'Provider', minWidth: 12 },
48
- { key: 'amount', label: 'Maliyet', minWidth: 10, render: r => tui.C.brand(r.amount) },
49
- { key: 'pct', label: 'Dağılım', minWidth: 20, render: r => tui.styled(r.pct, { color: tui.PALETTE.primary }) },
51
+ { key: 'amount', label: L('Maliyet', 'Cost'), minWidth: 10, render: r => tui.C.brand(r.amount) },
52
+ { key: 'pct', label: L('Dağılım', 'Distribution'), minWidth: 20, render: r => tui.styled(r.pct, { color: tui.PALETTE.primary }) },
50
53
  ], { borderStyle: 'round', zebra: true }));
51
54
  }
52
55
 
53
56
  if (Object.keys(data.byModel).length > 0) {
54
- console.log('\n' + tui.styled(' 🤖 Model Bazlı Maliyet (Top 5)', { color: tui.PALETTE.accent, bold: true }));
57
+ console.log('\n' + tui.styled(' 🤖 ' + L('Model Bazlı Maliyet (Top 5)', 'Cost by Model (Top 5)'), { color: tui.PALETTE.accent, bold: true }));
55
58
  const sortedModels = Object.entries(data.byModel).sort((a, b) => b[1] - a[1]).slice(0, 5);
56
59
  const modelRows = sortedModels.map(([model, amount]) => ({
57
60
  model,
@@ -59,7 +62,7 @@ function showPeriod(period) {
59
62
  }));
60
63
  console.log('\n' + tui.table(modelRows, [
61
64
  { key: 'model', label: 'Model', minWidth: 40, render: r => tui.C.muted(r.model) },
62
- { key: 'amount', label: 'Maliyet', minWidth: 10, render: r => tui.C.brand(r.amount) },
65
+ { key: 'amount', label: L('Maliyet', 'Cost'), minWidth: 10, render: r => tui.C.brand(r.amount) },
63
66
  ], { borderStyle: 'round', zebra: true }));
64
67
  }
65
68
  console.log('');
@@ -69,52 +72,52 @@ function showBudget() {
69
72
  const status = cost.checkBudget();
70
73
  const budget = cost.loadBudget();
71
74
 
72
- console.log('\n' + tui.styled(' 🛡️ Bütçe Durumu', { color: tui.PALETTE.primary, bold: true }));
75
+ console.log('\n' + tui.styled(' 🛡️ ' + L('Bütçe Durumu', 'Budget Status'), { color: tui.PALETTE.primary, bold: true }));
73
76
  console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
74
77
 
75
- // Günlük
78
+ // Daily
76
79
  const dailyBar = tui.progressBar(status.daily.usage, 1, {
77
80
  width: 25, showPercent: true,
78
81
  fillChar: status.daily.exceeded ? '▓' : status.daily.warning ? '▒' : '█',
79
82
  });
80
83
  const dailyColor = status.daily.exceeded ? tui.PALETTE.danger : status.daily.warning ? tui.PALETTE.warning : tui.PALETTE.success;
81
- console.log(`\n ${tui.C.muted('Günlük limit')} ${tui.C.brand(cost.formatUSD(budget.dailyLimit).padStart(10))} ${tui.styled(dailyBar, { color: dailyColor })}`);
82
- if (status.daily.exceeded) console.log(' ' + tui.styled('⚠️ Günlük limit aşıldı!', { color: tui.PALETTE.danger, bold: true }));
83
- else if (status.daily.warning) console.log(' ' + tui.styled(`⚠️ %${(budget.warnAt * 100)} eşiğine yaklaşıldı`, { color: tui.PALETTE.warning }));
84
+ console.log(`\n ${tui.C.muted(L('Günlük limit', 'Daily limit'))} ${tui.C.brand(cost.formatUSD(budget.dailyLimit).padStart(10))} ${tui.styled(dailyBar, { color: dailyColor })}`);
85
+ if (status.daily.exceeded) console.log(' ' + tui.styled('⚠️ ' + L('Günlük limit aşıldı!', 'Daily limit exceeded!'), { color: tui.PALETTE.danger, bold: true }));
86
+ else if (status.daily.warning) console.log(' ' + tui.styled('⚠️ ' + L(`%${(budget.warnAt * 100)} eşiğine yaklaşıldı`, `approaching the ${(budget.warnAt * 100)}% threshold`), { color: tui.PALETTE.warning }));
84
87
 
85
88
  console.log('');
86
89
 
87
- // Aylık
90
+ // Monthly
88
91
  const monthlyBar = tui.progressBar(status.monthly.usage, 1, {
89
92
  width: 25, showPercent: true,
90
93
  fillChar: status.monthly.exceeded ? '▓' : status.monthly.warning ? '▒' : '█',
91
94
  });
92
95
  const monthlyColor = status.monthly.exceeded ? tui.PALETTE.danger : status.monthly.warning ? tui.PALETTE.warning : tui.PALETTE.success;
93
- console.log(` ${tui.C.muted('Aylık limit')} ${tui.C.brand(cost.formatUSD(budget.monthlyLimit).padStart(10))} ${tui.styled(monthlyBar, { color: monthlyColor })}`);
94
- if (status.monthly.exceeded) console.log(' ' + tui.styled('⚠️ Aylık limit aşıldı!', { color: tui.PALETTE.danger, bold: true }));
95
- else if (status.monthly.warning) console.log(' ' + tui.styled(`⚠️ %${(budget.warnAt * 100)} eşiğine yaklaşıldı`, { color: tui.PALETTE.warning }));
96
+ console.log(` ${tui.C.muted(L('Aylık limit', 'Monthly limit'))} ${tui.C.brand(cost.formatUSD(budget.monthlyLimit).padStart(10))} ${tui.styled(monthlyBar, { color: monthlyColor })}`);
97
+ if (status.monthly.exceeded) console.log(' ' + tui.styled('⚠️ ' + L('Aylık limit aşıldı!', 'Monthly limit exceeded!'), { color: tui.PALETTE.danger, bold: true }));
98
+ else if (status.monthly.warning) console.log(' ' + tui.styled('⚠️ ' + L(`%${(budget.warnAt * 100)} eşiğine yaklaşıldı`, `approaching the ${(budget.warnAt * 100)}% threshold`), { color: tui.PALETTE.warning }));
96
99
 
97
100
  if (status.shouldDowngrade) {
98
- console.log('\n' + tui.styled(' ⬇️ Otomatik downgrade önerilir — basit soruları ucuz modele yönlendir.', { color: tui.PALETTE.warning, bold: true }));
101
+ console.log('\n' + tui.styled(' ⬇️ ' + L('Otomatik downgrade önerilir — basit soruları ucuz modele yönlendir.', 'Auto-downgrade recommended — route simple questions to a cheaper model.'), { color: tui.PALETTE.warning, bold: true }));
99
102
  }
100
103
 
101
- console.log('\n' + tui.C.muted(' Ayarlamak için: ') + tui.C.brand('natureco cost set <key> <value>'));
104
+ console.log('\n' + tui.C.muted(' ' + L('Ayarlamak için: ', 'To configure: ')) + tui.C.brand('natureco cost set <key> <value>'));
102
105
  console.log('');
103
106
  }
104
107
 
105
108
  function setBudget(args) {
106
109
  const [key, value] = args;
107
110
  if (!key || value === undefined) {
108
- console.log(chalk.red('\n Kullanım: natureco cost set <key> <value>\n'));
109
- console.log(chalk.gray(' Anahtarlar: dailyLimit, monthlyLimit, warnAt, downgradeAt'));
110
- console.log(chalk.gray(' Örnek: natureco cost set dailyLimit 3.00'));
111
+ console.log(chalk.red('\n ' + L('Kullanım: natureco cost set <key> <value>', 'Usage: natureco cost set <key> <value>') + '\n'));
112
+ console.log(chalk.gray(' ' + L('Anahtarlar: dailyLimit, monthlyLimit, warnAt, downgradeAt', 'Keys: dailyLimit, monthlyLimit, warnAt, downgradeAt')));
113
+ console.log(chalk.gray(' ' + L('Örnek: natureco cost set dailyLimit 3.00', 'Example: natureco cost set dailyLimit 3.00')));
111
114
  console.log('');
112
115
  return;
113
116
  }
114
117
  const budget = cost.loadBudget();
115
118
  const num = parseFloat(value);
116
119
  if (isNaN(num) && key !== 'preset') {
117
- console.log(chalk.red(`\n Geçersiz sayı: ${value}\n`));
120
+ console.log(chalk.red(`\n ${L('Geçersiz sayı', 'Invalid number')}: ${value}\n`));
118
121
  return;
119
122
  }
120
123
  budget[key] = num;
@@ -126,25 +129,25 @@ function setBudget(args) {
126
129
  function suggestModel(args) {
127
130
  const prompt = args.join(' ');
128
131
  if (!prompt) {
129
- console.log(chalk.red('\n Kullanım: natureco cost model "<prompt>"\n'));
132
+ console.log(chalk.red('\n ' + L('Kullanım: natureco cost model "<prompt>"', 'Usage: natureco cost model "<prompt>"') + '\n'));
130
133
  return;
131
134
  }
132
135
  const suggestion = cost.suggestModel(prompt);
133
136
  if (!suggestion) return;
134
137
 
135
- console.log(chalk.bold('\n 🎯 Model Önerisi\n'));
136
- console.log(chalk.gray(' Prompt karmaşıklığı: ') + chalk.cyan(suggestion.complexity));
138
+ console.log(chalk.bold('\n 🎯 ' + L('Model Önerisi', 'Model Suggestion') + '\n'));
139
+ console.log(chalk.gray(' ' + L('Prompt karmaşıklığı: ', 'Prompt complexity: ')) + chalk.cyan(suggestion.complexity));
137
140
  console.log(chalk.gray(` ${cost.ROUTING[suggestion.complexity].description}\n`));
138
- console.log(chalk.gray(' Önerilen model: ') + chalk.bold(`${suggestion.provider}:${suggestion.model}`));
139
- console.log(chalk.gray(' Neden: ') + chalk.gray(suggestion.reason));
141
+ console.log(chalk.gray(' ' + L('Önerilen model: ', 'Suggested model: ')) + chalk.bold(`${suggestion.provider}:${suggestion.model}`));
142
+ console.log(chalk.gray(' ' + L('Neden: ', 'Reason: ')) + chalk.gray(suggestion.reason));
140
143
 
141
144
  const pricing = cost.getPricing(suggestion.provider, suggestion.model);
142
- console.log(chalk.gray(' Fiyat: ') + chalk.cyan(`${cost.formatUSD(pricing.input)} in / ${cost.formatUSD(pricing.output)} out (per 1M)`));
145
+ console.log(chalk.gray(' ' + L('Fiyat: ', 'Price: ')) + chalk.cyan(`${cost.formatUSD(pricing.input)} in / ${cost.formatUSD(pricing.output)} out (per 1M)`));
143
146
 
144
147
  if (suggestion.optimal) {
145
- console.log(chalk.green('\n ✓ Mevcut model zaten optimal.\n'));
148
+ console.log(chalk.green('\n ✓ ' + L('Mevcut model zaten optimal.', 'Current model is already optimal.') + '\n'));
146
149
  } else {
147
- console.log(chalk.yellow('\n ⚠️ Mevcut model optimal değil. Değiştirmek için:'));
150
+ console.log(chalk.yellow('\n ⚠️ ' + L('Mevcut model optimal değil. Değiştirmek için:', 'Current model is not optimal. To change it:')));
148
151
  console.log(chalk.cyan(` natureco config set providerUrl <url>`));
149
152
  console.log(chalk.cyan(` natureco config set providerModel ${suggestion.model}`));
150
153
  console.log('');
@@ -152,10 +155,10 @@ function suggestModel(args) {
152
155
  }
153
156
 
154
157
  function showPrices() {
155
- console.log(chalk.bold('\n 💵 Model Fiyatları (USD / 1M token)\n'));
158
+ console.log(chalk.bold('\n 💵 ' + L('Model Fiyatları (USD / 1M token)', 'Model Prices (USD / 1M tokens)') + '\n'));
156
159
  console.log(chalk.gray(' ' + '─'.repeat(60)));
157
160
 
158
- // Provider'lara göre grupla
161
+ // Group by provider
159
162
  const grouped = {};
160
163
  for (const [key, price] of Object.entries(cost.PRICING)) {
161
164
  const [provider] = key.split(':');
@@ -166,8 +169,8 @@ function showPrices() {
166
169
  for (const [provider, models] of Object.entries(grouped)) {
167
170
  console.log(chalk.bold(`\n ${provider.toUpperCase()}`));
168
171
  for (const m of models) {
169
- const inPrice = m.input === 0 ? chalk.green('ücretsiz') : cost.formatUSD(m.input);
170
- const outPrice = m.output === 0 ? chalk.green('ücretsiz') : cost.formatUSD(m.output);
172
+ const inPrice = m.input === 0 ? chalk.green(L('ücretsiz', 'free')) : cost.formatUSD(m.input);
173
+ const outPrice = m.output === 0 ? chalk.green(L('ücretsiz', 'free')) : cost.formatUSD(m.output);
171
174
  console.log(` ${m.model.padEnd(40)} ${inPrice.padStart(10)} in ${outPrice.padStart(10)} out`);
172
175
  }
173
176
  }
@@ -194,16 +197,16 @@ function cost_cmd(args) {
194
197
 
195
198
  if (action === 'prices') { showPrices(); return; }
196
199
 
197
- // Yardım
198
- console.log(chalk.yellow('\n Kullanım:'));
199
- console.log(chalk.gray(' natureco cost Bugünün maliyeti'));
200
- console.log(chalk.gray(' natureco cost week Bu hafta'));
201
- console.log(chalk.gray(' natureco cost month Bu ay'));
202
- console.log(chalk.gray(' natureco cost all Tüm zamanlar'));
203
- console.log(chalk.gray(' natureco cost budget Bütçe durumu'));
204
- console.log(chalk.gray(' natureco cost set <k> <v> Bütçe ayarla'));
205
- console.log(chalk.gray(' natureco cost model "<p>" Model önerisi'));
206
- console.log(chalk.gray(' natureco cost prices Fiyat listesi'));
200
+ // Help
201
+ console.log(chalk.yellow('\n ' + L('Kullanım:', 'Usage:')));
202
+ console.log(chalk.gray(' natureco cost ' + L('Bugünün maliyeti', "Today's cost")));
203
+ console.log(chalk.gray(' natureco cost week ' + L('Bu hafta', 'This week')));
204
+ console.log(chalk.gray(' natureco cost month ' + L('Bu ay', 'This month')));
205
+ console.log(chalk.gray(' natureco cost all ' + L('Tüm zamanlar', 'All time')));
206
+ console.log(chalk.gray(' natureco cost budget ' + L('Bütçe durumu', 'Budget status')));
207
+ console.log(chalk.gray(' natureco cost set <k> <v> ' + L('Bütçe ayarla', 'Set a budget')));
208
+ console.log(chalk.gray(' natureco cost model "<p>" ' + L('Model önerisi', 'Model suggestion')));
209
+ console.log(chalk.gray(' natureco cost prices ' + L('Fiyat listesi', 'Price list')));
207
210
  console.log('');
208
211
  }
209
212