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 +1 -1
- package/src/commands/account.js +34 -30
- package/src/commands/ask.js +5 -3
- package/src/commands/chat.js +5 -3
- package/src/commands/cost.js +61 -58
- package/src/commands/help.js +230 -226
- package/src/commands/login.js +58 -55
- package/src/commands/memory-cmd.js +70 -68
- package/src/commands/models.js +623 -621
- package/src/commands/repl.js +11 -9
- package/src/commands/run.js +8 -6
- package/src/utils/dangerous.js +19 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "natureco-cli",
|
|
3
|
-
"version": "5.
|
|
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"
|
package/src/commands/account.js
CHANGED
|
@@ -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]` —
|
|
7
|
-
* developers.natureco.me API-KEY
|
|
8
|
-
*
|
|
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
|
|
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
|
|
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(
|
|
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
|
}
|
package/src/commands/ask.js
CHANGED
|
@@ -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
|
|
package/src/commands/chat.js
CHANGED
|
@@ -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(
|
|
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'],
|
package/src/commands/cost.js
CHANGED
|
@@ -1,41 +1,44 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* natureco cost —
|
|
2
|
+
* natureco cost — cost tracking and budget management (Phase 4)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* natureco cost
|
|
6
|
-
* natureco cost today
|
|
7
|
-
* natureco cost week
|
|
8
|
-
* natureco cost month
|
|
9
|
-
* natureco cost all
|
|
10
|
-
* natureco cost budget
|
|
11
|
-
* natureco cost set <key> <val>
|
|
12
|
-
* natureco cost model <prompt>
|
|
13
|
-
* natureco cost prices
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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(
|
|
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
|
-
//
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
|