natureco-cli 2.23.32 → 4.4.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 (174) hide show
  1. package/AUDIT.md +178 -0
  2. package/CHANGELOG.md +422 -0
  3. package/DEPLOY_v2.0.0.md +400 -0
  4. package/README.md +159 -1
  5. package/bin/natureco.js +170 -8
  6. package/package.json +43 -11
  7. package/skills/code-review/SKILL.md +0 -0
  8. package/skills/summarize/SKILL.md +0 -0
  9. package/skills/translate/SKILL.md +0 -0
  10. package/src/commands/acp.js +0 -0
  11. package/src/commands/admin-rpc.js +0 -0
  12. package/src/commands/agent.js +0 -0
  13. package/src/commands/agents.js +0 -0
  14. package/src/commands/approvals.js +0 -0
  15. package/src/commands/ask.js +0 -0
  16. package/src/commands/audit.js +209 -0
  17. package/src/commands/backup.js +0 -0
  18. package/src/commands/bonjour.js +0 -0
  19. package/src/commands/bots.js +0 -0
  20. package/src/commands/browser.js +0 -0
  21. package/src/commands/capability.js +0 -0
  22. package/src/commands/channels.js +0 -0
  23. package/src/commands/chat.js +0 -0
  24. package/src/commands/clawbot.js +0 -0
  25. package/src/commands/clickclack.js +0 -0
  26. package/src/commands/code.js +0 -0
  27. package/src/commands/commands.js +0 -0
  28. package/src/commands/commitments.js +0 -0
  29. package/src/commands/completion.js +0 -0
  30. package/src/commands/config.js +0 -0
  31. package/src/commands/configure.js +0 -0
  32. package/src/commands/cost.js +210 -0
  33. package/src/commands/crestodian.js +0 -0
  34. package/src/commands/cron.js +0 -0
  35. package/src/commands/daemon.js +0 -0
  36. package/src/commands/dashboard.js +126 -45
  37. package/src/commands/device-pair.js +0 -0
  38. package/src/commands/devices.js +0 -0
  39. package/src/commands/directory.js +0 -0
  40. package/src/commands/discord.js +0 -0
  41. package/src/commands/dns.js +0 -0
  42. package/src/commands/docs.js +0 -0
  43. package/src/commands/doctor.js +134 -15
  44. package/src/commands/exec-policy.js +0 -0
  45. package/src/commands/gateway-server.js +0 -0
  46. package/src/commands/gateway.js +0 -0
  47. package/src/commands/git.js +0 -0
  48. package/src/commands/health.js +0 -0
  49. package/src/commands/help.js +0 -0
  50. package/src/commands/hooks.js +0 -0
  51. package/src/commands/imessage.js +0 -0
  52. package/src/commands/infer.js +0 -0
  53. package/src/commands/init.js +0 -0
  54. package/src/commands/irc.js +0 -0
  55. package/src/commands/login.js +0 -0
  56. package/src/commands/logout.js +0 -0
  57. package/src/commands/logs.js +0 -0
  58. package/src/commands/mattermost.js +0 -0
  59. package/src/commands/mcp.js +0 -0
  60. package/src/commands/medium.js +206 -0
  61. package/src/commands/memory-cmd.js +0 -0
  62. package/src/commands/memory.js +0 -0
  63. package/src/commands/message.js +0 -0
  64. package/src/commands/migrate.js +0 -0
  65. package/src/commands/models.js +0 -0
  66. package/src/commands/naturehub.js +156 -0
  67. package/src/commands/node.js +0 -0
  68. package/src/commands/nodes.js +0 -0
  69. package/src/commands/oc-path.js +0 -0
  70. package/src/commands/onboard.js +0 -0
  71. package/src/commands/open-prose.js +0 -0
  72. package/src/commands/pairing.js +0 -0
  73. package/src/commands/path.js +0 -0
  74. package/src/commands/plugins.js +0 -0
  75. package/src/commands/policy.js +0 -0
  76. package/src/commands/proxy.js +0 -0
  77. package/src/commands/qr.js +0 -0
  78. package/src/commands/reset.js +0 -0
  79. package/src/commands/run.js +0 -0
  80. package/src/commands/sandbox.js +0 -0
  81. package/src/commands/secrets.js +0 -0
  82. package/src/commands/security.js +0 -0
  83. package/src/commands/seo.js +268 -0
  84. package/src/commands/sessions.js +0 -0
  85. package/src/commands/setup.js +6 -6
  86. package/src/commands/signal.js +0 -0
  87. package/src/commands/skills.js +82 -1
  88. package/src/commands/slack.js +0 -0
  89. package/src/commands/sms.js +0 -0
  90. package/src/commands/status.js +0 -0
  91. package/src/commands/system.js +0 -0
  92. package/src/commands/tasks.js +0 -0
  93. package/src/commands/team.js +171 -0
  94. package/src/commands/telegram.js +0 -0
  95. package/src/commands/terminal.js +0 -0
  96. package/src/commands/thread-ownership.js +0 -0
  97. package/src/commands/transcripts.js +0 -0
  98. package/src/commands/tui.js +0 -0
  99. package/src/commands/ultrareview.js +0 -0
  100. package/src/commands/uninstall.js +0 -0
  101. package/src/commands/update.js +0 -0
  102. package/src/commands/voice.js +0 -0
  103. package/src/commands/vydra.js +0 -0
  104. package/src/commands/web-fetch.js +0 -0
  105. package/src/commands/webhooks.js +0 -0
  106. package/src/commands/whatsapp.js +0 -0
  107. package/src/commands/wiki.js +0 -0
  108. package/src/commands/workboard.js +0 -0
  109. package/src/commands/xp.js +194 -0
  110. package/src/tools/audio_understanding.js +0 -0
  111. package/src/tools/bash.js +0 -0
  112. package/src/tools/browser.js +0 -0
  113. package/src/tools/canvas.js +0 -0
  114. package/src/tools/document_extract.js +0 -0
  115. package/src/tools/duckduckgo.js +0 -0
  116. package/src/tools/exa_search.js +0 -0
  117. package/src/tools/filesystem.js +0 -0
  118. package/src/tools/firecrawl.js +0 -0
  119. package/src/tools/git.js +0 -0
  120. package/src/tools/http.js +0 -0
  121. package/src/tools/image_generation.js +0 -0
  122. package/src/tools/list_dir.js +0 -0
  123. package/src/tools/llm_task.js +43 -11
  124. package/src/tools/media_understanding.js +0 -0
  125. package/src/tools/music_generation.js +0 -0
  126. package/src/tools/parallel_search.js +0 -0
  127. package/src/tools/phone_control.js +0 -0
  128. package/src/tools/phone_control_enhanced.js +0 -0
  129. package/src/tools/read_file.js +0 -0
  130. package/src/tools/searxng.js +0 -0
  131. package/src/tools/speech_to_text.js +0 -0
  132. package/src/tools/text_to_speech.js +0 -0
  133. package/src/tools/thread_ownership.js +0 -0
  134. package/src/tools/video_generation.js +0 -0
  135. package/src/tools/web_readability.js +0 -0
  136. package/src/tools/web_search.js +0 -0
  137. package/src/tools/write_file.js +0 -0
  138. package/src/utils/agents-md.js +0 -0
  139. package/src/utils/agents.js +0 -0
  140. package/src/utils/api.js +5 -1
  141. package/src/utils/approvals.js +0 -0
  142. package/src/utils/audit.js +199 -0
  143. package/src/utils/background.js +0 -0
  144. package/src/utils/baileys.js +0 -0
  145. package/src/utils/branding.js +136 -0
  146. package/src/utils/commands.js +0 -0
  147. package/src/utils/config.js +0 -0
  148. package/src/utils/cost-tracker.js +360 -0
  149. package/src/utils/cron.js +0 -0
  150. package/src/utils/dashboard-server.js +284 -0
  151. package/src/utils/errors.js +0 -0
  152. package/src/utils/format.js +7 -10
  153. package/src/utils/gateway-ws.js +0 -0
  154. package/src/utils/headless.js +0 -0
  155. package/src/utils/history.js +0 -0
  156. package/src/utils/hooks.js +0 -0
  157. package/src/utils/inquirer-wrapper.js +0 -0
  158. package/src/utils/mcp-client.js +0 -0
  159. package/src/utils/mcp.js +0 -0
  160. package/src/utils/memory.js +0 -0
  161. package/src/utils/parallel-tools.js +0 -0
  162. package/src/utils/path-utils.js +0 -0
  163. package/src/utils/pattern-detector.js +314 -0
  164. package/src/utils/plugin-registry.js +0 -0
  165. package/src/utils/secret-scanner.js +204 -0
  166. package/src/utils/secrets.js +0 -0
  167. package/src/utils/sessions.js +0 -0
  168. package/src/utils/skills.js +0 -0
  169. package/src/utils/sub-agent.js +6 -0
  170. package/src/utils/token-budget.js +0 -0
  171. package/src/utils/tool-adapter.js +0 -0
  172. package/src/utils/tool-runner.js +0 -0
  173. package/src/utils/tui.js +750 -0
  174. package/src/utils/web-fetch.js +0 -0
@@ -0,0 +1,194 @@
1
+ /**
2
+ * natureco xp — NatureCo XP/Level sistemi (Phase 6)
3
+ *
4
+ * Parton'un hedeflerinden biri: kullanıcıları ödüllendirmek.
5
+ * XP kazanma yolları:
6
+ * - Komut çalıştırma (1 XP)
7
+ * - Audit log kaydı (0.1 XP)
8
+ * - Skill kabul etme (5 XP)
9
+ * - Bir bug raporlama (10 XP)
10
+ * - Haftalık aktif kullanım (50 XP bonus)
11
+ *
12
+ * Kullanım:
13
+ * natureco xp Mevcut durum
14
+ * natureco xp stats Detaylı istatistikler
15
+ * natureco xp leaderboard Top kullanıcılar
16
+ * natureco xp rewards Aktif ödüller
17
+ */
18
+
19
+ const chalk = require('chalk');
20
+ const tui = require('../utils/tui');
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+ const os = require('os');
24
+
25
+ const XP_FILE = path.join(os.homedir(), '.natureco', 'xp.json');
26
+ const LEVELS = [
27
+ { level: 1, minXP: 0, title: '🌱 Tohum', color: chalk.green },
28
+ { level: 2, minXP: 100, title: '🌿 Filiz', color: chalk.green },
29
+ { level: 3, minXP: 300, title: '🍃 Yaprak', color: chalk.cyan },
30
+ { level: 4, minXP: 700, title: '🌳 Ağaç', color: chalk.blue },
31
+ { level: 5, minXP: 1500, title: '🌲 Orman', color: chalk.yellow },
32
+ { level: 6, minXP: 3000, title: '🏔️ Dağ', color: chalk.magenta },
33
+ { level: 7, minXP: 6000, title: '⭐ Yıldız', color: chalk.red.bold },
34
+ { level: 8, minXP: 12000,title: '🌌 Galaksi', color: chalk.hex('#a78bfa').bold },
35
+ ];
36
+
37
+ function loadXP() {
38
+ try {
39
+ if (fs.existsSync(XP_FILE)) return JSON.parse(fs.readFileSync(XP_FILE, 'utf8'));
40
+ } catch {}
41
+ return { xp: 0, history: [], username: os.userInfo().username };
42
+ }
43
+
44
+ function saveXP(data) {
45
+ const dir = path.dirname(XP_FILE);
46
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
47
+ fs.writeFileSync(XP_FILE, JSON.stringify(data, null, 2), 'utf8');
48
+ }
49
+
50
+ function getLevel(xp) {
51
+ let current = LEVELS[0];
52
+ for (const lv of LEVELS) {
53
+ if (xp >= lv.minXP) current = lv;
54
+ }
55
+ return current;
56
+ }
57
+
58
+ function getNextLevel(xp) {
59
+ for (const lv of LEVELS) {
60
+ if (lv.minXP > xp) return lv;
61
+ }
62
+ return null;
63
+ }
64
+
65
+ function addXP(amount, reason) {
66
+ const data = loadXP();
67
+ data.xp += amount;
68
+ data.history.push({ ts: new Date().toISOString(), amount, reason });
69
+ // Son 100 history tut
70
+ if (data.history.length > 100) data.history = data.history.slice(-100);
71
+ saveXP(data);
72
+ return data;
73
+ }
74
+
75
+ function cmdStatus() {
76
+ const data = loadXP();
77
+ const current = getLevel(data.xp);
78
+ const next = getNextLevel(data.xp);
79
+
80
+ console.log('\n' + tui.styled(' ⭐ NatureCo XP Sistemi', { color: tui.PALETTE.accent, bold: true }));
81
+ console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
82
+
83
+ // Üst metrik kartı
84
+ const w = 50;
85
+ const lines = [];
86
+ lines.push(tui.styled(' ╭' + '─'.repeat(w) + '╮', { color: tui.PALETTE.border }));
87
+ lines.push(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted('Kullanıcı ') + tui.styled(data.username.padEnd(20), { color: tui.PALETTE.text, bold: true }) + ' ' + tui.styled('│', { color: tui.PALETTE.border }));
88
+ lines.push(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted('XP ') + tui.styled(data.xp.toLocaleString().padStart(8), { color: tui.PALETTE.primary, bold: true }) + ' ' + tui.styled('│', { color: tui.PALETTE.border }));
89
+ lines.push(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted('Seviye ') + current.color(`Lv.${current.level} ${current.title}`.padEnd(20)) + ' ' + tui.styled('│', { color: tui.PALETTE.border }));
90
+ lines.push(tui.styled(' ╰' + '─'.repeat(w) + '╯', { color: tui.PALETTE.border }));
91
+ console.log(lines.join('\n'));
92
+
93
+ if (next) {
94
+ const needed = next.minXP - data.xp;
95
+ const progress = ((data.xp - current.minXP) / (next.minXP - current.minXP)) * 100;
96
+ const filled = Math.floor(progress / 5);
97
+ const bar = tui.progressBar(data.xp - current.minXP, next.minXP - current.minXP, {
98
+ width: 40, showPercent: true,
99
+ });
100
+ console.log('\n ' + tui.C.muted('Sonraki: ') + next.color(`${next.title}`) + tui.C.muted(` (${needed} XP kaldı)`));
101
+ console.log(' ' + bar);
102
+ } else {
103
+ console.log('\n ' + tui.styled(' 🌟 Maksimum seviye!', { color: tui.PALETTE.success, bold: true }));
104
+ }
105
+
106
+ // Son kazanımlar — TUI tablo
107
+ if (data.history.length > 0) {
108
+ console.log('\n' + tui.styled(' 📜 Son XP Kazanımları', { color: tui.PALETTE.secondary, bold: true }));
109
+ const rows = data.history.slice(-5).reverse().map(h => ({
110
+ amount: (h.amount > 0 ? '+' : '') + h.amount,
111
+ ts: new Date(h.ts).toLocaleString(),
112
+ reason: h.reason,
113
+ }));
114
+ console.log('\n' + tui.table(rows, [
115
+ { key: 'amount', label: 'XP', minWidth: 8, render: r => tui.styled(r.amount, { color: r.amount.startsWith('+') ? tui.PALETTE.success : tui.PALETTE.danger, bold: true }) },
116
+ { key: 'ts', label: 'Zaman', minWidth: 22, render: r => tui.C.muted(r.ts) },
117
+ { key: 'reason', label: 'Sebep', minWidth: 30, render: r => tui.C.text(r.reason) },
118
+ ], { borderStyle: 'round', zebra: true }));
119
+ }
120
+ console.log('');
121
+ }
122
+
123
+ function cmdStats() {
124
+ const data = loadXP();
125
+ console.log(chalk.bold('\n 📊 XP İstatistikleri\n'));
126
+ console.log(chalk.gray(' Toplam XP: ') + chalk.cyan(data.xp.toLocaleString()));
127
+ console.log(chalk.gray(' Toplam kayıt: ') + chalk.cyan(data.history.length));
128
+
129
+ // Reason bazlı
130
+ const byReason = {};
131
+ for (const h of data.history) {
132
+ byReason[h.reason] = (byReason[h.reason] || 0) + h.amount;
133
+ }
134
+ if (Object.keys(byReason).length > 0) {
135
+ console.log(chalk.bold('\n 🏷️ Kaynak Bazlı XP:\n'));
136
+ for (const [reason, amount] of Object.entries(byReason).sort((a, b) => b[1] - a[1])) {
137
+ console.log(` ${reason.padEnd(30)} ${chalk.cyan((amount > 0 ? '+' : '') + amount)} XP`);
138
+ }
139
+ }
140
+ console.log('');
141
+ }
142
+
143
+ function cmdLeaderboard() {
144
+ console.log(chalk.cyan('\n 🏆 Liderlik Tablosu\n'));
145
+ console.log(chalk.gray(' Bu özellik api.natureco.me hazır olunca tam çalışacak.\n'));
146
+ console.log(chalk.gray(' Şimdilik senin sıralaman local XP dosyanda.\n'));
147
+ cmdStatus();
148
+ }
149
+
150
+ function cmdRewards() {
151
+ console.log('\n' + tui.styled(' 🎁 Aktif Ödüller', { color: tui.PALETTE.accent, bold: true }));
152
+ console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
153
+
154
+ const rows = [
155
+ { level: 'Lv.2', xp: '100 XP', reward: 'NatureCo sticker paketi', color: tui.PALETTE.success },
156
+ { level: 'Lv.3', xp: '300 XP', reward: 'NatureBot\'ta özel bot erişimi', color: tui.PALETTE.success },
157
+ { level: 'Lv.4', xp: '700 XP', reward: 'Medium\'da otomatik yayınlama', color: tui.PALETTE.secondary },
158
+ { level: 'Lv.5', xp: '1500 XP', reward: 'NatureCo Pro ayda 1 ay ücretsiz', color: tui.PALETTE.secondary },
159
+ { level: 'Lv.6', xp: '3000 XP', reward: 'Özel NatureCo rozeti', color: tui.PALETTE.accent },
160
+ { level: 'Lv.7', xp: '6000 XP', reward: '@Naturecofficial\'dan mention', color: tui.PALETTE.warning },
161
+ { level: 'Lv.8', xp: '12000 XP', reward: 'Founder statüsü (sınırlı)', color: tui.PALETTE.danger },
162
+ ];
163
+
164
+ console.log('\n' + tui.table(rows, [
165
+ { key: 'level', label: 'Seviye', minWidth: 8, render: r => tui.styled(r.level, { color: r.color, bold: true }) },
166
+ { key: 'xp', label: 'Eşik', minWidth: 10, render: r => tui.C.brand(r.xp) },
167
+ { key: 'reward', label: 'Ödül', minWidth: 35, render: r => tui.C.text(r.reward) },
168
+ ], { borderStyle: 'round', zebra: true }));
169
+ console.log('');
170
+ }
171
+
172
+ function xp(args) {
173
+ const [action] = args || [];
174
+ if (!action) return cmdStatus();
175
+ if (action === 'stats') return cmdStats();
176
+ if (action === 'leaderboard') return cmdLeaderboard();
177
+ if (action === 'rewards') return cmdRewards();
178
+ if (action === 'help') {
179
+ console.log(chalk.yellow('\n Kullanım:'));
180
+ console.log(chalk.gray(' natureco xp Mevcut durum'));
181
+ console.log(chalk.gray(' natureco xp stats İstatistikler'));
182
+ console.log(chalk.gray(' natureco xp leaderboard Liderlik'));
183
+ console.log(chalk.gray(' natureco xp rewards Aktif ödüller'));
184
+ console.log('');
185
+ return;
186
+ }
187
+ console.log(chalk.red(`\n Bilinmeyen: ${action}\n`));
188
+ }
189
+
190
+ // Export addXP — diğer modüller XP kazandırabilsin
191
+ xp.addXP = addXP;
192
+ xp.getXP = () => loadXP().xp;
193
+
194
+ module.exports = xp;
File without changes
package/src/tools/bash.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/src/tools/git.js CHANGED
File without changes
package/src/tools/http.js CHANGED
File without changes
File without changes
File without changes
@@ -38,8 +38,9 @@ module.exports = {
38
38
  schema: { type: 'object', description: 'Optional JSON Schema to validate the returned JSON' },
39
39
  provider: { type: 'string', description: 'Provider override (e.g. openai, anthropic)' },
40
40
  model: { type: 'string', description: 'Model override' },
41
- temperature: { type: 'number', description: 'Temperature override' },
42
- maxTokens: { type: 'number', description: 'Max tokens override' }
41
+ // LLM'ler JSON'da sayıları string olarak dönebiliyor — esnek schema
42
+ temperature: { type: ['number', 'string'], description: 'Temperature override' },
43
+ maxTokens: { type: ['number', 'string'], description: 'Max tokens override' }
43
44
  },
44
45
  required: ['prompt']
45
46
  },
@@ -50,13 +51,21 @@ module.exports = {
50
51
  const provider = params.provider || config.provider || 'openai';
51
52
  const model = params.model || config.model || 'gpt-4o';
52
53
 
54
+ // LLM'ler sayıları string olarak dönebiliyor — cast et
55
+ const temperature = typeof params.temperature === 'string' ? parseFloat(params.temperature) : (params.temperature ?? 0.1);
56
+ const maxTokens = typeof params.maxTokens === 'string' ? parseInt(params.maxTokens, 10) : (params.maxTokens ?? 4096);
57
+
53
58
  let apiKey;
54
59
  if (provider === 'openai') apiKey = params.apiKey || config.openaiApiKey || process.env.OPENAI_API_KEY;
55
60
  else if (provider === 'anthropic') apiKey = params.apiKey || config.anthropicApiKey || process.env.ANTHROPIC_API_KEY;
56
61
  else if (provider === 'groq') apiKey = params.apiKey || config.groqApiKey || process.env.GROQ_API_KEY;
62
+ else if (provider === 'groq' || provider === 'together' || provider === 'openrouter') {
63
+ // Yeni provider presetler için ana providerApiKey'i kullan
64
+ apiKey = config.providerApiKey;
65
+ }
57
66
 
58
67
  if (!apiKey) {
59
- return { success: false, error: `API key required for ${provider}. Set: natureco config set ${provider}ApiKey <key>` };
68
+ return { success: false, error: `API key required for ${provider}. Set: natureco config set ${provider}ApiKey <key> veya providerApiKey` };
60
69
  }
61
70
 
62
71
  const systemPrompt = [
@@ -70,15 +79,37 @@ module.exports = {
70
79
  const inputJson = JSON.stringify(params.input ?? null, null, 2);
71
80
  const fullPrompt = `${systemPrompt}\n\nTASK:\n${params.prompt}\n\nINPUT:\n${inputJson}\n`;
72
81
 
73
- const baseUrl = provider === 'openai' ? 'https://api.openai.com/v1' : `https://api.${provider}.com/v1`;
74
- const requestBody = {
75
- model,
76
- messages: [{ role: 'user', content: fullPrompt }],
77
- temperature: params.temperature ?? 0.1,
78
- max_tokens: params.maxTokens ?? 4096
79
- };
82
+ // Provider URL'ini config'ten al (Groq, MiniMax, OpenRouter için)
83
+ let baseUrl = provider === 'openai' ? 'https://api.openai.com/v1' : `https://api.${provider}.com/v1`;
84
+ if (provider === 'groq') baseUrl = config.providerUrl || 'https://api.groq.com/openai/v1';
85
+ if (provider === 'openrouter') baseUrl = 'https://openrouter.ai/api/v1';
86
+ // MiniMax özel endpoint: /v1/text/chatcompletion_v2 (OpenAI uyumlu DEĞİL)
87
+ if (provider === 'minimax') {
88
+ baseUrl = config.providerUrl || 'https://api.minimax.io';
89
+ }
90
+
91
+ // MiniMax özel mi, OpenAI uyumlu mu?
92
+ const isMiniMax = provider === 'minimax' || baseUrl.includes('minimax.io') || baseUrl.includes('minimaxi.com');
93
+ const endpoint = isMiniMax
94
+ ? `${baseUrl}/v1/text/chatcompletion_v2`
95
+ : `${baseUrl}/chat/completions`;
96
+
97
+ // MiniMax özel request format
98
+ const requestBody = isMiniMax
99
+ ? {
100
+ model,
101
+ messages: [{ role: 'user', content: fullPrompt }],
102
+ temperature,
103
+ max_tokens: maxTokens,
104
+ }
105
+ : {
106
+ model,
107
+ messages: [{ role: 'user', content: fullPrompt }],
108
+ temperature,
109
+ max_tokens: maxTokens
110
+ };
80
111
 
81
- const response = await fetch(`${baseUrl}/chat/completions`, {
112
+ const response = await fetch(endpoint, {
82
113
  method: 'POST',
83
114
  headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` },
84
115
  body: JSON.stringify(requestBody)
@@ -89,6 +120,7 @@ module.exports = {
89
120
  }
90
121
 
91
122
  const data = await response.json();
123
+ // MiniMax response format: choices[0].message.content (OpenAI ile aynı)
92
124
  const text = data.choices?.[0]?.message?.content?.trim();
93
125
  if (!text) return { success: false, error: 'LLM returned empty output' };
94
126
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/src/utils/api.js CHANGED
@@ -430,7 +430,11 @@ function formatToolsForAnthropic() {
430
430
  */
431
431
  async function sendMessageOpenAICompatible(providerConfig, messages, tools) {
432
432
  const baseUrl = providerConfig.url.replace(/\/+$/, '');
433
- const endpoint = `${baseUrl}/chat/completions`;
433
+ // MiniMax özel endpoint tespiti
434
+ const isMiniMax = baseUrl.includes('minimax.io') || baseUrl.includes('minimaxi.com') || baseUrl.includes('minimax.cn');
435
+ const endpoint = isMiniMax
436
+ ? `${baseUrl}/v1/text/chatcompletion_v2`
437
+ : `${baseUrl}/chat/completions`;
434
438
  const requestBody = {
435
439
  model: providerConfig.model,
436
440
  messages: messages,
File without changes
@@ -0,0 +1,199 @@
1
+ /**
2
+ * NatureCo CLI — Audit Log (Phase 2)
3
+ *
4
+ * Tüm kullanıcı işlemlerini (komut, onay, tool call, hata) JSONL olarak kaydeder.
5
+ * Bu log güvenlik denetimi, hata ayıklama ve compliance için kullanılır.
6
+ *
7
+ * Format: Her satır bir JSON objesi. Sıralı append, async-non-blocking.
8
+ *
9
+ * Varsayılan: ~/.natureco/audit/audit-YYYY-MM-DD.jsonl
10
+ * 30 günden eski loglar otomatik temizlenir.
11
+ */
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const os = require('os');
16
+
17
+ const AUDIT_DIR = path.join(os.homedir(), '.natureco', 'audit');
18
+ const RETENTION_DAYS = 30;
19
+
20
+ // Action tipleri
21
+ const ACTIONS = {
22
+ COMMAND_RUN: 'command.run', // Bir CLI komutu çalıştırıldı
23
+ COMMAND_FAIL: 'command.fail', // Komut hata verdi
24
+ APPROVAL_ASK: 'approval.ask', // Onay istendi
25
+ APPROVAL_GRANT: 'approval.grant', // Kullanıcı onayladı
26
+ APPROVAL_DENY: 'approval.deny', // Kullanıcı reddetti
27
+ TOOL_CALL: 'tool.call', // Agent bir tool çağırdı
28
+ TOOL_BLOCK: 'tool.block', // Tehlikeli tool çağrısı engellendi
29
+ AUTH_LOGIN: 'auth.login', // Login
30
+ AUTH_LOGOUT: 'auth.logout', // Logout
31
+ SECRET_READ: 'secret.read', // Secret çözüldü
32
+ SECRET_LEAK: 'secret.leak', // Potansiyel secret sızıntısı tespit
33
+ CONFIG_CHANGE: 'config.change', // Config değişti
34
+ CRON_RUN: 'cron.run', // Cron job çalıştı
35
+ SKILL_INSTALL: 'skill.install', // Skill yüklendi
36
+ SKILL_AUTO: 'skill.auto', // Self-evolving skill oluştu
37
+ ERROR: 'error', // Genel hata
38
+ INFO: 'info', // Bilgi mesajı
39
+ };
40
+
41
+ let _stream = null;
42
+ let _streamPath = null;
43
+ let _writeQueue = Promise.resolve();
44
+
45
+ function ensureDir() {
46
+ if (!fs.existsSync(AUDIT_DIR)) fs.mkdirSync(AUDIT_DIR, { recursive: true });
47
+ }
48
+
49
+ function todayFile() {
50
+ const d = new Date().toISOString().slice(0, 10);
51
+ return path.join(AUDIT_DIR, `audit-${d}.jsonl`);
52
+ }
53
+
54
+ function getStream() {
55
+ const target = todayFile();
56
+ if (_stream && target === _streamPath) return _stream;
57
+ if (_stream) {
58
+ try { _stream.end(); } catch {}
59
+ }
60
+ ensureDir();
61
+ _stream = fs.createWriteStream(target, { flags: 'a' });
62
+ _streamPath = target;
63
+ return _stream;
64
+ }
65
+
66
+ /**
67
+ * Ana audit kayıt fonksiyonu. Non-blocking — queue'ya ekler ve döner.
68
+ *
69
+ * @param {string} action - ACTIONS enum'undan
70
+ * @param {object} data - Ek bağlam
71
+ * @returns {Promise<void>}
72
+ */
73
+ function log(action, data = {}) {
74
+ ensureDir();
75
+ const entry = {
76
+ ts: new Date().toISOString(),
77
+ pid: process.pid,
78
+ ppid: process.ppid,
79
+ user: os.userInfo().username,
80
+ cwd: process.cwd(),
81
+ argv: process.argv.slice(2).slice(0, 5), // ilk 5 argüman
82
+ action,
83
+ ...data,
84
+ };
85
+
86
+ _writeQueue = _writeQueue.then(() => new Promise((resolve) => {
87
+ try {
88
+ const stream = getStream();
89
+ stream.write(JSON.stringify(entry) + '\n', () => resolve());
90
+ } catch (e) {
91
+ // Audit log hatası uygulamayı kıramamalı
92
+ resolve();
93
+ }
94
+ })).catch(() => {});
95
+
96
+ return _writeQueue;
97
+ }
98
+
99
+ /**
100
+ * Senkron versiyon — kritik olaylarda çağrılabilir (örn: approval deny).
101
+ * Hata durumunda null döner, exception fırlatmaz.
102
+ */
103
+ function logSync(action, data = {}) {
104
+ try {
105
+ ensureDir();
106
+ const entry = {
107
+ ts: new Date().toISOString(),
108
+ pid: process.pid,
109
+ user: os.userInfo().username,
110
+ cwd: process.cwd(),
111
+ action,
112
+ ...data,
113
+ };
114
+ fs.appendFileSync(todayFile(), JSON.stringify(entry) + '\n', 'utf8');
115
+ return true;
116
+ } catch {
117
+ return false;
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Tüm log dosyalarını döner — gün ismine göre sıralı.
123
+ */
124
+ function listLogFiles() {
125
+ ensureDir();
126
+ return fs.readdirSync(AUDIT_DIR)
127
+ .filter(f => f.startsWith('audit-') && f.endsWith('.jsonl'))
128
+ .sort()
129
+ .reverse();
130
+ }
131
+
132
+ /**
133
+ * Belirli bir günün loglarını parse eder.
134
+ */
135
+ function readLog(dateStr) {
136
+ const file = path.join(AUDIT_DIR, `audit-${dateStr}.jsonl`);
137
+ if (!fs.existsSync(file)) return [];
138
+ return fs.readFileSync(file, 'utf8')
139
+ .split('\n')
140
+ .filter(Boolean)
141
+ .map(l => {
142
+ try { return JSON.parse(l); } catch { return null; }
143
+ })
144
+ .filter(Boolean);
145
+ }
146
+
147
+ /**
148
+ * Retention temizliği — RETENTION_DAYS günden eski dosyaları siler.
149
+ */
150
+ function cleanup() {
151
+ ensureDir();
152
+ const cutoff = Date.now() - RETENTION_DAYS * 86400 * 1000;
153
+ let removed = 0;
154
+ for (const file of fs.readdirSync(AUDIT_DIR)) {
155
+ if (!file.startsWith('audit-') || !file.endsWith('.jsonl')) continue;
156
+ const filePath = path.join(AUDIT_DIR, file);
157
+ const stat = fs.statSync(filePath);
158
+ if (stat.mtimeMs < cutoff) {
159
+ try { fs.unlinkSync(filePath); removed++; } catch {}
160
+ }
161
+ }
162
+ return removed;
163
+ }
164
+
165
+ /**
166
+ * Basit istatistik — son 24 saatte hangi actionlar kaç kez?
167
+ */
168
+ function stats24h() {
169
+ const today = new Date().toISOString().slice(0, 10);
170
+ const yesterday = new Date(Date.now() - 86400000).toISOString().slice(0, 10);
171
+ const entries = [...readLog(today), ...readLog(yesterday)];
172
+ const counts = {};
173
+ for (const e of entries) {
174
+ counts[e.action] = (counts[e.action] || 0) + 1;
175
+ }
176
+ return { total: entries.length, byAction: counts, period: `${yesterday} → ${today}` };
177
+ }
178
+
179
+ /**
180
+ * Flush — bekleyen yazma işlemlerini tamamla. Çıkışta çağrılır.
181
+ */
182
+ async function flush() {
183
+ await _writeQueue;
184
+ if (_stream) {
185
+ return new Promise((resolve) => _stream.end(resolve));
186
+ }
187
+ }
188
+
189
+ module.exports = {
190
+ ACTIONS,
191
+ log,
192
+ logSync,
193
+ listLogFiles,
194
+ readLog,
195
+ cleanup,
196
+ stats24h,
197
+ flush,
198
+ AUDIT_DIR,
199
+ };
File without changes
File without changes