natureco-cli 5.52.1 → 5.53.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/bin/natureco.js CHANGED
@@ -14,6 +14,7 @@ const login = require('../src/commands/login');
14
14
  const logout = require('../src/commands/logout');
15
15
  const account = require('../src/commands/account');
16
16
  const dna = require('../src/commands/dna');
17
+ const lang = require('../src/commands/lang');
17
18
  const bots = require('../src/commands/bots');
18
19
  const chat = require('../src/commands/chat');
19
20
  const help = require('../src/commands/help');
@@ -213,6 +214,11 @@ program
213
214
  .option('--max <n>', 'En fazla taranacak dosya sayısı')
214
215
  .action(dna);
215
216
 
217
+ program
218
+ .command('lang [code]')
219
+ .description('Arayüz dili / Interface language (tr | en)')
220
+ .action(lang);
221
+
216
222
  program
217
223
  .command('setup [action]')
218
224
  .description('Run initial setup wizard (wizard|config|workspace|dirs|status)')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "5.52.1",
3
+ "version": "5.53.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,5 +1,6 @@
1
1
  const chalk = require('chalk');
2
2
  const { spawnSync } = require('child_process');
3
+ const { t } = require('../utils/i18n');
3
4
 
4
5
  /**
5
6
  * `natureco dna [path]` — CodeDNA ile kod şeffaflığı.
@@ -21,9 +22,9 @@ async function dna(pathArg, opts = {}) {
21
22
 
22
23
  if (res.error && res.error.code === 'ENOENT') {
23
24
  console.log('');
24
- console.log(chalk.yellow(' CodeDNA kurulu değil.'));
25
- console.log(chalk.gray(' Kurmak için: ') + chalk.cyan('pip install codedna') + chalk.gray(' (veya ') + chalk.cyan('uv tool install codedna') + chalk.gray(')'));
26
- console.log(chalk.gray(' CodeDNA, kodun ne kadarının yapay zekâ olduğunu ölçen NatureCo aracıdır.\n'));
25
+ console.log(chalk.yellow(' ' + t('dna.notInstalled')));
26
+ console.log(chalk.gray(' ' + t('dna.installHint') + ' ') + chalk.cyan('pip install codedna') + chalk.gray(' (uv tool install codedna)'));
27
+ console.log(chalk.gray(' ' + t('dna.installDesc') + '\n'));
27
28
  process.exitCode = 1;
28
29
  return;
29
30
  }
@@ -32,7 +33,7 @@ async function dna(pathArg, opts = {}) {
32
33
  try {
33
34
  data = JSON.parse(res.stdout);
34
35
  } catch (_e) {
35
- console.log(chalk.red(' CodeDNA çıktısı okunamadı.'));
36
+ console.log(chalk.red(' ' + t('dna.unreadable')));
36
37
  if (res.stderr) console.log(chalk.gray(res.stderr.trim().split('\n').slice(0, 4).join('\n')));
37
38
  process.exitCode = 1;
38
39
  return;
@@ -49,9 +50,10 @@ async function dna(pathArg, opts = {}) {
49
50
  console.log('');
50
51
  console.log(' ' + chalk.bold.cyan('🧬 CodeDNA') + chalk.gray(' · ' + (data.repo || target)));
51
52
  console.log('');
52
- console.log(' ' + chalk.gray('Ortalama YZ olasılığı ') + tone(pct)(bar(pct)) + ' ' + tone(pct).bold(`%${pct}`));
53
- console.log(' ' + chalk.gray('En yüksek dosya ') + tone(maxPct)(bar(maxPct)) + ' ' + tone(maxPct).bold(`%${maxPct}`));
54
- console.log(' ' + chalk.gray(`Taranan dosya: ${data.file_count || 0}`));
53
+ const pad = (s) => (s + ' ').slice(0, 22);
54
+ console.log(' ' + chalk.gray(pad(t('dna.avgAi'))) + tone(pct)(bar(pct)) + ' ' + tone(pct).bold(`%${pct}`));
55
+ console.log(' ' + chalk.gray(pad(t('dna.maxFile'))) + tone(maxPct)(bar(maxPct)) + ' ' + tone(maxPct).bold(`%${maxPct}`));
56
+ console.log(' ' + chalk.gray(t('dna.scanned', { n: data.file_count || 0 })));
55
57
  console.log('');
56
58
 
57
59
  // Anlama skoru (1-5): anket varsa onu, yoksa otomatik tahmini kullan
@@ -61,11 +63,11 @@ async function dna(pathArg, opts = {}) {
61
63
  // En yüksek YZ olasılıklı 5 dosya
62
64
  const top = (data.files || []).slice(0, 5);
63
65
  if (top.length) {
64
- console.log(' ' + chalk.gray('En yüksek YZ olasılıklı dosyalar:'));
66
+ console.log(' ' + chalk.gray(t('dna.topFiles')));
65
67
  for (const f of top) {
66
68
  const fp = Math.round((f.ai_probability || 0) * 100);
67
69
  const uv = uScore(f);
68
- const u = uv == null ? '' : ' ' + uCol(uv)(`anlama ${uv.toFixed(1)}/5`);
70
+ const u = uv == null ? '' : ' ' + uCol(uv)(`${t('dna.understanding')} ${uv.toFixed(1)}/5`);
69
71
  console.log(' ' + tone(fp).bold(`%${String(fp).padStart(3)}`) + ' ' + chalk.white(f.file) + u);
70
72
  }
71
73
  console.log('');
@@ -77,13 +79,13 @@ async function dna(pathArg, opts = {}) {
77
79
  .sort((a, b) => uScore(a) - uScore(b))
78
80
  .slice(0, 5);
79
81
  if (debt.length) {
80
- console.log(' ' + chalk.bold('🧠 Anlama borcu') + chalk.gray(' (AI yazdı ama ekip muhtemelen anlamıyor):'));
82
+ console.log(' ' + chalk.bold(t('dna.debtTitle')) + chalk.gray(' ' + t('dna.debtDesc')));
81
83
  for (const f of debt) {
82
- console.log(' ' + chalk.red(`${uScore(f).toFixed(1)}/5`) + ' ' + chalk.white(f.file) + chalk.gray(` (YZ %${Math.round(f.ai_probability * 100)})`));
84
+ console.log(' ' + chalk.red(`${uScore(f).toFixed(1)}/5`) + ' ' + chalk.white(f.file) + chalk.gray(` (AI %${Math.round(f.ai_probability * 100)})`));
83
85
  }
84
86
  console.log('');
85
87
  }
86
- console.log(chalk.gray(' Ayrıntı için: ') + chalk.cyan('codedna scan') + chalk.gray(' · Ekosistem: ') + chalk.cyan('natureco.me/ekosistem') + '\n');
88
+ console.log(chalk.gray(' ' + t('dna.detail') + ' ') + chalk.cyan('codedna scan') + chalk.gray(' · ' + t('dna.ecosystem') + ' ') + chalk.cyan('natureco.me/ekosistem') + '\n');
87
89
  }
88
90
 
89
91
  module.exports = dna;
@@ -0,0 +1,31 @@
1
+ const chalk = require('chalk');
2
+ const { setConfigValue } = require('../utils/config');
3
+ const { t, getLang, setLangCache } = require('../utils/i18n');
4
+
5
+ /**
6
+ * `natureco lang [tr|en]` — arayüz dilini görüntüle/ayarla.
7
+ * Ayar `~/.natureco/config.json` içindeki `language` alanına yazılır ve
8
+ * i18n katmanı + ajanın system-prompt'u bunu okur (EN → İngilizce deneyim).
9
+ */
10
+ async function lang(arg) {
11
+ const label = (l) => (l === 'en' ? 'English (en)' : 'Türkçe (tr)');
12
+ const val = (arg || '').toLowerCase().trim();
13
+
14
+ if (!val) {
15
+ console.log('\n ' + t('lang.current', { lang: label(getLang()) }));
16
+ console.log(' ' + chalk.gray(t('lang.usage')) + '\n');
17
+ return;
18
+ }
19
+ if (val !== 'tr' && val !== 'en') {
20
+ console.log('\n ' + chalk.red(t('lang.invalid')) + '\n');
21
+ process.exitCode = 1;
22
+ return;
23
+ }
24
+
25
+ setConfigValue('language', val);
26
+ setLangCache(val);
27
+ console.log('\n ' + chalk.green(t('lang.set', { lang: label(val) })));
28
+ console.log(' ' + chalk.gray(t('lang.restartHint')) + '\n');
29
+ }
30
+
31
+ module.exports = lang;
@@ -0,0 +1,95 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * NatureCo CLI — hafif i18n katmanı.
5
+ * Dil `~/.natureco/config.json` içindeki `language` alanından okunur (tr | en).
6
+ * Yoksa ortam değişkeninden (LANG/LC_ALL) tahmin edilir; varsayılan Türkçe.
7
+ *
8
+ * Kullanım: const { t } = require('../utils/i18n'); t('dna.avgAi')
9
+ * Yeni çeviri eklemek: aşağıdaki MESSAGES.tr ve MESSAGES.en'e aynı anahtarı ekle.
10
+ */
11
+
12
+ const { getConfig } = require('./config');
13
+
14
+ let _cache = null;
15
+
16
+ function getLang() {
17
+ if (_cache) return _cache;
18
+ try {
19
+ const cfg = getConfig();
20
+ if (cfg && (cfg.language === 'en' || cfg.language === 'tr')) {
21
+ _cache = cfg.language;
22
+ return _cache;
23
+ }
24
+ } catch (_) { /* config yoksa ortam değişkenine düş */ }
25
+ const env = (process.env.NATURECO_LANG || process.env.LANG || process.env.LC_ALL || '').toLowerCase();
26
+ _cache = env.startsWith('en') ? 'en' : 'tr'; // varsayılan: Türkçe-öncelikli
27
+ return _cache;
28
+ }
29
+
30
+ /** Bellek önbelleğini güncelle (dil değiştirildiğinde çağrılır). */
31
+ function setLangCache(lang) {
32
+ _cache = lang === 'en' ? 'en' : 'tr';
33
+ }
34
+
35
+ const MESSAGES = {
36
+ tr: {
37
+ // dna
38
+ 'dna.notInstalled': 'CodeDNA kurulu değil.',
39
+ 'dna.installHint': 'Kurmak için:',
40
+ 'dna.installDesc': 'CodeDNA, kodun ne kadarının yapay zekâ olduğunu ölçen NatureCo aracıdır.',
41
+ 'dna.unreadable': 'CodeDNA çıktısı okunamadı.',
42
+ 'dna.avgAi': 'Ortalama YZ olasılığı',
43
+ 'dna.maxFile': 'En yüksek dosya',
44
+ 'dna.scanned': 'Taranan dosya: {n}',
45
+ 'dna.topFiles': 'En yüksek YZ olasılıklı dosyalar:',
46
+ 'dna.understanding': 'anlama',
47
+ 'dna.debtTitle': '🧠 Anlama borcu',
48
+ 'dna.debtDesc': '(AI yazdı ama ekip muhtemelen anlamıyor):',
49
+ 'dna.detail': 'Ayrıntı için:',
50
+ 'dna.ecosystem': 'Ekosistem:',
51
+ // lang
52
+ 'lang.current': 'Şu anki dil: {lang}',
53
+ 'lang.set': 'Dil ayarlandı: {lang} ✓',
54
+ 'lang.usage': 'Kullanım: natureco lang <tr|en>',
55
+ 'lang.invalid': 'Geçersiz dil. "tr" veya "en" kullanın.',
56
+ 'lang.restartHint': 'Değişiklik yeni komutlarda geçerli.',
57
+ },
58
+ en: {
59
+ // dna
60
+ 'dna.notInstalled': 'CodeDNA is not installed.',
61
+ 'dna.installHint': 'Install with:',
62
+ 'dna.installDesc': "CodeDNA is the NatureCo tool that measures how much of your code is AI-written.",
63
+ 'dna.unreadable': "Couldn't read CodeDNA output.",
64
+ 'dna.avgAi': 'Average AI probability',
65
+ 'dna.maxFile': 'Highest file',
66
+ 'dna.scanned': 'Files scanned: {n}',
67
+ 'dna.topFiles': 'Highest AI-probability files:',
68
+ 'dna.understanding': 'understanding',
69
+ 'dna.debtTitle': '🧠 Understanding debt',
70
+ 'dna.debtDesc': "(AI-written code the team likely doesn't understand):",
71
+ 'dna.detail': 'For details:',
72
+ 'dna.ecosystem': 'Ecosystem:',
73
+ // lang
74
+ 'lang.current': 'Current language: {lang}',
75
+ 'lang.set': 'Language set to: {lang} ✓',
76
+ 'lang.usage': 'Usage: natureco lang <tr|en>',
77
+ 'lang.invalid': 'Invalid language. Use "tr" or "en".',
78
+ 'lang.restartHint': 'Takes effect on the next commands.',
79
+ },
80
+ };
81
+
82
+ /** Çeviri: geçerli dilde `key`'i döndür (yoksa TR'ye, o da yoksa key'in kendisine düşer). {var} enterpolasyonu. */
83
+ function t(key, vars) {
84
+ const lang = getLang();
85
+ const cat = MESSAGES[lang] || MESSAGES.tr;
86
+ let s = cat[key];
87
+ if (s == null) s = MESSAGES.tr[key];
88
+ if (s == null) s = key;
89
+ if (vars) {
90
+ for (const k of Object.keys(vars)) s = s.split('{' + k + '}').join(String(vars[k]));
91
+ }
92
+ return s;
93
+ }
94
+
95
+ module.exports = { t, getLang, setLangCache, MESSAGES };
@@ -10,7 +10,11 @@
10
10
  * Volatile is rebuilt every turn.
11
11
  */
12
12
 
13
+ let _getLang;
14
+ try { _getLang = require('./i18n').getLang; } catch (_) { _getLang = () => 'tr'; }
15
+
13
16
  function buildTiers(opts) {
17
+ const lang = opts.language || _getLang();
14
18
  const {
15
19
  botName,
16
20
  userName = 'kullanıcı',
@@ -43,7 +47,9 @@ function buildTiers(opts) {
43
47
  `ASLA "MiniMax", "MiniMax-M2.5", "Claude", "GPT", "AI asistanı", "yapay zeka" gibi ifadeleri KENDİNİ tanıtmak için KULLANMA.`,
44
48
  `Kullanıcı "adın ne?", "sen kimsin?" diye sorduğunda İLK cümlende MUTLAKA "Ben ${displayBot}" yaz.`,
45
49
  `Senin adın: ${displayBot}. Tekrar: ${displayBot}. Asla unutma: ${displayBot}.`,
46
- `Sen bir marka veya ürün değilsin. Sen ${displayBot}sin, NatureCo CLI'nin Türkçe yapay zeka asistanısın.`,
50
+ lang === 'en'
51
+ ? `You are not a brand or product. You are ${displayBot}, the AI assistant of the NatureCo CLI.`
52
+ : `Sen bir marka veya ürün değilsin. Sen ${displayBot}sin, NatureCo CLI'nin yapay zeka asistanısın.`,
47
53
 
48
54
  // Personality (stable)
49
55
  `Kisiselik: Sen samimi, sicak, dosta benzeyen bir asistansin. "Selam", "tamam", "hadi yapalim", "bak simdi", "sakin ol" gibi gunluk ifadeler kullan.`,
@@ -52,9 +58,11 @@ function buildTiers(opts) {
52
58
  `Kisa yanit: Uzun paragraflar yazma. Direkt konuya gir.`,
53
59
  `Hata yaparsan "Pardon, yanlis yaptim, simdi duzelteyim" de. "Hata", "basarisiz", "imkansiz" deme.`,
54
60
 
55
- // Language rules (stable)
56
- `KRITIK DIL KURALI: Kullanici Turkce yaziyorsa MUTLAKA yuzde yuz Turkce cevap ver. Asla baska dil kullanma. Turkce karakterleri dogru kullan.`,
57
- `Yazim: "degilim" dogru, "degil" degil. Turkce dil bilgisi kurallarina uy.`,
61
+ // Language rules (stable) — honor the user's chosen interface language
62
+ lang === 'en'
63
+ ? `CRITICAL LANGUAGE RULE: ALWAYS reply to the user in English. These internal instructions are written in Turkish, but every message you send to the user MUST be in natural, correct English. Never reply in Turkish.`
64
+ : `KRITIK DIL KURALI: Kullanici Turkce yaziyorsa MUTLAKA yuzde yuz Turkce cevap ver. Asla baska dil kullanma. Turkce karakterleri dogru kullan.`,
65
+ lang === 'en' ? '' : `Yazim: "degilim" dogru, "degil" degil. Turkce dil bilgisi kurallarina uy.`,
58
66
 
59
67
  // Tool rules (stable)
60
68
  `ONEMLI: Tool cagirma SIMULE ETME. Sadece duz metin cevap ver. Islem yapmak gerekirse tool'u gercekten cagir.`,