natureco-cli 2.23.30 → 2.23.31
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 +166 -163
- package/package.json +1 -1
- package/src/commands/acp.js +39 -0
- package/src/commands/admin-rpc.js +83 -0
- package/src/commands/agent.js +214 -23
- package/src/commands/agents.js +114 -30
- package/src/commands/approvals.js +172 -11
- package/src/commands/browser.js +815 -0
- package/src/commands/capability.js +195 -22
- package/src/commands/channels.js +422 -267
- package/src/commands/chat.js +5 -8
- package/src/commands/clawbot.js +19 -0
- package/src/commands/code.js +3 -2
- package/src/commands/commitments.js +125 -9
- package/src/commands/completion.js +40 -32
- package/src/commands/config.js +219 -30
- package/src/commands/configure.js +84 -67
- package/src/commands/cron.js +239 -19
- package/src/commands/daemon.js +34 -4
- package/src/commands/dashboard.js +47 -374
- package/src/commands/devices.js +53 -26
- package/src/commands/directory.js +146 -14
- package/src/commands/dns.js +148 -10
- package/src/commands/docs.js +119 -26
- package/src/commands/doctor.js +143 -492
- package/src/commands/exec-policy.js +57 -48
- package/src/commands/gateway.js +492 -249
- package/src/commands/health.js +141 -11
- package/src/commands/help.js +24 -25
- package/src/commands/hooks.js +141 -87
- package/src/commands/infer.js +1442 -41
- package/src/commands/logs.js +122 -99
- package/src/commands/mcp.js +121 -309
- package/src/commands/memory.js +128 -0
- package/src/commands/message.js +720 -140
- package/src/commands/models.js +39 -1
- package/src/commands/node.js +77 -77
- package/src/commands/nodes.js +278 -22
- package/src/commands/onboard.js +115 -56
- package/src/commands/pairing.js +108 -107
- package/src/commands/path.js +206 -0
- package/src/commands/plugins.js +35 -1
- package/src/commands/proxy.js +159 -8
- package/src/commands/qr.js +55 -13
- package/src/commands/reset.js +101 -94
- package/src/commands/secrets.js +104 -21
- package/src/commands/sessions.js +110 -51
- package/src/commands/setup.js +102 -649
- package/src/commands/skills.js +67 -1
- package/src/commands/status.js +101 -127
- package/src/commands/tasks.js +208 -100
- package/src/commands/terminal.js +130 -12
- package/src/commands/transcripts.js +24 -1
- package/src/commands/tui.js +41 -0
- package/src/commands/uninstall.js +73 -92
- package/src/commands/update.js +146 -91
- package/src/commands/webhooks.js +58 -66
- package/src/commands/wiki.js +783 -0
- package/src/utils/agents-md.js +85 -0
- package/src/utils/api.js +39 -40
- package/src/utils/format.js +144 -0
- package/src/utils/headless.js +2 -1
- package/src/utils/parallel-tools.js +106 -0
- package/src/utils/sub-agent.js +148 -0
- package/src/utils/token-budget.js +304 -0
- package/src/utils/tool-runner.js +7 -5
- package/src/utils/web-fetch.js +107 -0
package/src/commands/setup.js
CHANGED
|
@@ -1,649 +1,102 @@
|
|
|
1
|
-
const chalk = require('chalk');
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
integCmds: {
|
|
104
|
-
Telegram: 'natureco telegram connect',
|
|
105
|
-
WhatsApp: 'natureco whatsapp connect',
|
|
106
|
-
Discord: 'natureco discord connect',
|
|
107
|
-
Slack: 'natureco slack connect',
|
|
108
|
-
Signal: 'natureco signal connect',
|
|
109
|
-
IRC: 'natureco irc connect',
|
|
110
|
-
Mattermost:'natureco mattermost connect',
|
|
111
|
-
iMessage: 'natureco imessage connect',
|
|
112
|
-
SMS: 'natureco sms connect',
|
|
113
|
-
Webhooks: 'natureco webhooks connect',
|
|
114
|
-
},
|
|
115
|
-
// Step 5
|
|
116
|
-
gatewayTitle: 'Gateway',
|
|
117
|
-
gatewayQ: 'Start the gateway now? (runs in background)',
|
|
118
|
-
gatewayYes: 'Starting gateway...',
|
|
119
|
-
gatewaySkip: 'To start later: natureco gateway start',
|
|
120
|
-
// Step 6
|
|
121
|
-
chatTitle: 'All set!',
|
|
122
|
-
chatQ: 'Start chatting now?',
|
|
123
|
-
chatStart: 'Starting chat...',
|
|
124
|
-
chatSkip: 'To start: natureco chat',
|
|
125
|
-
// Summary
|
|
126
|
-
summaryTitle: '✅ Setup complete!',
|
|
127
|
-
summaryProvider:'Provider',
|
|
128
|
-
summaryModel: 'Model',
|
|
129
|
-
summaryBot: 'Bot name',
|
|
130
|
-
summaryUser: 'User',
|
|
131
|
-
summaryConfig: 'Config',
|
|
132
|
-
// Errors
|
|
133
|
-
urlRequired: 'URL is required',
|
|
134
|
-
urlInvalid: 'URL must start with http:// or https://',
|
|
135
|
-
apiKeyRequired: 'API key is required',
|
|
136
|
-
modelRequired: 'Model name is required',
|
|
137
|
-
nameRequired: 'Name is required',
|
|
138
|
-
},
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
// ─── Provider presets ─────────────────────────────────────────────────────────
|
|
142
|
-
const NATURECO_PROVIDER = {
|
|
143
|
-
name: 'NatureCo (natureco.me — kendi platformun)',
|
|
144
|
-
value: 'natureco',
|
|
145
|
-
url: 'https://api.natureco.me',
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
const PROVIDER_PRESETS = (customLabel) => [
|
|
149
|
-
NATURECO_PROVIDER,
|
|
150
|
-
{ name: 'Groq (recommended — fast & free)', value: 'https://api.groq.com/openai/v1' },
|
|
151
|
-
{ name: 'OpenAI', value: 'https://api.openai.com/v1' },
|
|
152
|
-
{ name: 'Anthropic', value: 'https://api.anthropic.com' },
|
|
153
|
-
{ name: 'Together AI', value: 'https://api.together.xyz/v1' },
|
|
154
|
-
{ name: 'Fireworks AI', value: 'https://api.fireworks.ai/inference/v1' },
|
|
155
|
-
{ name: 'DeepSeek', value: 'https://api.deepseek.com/v1' },
|
|
156
|
-
{ name: 'OpenRouter', value: 'https://openrouter.ai/api/v1' },
|
|
157
|
-
{ name: 'Ollama (local)', value: 'http://localhost:11434/v1' },
|
|
158
|
-
{ name: 'LM Studio (local)', value: 'http://localhost:1234/v1' },
|
|
159
|
-
{ name: customLabel, value: 'custom' },
|
|
160
|
-
];
|
|
161
|
-
|
|
162
|
-
const COMMON_MODELS = {
|
|
163
|
-
'api.groq.com': ['llama-3.3-70b-versatile','llama-3.1-8b-instant','llama-3.1-70b-versatile','mixtral-8x7b-32768','gemma2-9b-it'],
|
|
164
|
-
'api.openai.com': ['gpt-4o','gpt-4o-mini','gpt-4-turbo','gpt-3.5-turbo'],
|
|
165
|
-
'api.anthropic.com': ['claude-opus-4-7','claude-sonnet-4-6','claude-haiku-4-5-20251001'],
|
|
166
|
-
'api.together.xyz': ['meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo','meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo','mistralai/Mixtral-8x7B-Instruct-v0.1'],
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// ─── Yardımcı: adım başlığı ───────────────────────────────────────────────────
|
|
170
|
-
function printStep(L, n, title) {
|
|
171
|
-
console.log('');
|
|
172
|
-
console.log(chalk.gray('─'.repeat(50)));
|
|
173
|
-
console.log(L.step(n, title));
|
|
174
|
-
console.log('');
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function printDone(L, msg) {
|
|
178
|
-
console.log(chalk.green(` ${L.done} ${msg}`));
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// ─── Ana fonksiyon ────────────────────────────────────────────────────────────
|
|
182
|
-
async function setup() {
|
|
183
|
-
console.clear();
|
|
184
|
-
|
|
185
|
-
// ── Karşılama ──────────────────────────────────────────────────────────────
|
|
186
|
-
console.log('');
|
|
187
|
-
console.log(chalk.green.bold(' (\\_/)'));
|
|
188
|
-
console.log(chalk.green.bold(' (•ᴥ•)'));
|
|
189
|
-
console.log(chalk.green(' />🌿'));
|
|
190
|
-
console.log('');
|
|
191
|
-
|
|
192
|
-
// ── ADIM 0: Dil seçimi ─────────────────────────────────────────────────────
|
|
193
|
-
const { lang } = await inquirer.prompt([{
|
|
194
|
-
type: 'list',
|
|
195
|
-
name: 'lang',
|
|
196
|
-
message: 'Language / Dil:',
|
|
197
|
-
choices: [
|
|
198
|
-
{ name: '🇹🇷 Türkçe', value: 'tr' },
|
|
199
|
-
{ name: '🇬🇧 English', value: 'en' },
|
|
200
|
-
],
|
|
201
|
-
}]);
|
|
202
|
-
|
|
203
|
-
const L = LANG[lang];
|
|
204
|
-
|
|
205
|
-
console.log('');
|
|
206
|
-
console.log(chalk.green.bold(` ${L.welcome}`));
|
|
207
|
-
console.log(chalk.gray(` ${L.welcomeSub}`));
|
|
208
|
-
|
|
209
|
-
// Klasör oluştur
|
|
210
|
-
if (!fs.existsSync(CONFIG_DIR)) {
|
|
211
|
-
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Mevcut config
|
|
215
|
-
let existingConfig = {};
|
|
216
|
-
if (fs.existsSync(CONFIG_FILE)) {
|
|
217
|
-
try { existingConfig = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8')); } catch {}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// ── ADIM 1: Provider + API key + Model ────────────────────────────────────
|
|
221
|
-
printStep(L, 1, L.providerTitle);
|
|
222
|
-
|
|
223
|
-
const { providerChoice } = await inquirer.prompt([{
|
|
224
|
-
type: 'list',
|
|
225
|
-
name: 'providerChoice',
|
|
226
|
-
message: L.providerQ,
|
|
227
|
-
choices: PROVIDER_PRESETS(L.customEntry),
|
|
228
|
-
default: 'https://api.groq.com/openai/v1',
|
|
229
|
-
}]);
|
|
230
|
-
|
|
231
|
-
// NatureCo provider seçildiyse URL'yi ayarla
|
|
232
|
-
let providerUrl = providerChoice; // varsayılan: seçilen değer direkt URL
|
|
233
|
-
let isNatureCo = false;
|
|
234
|
-
if (providerChoice === 'natureco') {
|
|
235
|
-
providerUrl = NATURECO_PROVIDER.url;
|
|
236
|
-
isNatureCo = true;
|
|
237
|
-
} else if (providerChoice === 'custom') {
|
|
238
|
-
const { customUrl } = await inquirer.prompt([{
|
|
239
|
-
type: 'input',
|
|
240
|
-
name: 'customUrl',
|
|
241
|
-
message: L.customUrl,
|
|
242
|
-
validate: (v) => {
|
|
243
|
-
if (!v.trim()) return L.urlRequired;
|
|
244
|
-
if (!v.startsWith('http://') && !v.startsWith('https://')) return L.urlInvalid;
|
|
245
|
-
return true;
|
|
246
|
-
},
|
|
247
|
-
}]);
|
|
248
|
-
providerUrl = customUrl.trim();
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const { providerApiKey } = await inquirer.prompt([{
|
|
252
|
-
type: 'password',
|
|
253
|
-
name: 'providerApiKey',
|
|
254
|
-
message: isNatureCo ? L.apiKeyNatureCo : L.apiKeyQ,
|
|
255
|
-
mask: '*',
|
|
256
|
-
validate: (v) => v.trim() ? true : L.apiKeyRequired,
|
|
257
|
-
}]);
|
|
258
|
-
|
|
259
|
-
// Model listesi — NatureCo seçildiyse atla
|
|
260
|
-
let providerModel;
|
|
261
|
-
if (isNatureCo) {
|
|
262
|
-
providerModel = 'natureco-default';
|
|
263
|
-
} else {
|
|
264
|
-
let modelChoices = [L.customModelEntry];
|
|
265
|
-
for (const [domain, models] of Object.entries(COMMON_MODELS)) {
|
|
266
|
-
if (providerUrl.includes(domain)) {
|
|
267
|
-
modelChoices = [...models, L.customModelEntry];
|
|
268
|
-
break;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const { modelChoice } = await inquirer.prompt([{
|
|
273
|
-
type: 'list',
|
|
274
|
-
name: 'modelChoice',
|
|
275
|
-
message: L.modelQ,
|
|
276
|
-
choices: modelChoices,
|
|
277
|
-
}]);
|
|
278
|
-
|
|
279
|
-
providerModel = modelChoice;
|
|
280
|
-
if (modelChoice === L.customModelEntry) {
|
|
281
|
-
const { customModel } = await inquirer.prompt([{
|
|
282
|
-
type: 'input',
|
|
283
|
-
name: 'customModel',
|
|
284
|
-
message: L.customModel,
|
|
285
|
-
validate: (v) => v.trim() ? true : L.modelRequired,
|
|
286
|
-
}]);
|
|
287
|
-
providerModel = customModel.trim();
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
printDone(L, `${providerUrl.replace('https://', '').split('/')[0]} · ${providerModel}`);
|
|
292
|
-
|
|
293
|
-
// ── ADIM 2: Bot adı — NatureCo provider'da API'den çek ───────────────────
|
|
294
|
-
printStep(L, 2, L.botNameTitle);
|
|
295
|
-
|
|
296
|
-
let safeBotName = existingConfig.botName || 'NatureBot';
|
|
297
|
-
|
|
298
|
-
if (isNatureCo) {
|
|
299
|
-
// API'den bot listesini çek
|
|
300
|
-
console.log(chalk.gray(lang === 'tr' ? ' Botlar yükleniyor...' : ' Loading bots...'));
|
|
301
|
-
try {
|
|
302
|
-
const res = await fetch('https://api.natureco.me/api/v1/bots', {
|
|
303
|
-
headers: { 'Authorization': `Bearer ${providerApiKey.trim()}` },
|
|
304
|
-
});
|
|
305
|
-
if (res.ok) {
|
|
306
|
-
const data = await res.json();
|
|
307
|
-
const bots = Array.isArray(data) ? data : (data.bots || data.data || []);
|
|
308
|
-
if (bots.length > 0) {
|
|
309
|
-
if (bots.length === 1) {
|
|
310
|
-
// Tek bot varsa otomatik seç
|
|
311
|
-
safeBotName = bots[0].name;
|
|
312
|
-
printDone(L, safeBotName);
|
|
313
|
-
} else {
|
|
314
|
-
// Birden fazla bot varsa seçtir
|
|
315
|
-
const { selectedBotName } = await inquirer.prompt([{
|
|
316
|
-
type: 'list',
|
|
317
|
-
name: 'selectedBotName',
|
|
318
|
-
message: lang === 'tr' ? ' Hangi botu kullanmak istiyorsunuz?' : ' Which bot do you want to use?',
|
|
319
|
-
choices: bots.map(b => ({ name: b.name, value: b.name })),
|
|
320
|
-
}]);
|
|
321
|
-
safeBotName = selectedBotName;
|
|
322
|
-
printDone(L, safeBotName);
|
|
323
|
-
}
|
|
324
|
-
} else {
|
|
325
|
-
console.log(chalk.yellow(lang === 'tr'
|
|
326
|
-
? ' Bot bulunamadı. developers.natureco.me\'den bot oluşturun.'
|
|
327
|
-
: ' No bots found. Create one at developers.natureco.me'));
|
|
328
|
-
printDone(L, safeBotName);
|
|
329
|
-
}
|
|
330
|
-
} else {
|
|
331
|
-
console.log(chalk.yellow(lang === 'tr' ? ' Bot listesi alınamadı.' : ' Could not fetch bot list.'));
|
|
332
|
-
printDone(L, safeBotName);
|
|
333
|
-
}
|
|
334
|
-
} catch (e) {
|
|
335
|
-
console.log(chalk.yellow(lang === 'tr' ? ' Bağlantı hatası, varsayılan kullanılıyor.' : ' Connection error, using default.'));
|
|
336
|
-
printDone(L, safeBotName);
|
|
337
|
-
}
|
|
338
|
-
} else {
|
|
339
|
-
const { botName } = await inquirer.prompt([{
|
|
340
|
-
type: 'input',
|
|
341
|
-
name: 'botName',
|
|
342
|
-
message: L.botNameQ,
|
|
343
|
-
default: existingConfig.botName || L.botNameDefault,
|
|
344
|
-
validate: (v) => v.trim() ? true : L.nameRequired,
|
|
345
|
-
}]);
|
|
346
|
-
safeBotName = String(botName || 'NatureBot').trim();
|
|
347
|
-
printDone(L, safeBotName);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// ── ADIM 3: Kullanıcı adı ──────────────────────────────────────────────────
|
|
351
|
-
printStep(L, 3, L.userNameTitle);
|
|
352
|
-
|
|
353
|
-
const { userName } = await inquirer.prompt([{
|
|
354
|
-
type: 'input',
|
|
355
|
-
name: 'userName',
|
|
356
|
-
message: L.userNameQ,
|
|
357
|
-
default: existingConfig.userName || L.userNameDefault,
|
|
358
|
-
validate: (v) => v.trim() ? true : L.nameRequired,
|
|
359
|
-
}]);
|
|
360
|
-
|
|
361
|
-
printDone(L, userName.trim());
|
|
362
|
-
|
|
363
|
-
// ── ADIM 4: Entegrasyonlar ─────────────────────────────────────────────────
|
|
364
|
-
printStep(L, 4, L.integTitle);
|
|
365
|
-
|
|
366
|
-
const { integrations } = await inquirer.prompt([{
|
|
367
|
-
type: 'checkbox',
|
|
368
|
-
name: 'integrations',
|
|
369
|
-
message: L.integQ,
|
|
370
|
-
choices: [
|
|
371
|
-
{ name: 'Telegram', value: 'Telegram' },
|
|
372
|
-
{ name: 'WhatsApp', value: 'WhatsApp' },
|
|
373
|
-
{ name: 'Discord', value: 'Discord' },
|
|
374
|
-
{ name: 'Slack', value: 'Slack' },
|
|
375
|
-
{ name: 'Signal', value: 'Signal' },
|
|
376
|
-
{ name: 'IRC', value: 'IRC' },
|
|
377
|
-
{ name: 'Mattermost', value: 'Mattermost' },
|
|
378
|
-
{ name: 'iMessage', value: 'iMessage' },
|
|
379
|
-
{ name: 'SMS (Twilio)', value: 'SMS' },
|
|
380
|
-
{ name: 'Webhooks', value: 'Webhooks' },
|
|
381
|
-
],
|
|
382
|
-
}]);
|
|
383
|
-
|
|
384
|
-
// ── Entegrasyon sub-flow'ları ──────────────────────────────────────────────
|
|
385
|
-
const integConfig = {};
|
|
386
|
-
|
|
387
|
-
if (integrations.includes('Telegram')) {
|
|
388
|
-
console.log('');
|
|
389
|
-
console.log(chalk.cyan(' Telegram kurulumu:'));
|
|
390
|
-
const { tgToken } = await inquirer.prompt([{
|
|
391
|
-
type: 'input',
|
|
392
|
-
name: 'tgToken',
|
|
393
|
-
message: lang === 'tr' ? ' Bot Token girin (BotFather\'dan):' : ' Enter Bot Token (from BotFather):',
|
|
394
|
-
validate: (v) => v.trim() ? true : (lang === 'tr' ? 'Token gerekli' : 'Token required'),
|
|
395
|
-
}]);
|
|
396
|
-
const { tgChatId } = await inquirer.prompt([{
|
|
397
|
-
type: 'input',
|
|
398
|
-
name: 'tgChatId',
|
|
399
|
-
message: lang === 'tr' ? ' Chat ID girin (sadece bu ID\'den gelen mesajlara cevap verilir):' : ' Enter Chat ID (only messages from this ID will be answered):',
|
|
400
|
-
validate: (v) => v.trim() ? true : (lang === 'tr' ? 'Chat ID gerekli' : 'Chat ID required'),
|
|
401
|
-
}]);
|
|
402
|
-
console.log(chalk.gray(lang === 'tr'
|
|
403
|
-
? ' 💡 Chat ID\'nizi öğrenmek için @userinfobot\'a /start yazın'
|
|
404
|
-
: ' 💡 To find your Chat ID, send /start to @userinfobot'));
|
|
405
|
-
integConfig.telegramToken = tgToken.trim();
|
|
406
|
-
integConfig.telegramChatId = tgChatId.trim();
|
|
407
|
-
// Bağlantı testi
|
|
408
|
-
try {
|
|
409
|
-
const res = await fetch(`https://api.telegram.org/bot${tgToken.trim()}/getMe`);
|
|
410
|
-
const data = await res.json();
|
|
411
|
-
if (data.ok) {
|
|
412
|
-
printDone(L, `Telegram @${data.result.username}`);
|
|
413
|
-
} else {
|
|
414
|
-
console.log(chalk.yellow(' ⚠ Token geçersiz görünüyor, ilerleyebilirsin'));
|
|
415
|
-
}
|
|
416
|
-
} catch {
|
|
417
|
-
console.log(chalk.gray(' (bağlantı testi atlandı)'));
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
if (integrations.includes('WhatsApp')) {
|
|
422
|
-
console.log('');
|
|
423
|
-
console.log(chalk.cyan(lang === 'tr'
|
|
424
|
-
? ' WhatsApp için gateway başlatılması gerekiyor.'
|
|
425
|
-
: ' WhatsApp requires the gateway to be running.'));
|
|
426
|
-
console.log(chalk.gray(lang === 'tr'
|
|
427
|
-
? ' Kurulum sonunda gateway başlatılacak, ardından QR kodu taratman gerekecek.'
|
|
428
|
-
: ' The gateway will start after setup — you\'ll need to scan the QR code.'));
|
|
429
|
-
printDone(L, 'WhatsApp');
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
if (integrations.includes('Discord')) {
|
|
433
|
-
console.log('');
|
|
434
|
-
console.log(chalk.cyan(' Discord kurulumu:'));
|
|
435
|
-
const { discordToken } = await inquirer.prompt([{
|
|
436
|
-
type: 'password',
|
|
437
|
-
name: 'discordToken',
|
|
438
|
-
message: lang === 'tr' ? ' Discord Bot Token girin:' : ' Enter Discord Bot Token:',
|
|
439
|
-
mask: '*',
|
|
440
|
-
validate: (v) => v.trim() ? true : (lang === 'tr' ? 'Token gerekli' : 'Token required'),
|
|
441
|
-
}]);
|
|
442
|
-
integConfig.discordToken = discordToken.trim();
|
|
443
|
-
printDone(L, 'Discord');
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
if (integrations.includes('Signal')) {
|
|
447
|
-
console.log('');
|
|
448
|
-
console.log(chalk.cyan(' Signal kurulumu (signal-cli REST API):'));
|
|
449
|
-
const { sigUrl, sigAccount } = await inquirer.prompt([
|
|
450
|
-
{ type: 'input', name: 'sigUrl', message: lang === 'tr' ? ' signal-cli REST API URL (örn: http://localhost:8080):' : ' signal-cli REST API URL (e.g. http://localhost:8080):', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
|
|
451
|
-
{ type: 'input', name: 'sigAccount', message: lang === 'tr' ? ' Signal hesap numarası:' : ' Signal account number:', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
|
|
452
|
-
]);
|
|
453
|
-
const sigBotId = `signal_${Date.now()}`;
|
|
454
|
-
integConfig.signalHttpUrl = sigUrl.trim();
|
|
455
|
-
integConfig.signalAccount = sigAccount.trim();
|
|
456
|
-
integConfig.signalBotId = sigBotId;
|
|
457
|
-
printDone(L, 'Signal');
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
if (integrations.includes('IRC')) {
|
|
461
|
-
console.log('');
|
|
462
|
-
console.log(chalk.cyan(' IRC kurulumu:'));
|
|
463
|
-
const { ircHost, ircPort, ircNick } = await inquirer.prompt([
|
|
464
|
-
{ type: 'input', name: 'ircHost', message: lang === 'tr' ? ' IRC sunucusu (örn: irc.libera.chat):' : ' IRC server (e.g. irc.libera.chat):', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
|
|
465
|
-
{ type: 'input', name: 'ircPort', message: lang === 'tr' ? ' Port:' : ' Port:', default: '6697' },
|
|
466
|
-
{ type: 'input', name: 'ircNick', message: lang === 'tr' ? ' Nick:' : ' Nick:', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
|
|
467
|
-
]);
|
|
468
|
-
integConfig.ircHost = ircHost.trim();
|
|
469
|
-
integConfig.ircPort = parseInt(ircPort) || 6697;
|
|
470
|
-
integConfig.ircNick = ircNick.trim();
|
|
471
|
-
integConfig.ircBotId = `irc_${Date.now()}`;
|
|
472
|
-
printDone(L, 'IRC');
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
if (integrations.includes('Mattermost')) {
|
|
476
|
-
console.log('');
|
|
477
|
-
console.log(chalk.cyan(' Mattermost kurulumu:'));
|
|
478
|
-
const { mmUrl, mmToken } = await inquirer.prompt([
|
|
479
|
-
{ type: 'input', name: 'mmUrl', message: lang === 'tr' ? ' Mattermost sunucu URL:' : ' Mattermost server URL:', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
|
|
480
|
-
{ type: 'password', name: 'mmToken', message: lang === 'tr' ? ' Bot token:' : ' Bot token:', mask: '*', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
|
|
481
|
-
]);
|
|
482
|
-
integConfig.mattermostBaseUrl = mmUrl.trim().replace(/\/$/, '');
|
|
483
|
-
integConfig.mattermostToken = mmToken.trim();
|
|
484
|
-
integConfig.mattermostBotId = `mattermost_${Date.now()}`;
|
|
485
|
-
printDone(L, 'Mattermost');
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
if (integrations.includes('iMessage')) {
|
|
489
|
-
console.log('');
|
|
490
|
-
console.log(chalk.cyan(lang === 'tr' ? ' iMessage (sadece macOS):' : ' iMessage (macOS only):'));
|
|
491
|
-
const { imCliPath } = await inquirer.prompt([{ type: 'input', name: 'imCliPath', message: lang === 'tr' ? ' imsg CLI yolu (opsiyonel):' : ' imsg CLI path (optional):' }]);
|
|
492
|
-
integConfig.imessageCliPath = imCliPath.trim() || '';
|
|
493
|
-
integConfig.imessageBotId = `imessage_${Date.now()}`;
|
|
494
|
-
printDone(L, 'iMessage');
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
if (integrations.includes('SMS')) {
|
|
498
|
-
console.log('');
|
|
499
|
-
console.log(chalk.cyan(' SMS (Twilio) kurulumu:'));
|
|
500
|
-
const { smsSid, smsToken, smsFrom } = await inquirer.prompt([
|
|
501
|
-
{ type: 'input', name: 'smsSid', message: ' Twilio Account SID:', validate: v => v.trim() ? true : 'Required' },
|
|
502
|
-
{ type: 'password', name: 'smsToken', message: ' Twilio Auth Token:', mask: '*', validate: v => v.trim() ? true : 'Required' },
|
|
503
|
-
{ type: 'input', name: 'smsFrom', message: ' Twilio telefon numarası (E.164):', validate: v => v.trim() ? true : 'Required' },
|
|
504
|
-
]);
|
|
505
|
-
integConfig.smsAccountSid = smsSid.trim();
|
|
506
|
-
integConfig.smsAuthToken = smsToken.trim();
|
|
507
|
-
integConfig.smsFromNumber = smsFrom.trim();
|
|
508
|
-
integConfig.smsBotId = `sms_${Date.now()}`;
|
|
509
|
-
printDone(L, 'SMS');
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
if (integrations.includes('Webhooks')) {
|
|
513
|
-
printDone(L, 'Webhooks');
|
|
514
|
-
console.log(chalk.gray(lang === 'tr'
|
|
515
|
-
? ' → Webhook eklemek için: natureco webhooks connect'
|
|
516
|
-
: ' → To add a webhook: natureco webhooks connect'));
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
if (integrations.length > 0) {
|
|
520
|
-
const subflowChannels = ['Telegram', 'WhatsApp', 'Discord', 'Signal', 'IRC', 'Mattermost', 'iMessage', 'SMS', 'Webhooks'];
|
|
521
|
-
const hasSubflow = subflowChannels.some(ch => integrations.includes(ch));
|
|
522
|
-
if (!hasSubflow) {
|
|
523
|
-
printDone(L, integrations.join(', '));
|
|
524
|
-
}
|
|
525
|
-
console.log('');
|
|
526
|
-
} else {
|
|
527
|
-
printDone(L, L.integSkip);
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// ── ADIM 5: Gateway ────────────────────────────────────────────────────────
|
|
531
|
-
printStep(L, 5, L.gatewayTitle);
|
|
532
|
-
const { startGateway } = await inquirer.prompt([{
|
|
533
|
-
type: 'confirm',
|
|
534
|
-
name: 'startGateway',
|
|
535
|
-
message: L.gatewayQ,
|
|
536
|
-
default: integrations.includes('WhatsApp'),
|
|
537
|
-
}]);
|
|
538
|
-
|
|
539
|
-
// ── Config kaydet ──────────────────────────────────────────────────────────
|
|
540
|
-
const config = {
|
|
541
|
-
...existingConfig,
|
|
542
|
-
setupCompleted: true,
|
|
543
|
-
setupDate: new Date().toISOString(),
|
|
544
|
-
language: lang,
|
|
545
|
-
providerUrl,
|
|
546
|
-
providerApiKey: providerApiKey.trim(),
|
|
547
|
-
botName: safeBotName,
|
|
548
|
-
userName: userName.trim(),
|
|
549
|
-
debug: existingConfig.debug || false,
|
|
550
|
-
skills: existingConfig.skills || { enabled: true, list: [] },
|
|
551
|
-
mcpServers: existingConfig.mcpServers || {},
|
|
552
|
-
// Entegrasyon config'leri
|
|
553
|
-
...(integConfig.telegramToken && { telegramToken: integConfig.telegramToken }),
|
|
554
|
-
...(integConfig.telegramChatId && { telegramChatId: integConfig.telegramChatId }),
|
|
555
|
-
...(integConfig.discordToken && { discordToken: integConfig.discordToken }),
|
|
556
|
-
...(integConfig.signalHttpUrl && { signalHttpUrl: integConfig.signalHttpUrl }),
|
|
557
|
-
...(integConfig.signalAccount && { signalAccount: integConfig.signalAccount }),
|
|
558
|
-
...(integConfig.signalBotId && { signalBotId: integConfig.signalBotId }),
|
|
559
|
-
...(integConfig.ircHost && { ircHost: integConfig.ircHost }),
|
|
560
|
-
...(integConfig.ircPort && { ircPort: integConfig.ircPort }),
|
|
561
|
-
...(integConfig.ircNick && { ircNick: integConfig.ircNick }),
|
|
562
|
-
...(integConfig.ircBotId && { ircBotId: integConfig.ircBotId }),
|
|
563
|
-
...(integConfig.mattermostBaseUrl && { mattermostBaseUrl: integConfig.mattermostBaseUrl }),
|
|
564
|
-
...(integConfig.mattermostToken && { mattermostToken: integConfig.mattermostToken }),
|
|
565
|
-
...(integConfig.mattermostBotId && { mattermostBotId: integConfig.mattermostBotId }),
|
|
566
|
-
...(integConfig.imessageCliPath && { imessageCliPath: integConfig.imessageCliPath }),
|
|
567
|
-
...(integConfig.imessageBotId && { imessageBotId: integConfig.imessageBotId }),
|
|
568
|
-
...(integConfig.smsAccountSid && { smsAccountSid: integConfig.smsAccountSid }),
|
|
569
|
-
...(integConfig.smsAuthToken && { smsAuthToken: integConfig.smsAuthToken }),
|
|
570
|
-
...(integConfig.smsFromNumber && { smsFromNumber: integConfig.smsFromNumber }),
|
|
571
|
-
...(integConfig.smsBotId && { smsBotId: integConfig.smsBotId }),
|
|
572
|
-
};
|
|
573
|
-
|
|
574
|
-
saveConfig(config);
|
|
575
|
-
|
|
576
|
-
// Hafızaya kullanıcı adı ve bot adı kaydet
|
|
577
|
-
const botId = 'universal-provider';
|
|
578
|
-
try {
|
|
579
|
-
saveMemory(botId, {
|
|
580
|
-
name: userName.trim(),
|
|
581
|
-
botName: safeBotName,
|
|
582
|
-
nickname: '',
|
|
583
|
-
preferences: [],
|
|
584
|
-
facts: [],
|
|
585
|
-
lastSeen: new Date().toISOString(),
|
|
586
|
-
});
|
|
587
|
-
} catch {}
|
|
588
|
-
|
|
589
|
-
// ── Özet ───────────────────────────────────────────────────────────────────
|
|
590
|
-
console.log('');
|
|
591
|
-
console.log(chalk.gray('─'.repeat(50)));
|
|
592
|
-
console.log(chalk.green.bold(` ${L.summaryTitle}`));
|
|
593
|
-
console.log('');
|
|
594
|
-
console.log(chalk.gray(` ${L.summaryProvider}:`), chalk.white(providerUrl.replace('https://', '').split('/')[0]));
|
|
595
|
-
console.log(chalk.gray(` ${L.summaryModel}:`), chalk.white(providerModel));
|
|
596
|
-
console.log(chalk.gray(` ${L.summaryBot}:`), chalk.cyan(safeBotName));
|
|
597
|
-
console.log(chalk.gray(` ${L.summaryUser}:`), chalk.white(userName.trim()));
|
|
598
|
-
console.log(chalk.gray(` ${L.summaryConfig}:`), chalk.gray(CONFIG_FILE));
|
|
599
|
-
console.log('');
|
|
600
|
-
|
|
601
|
-
// Gateway başlat
|
|
602
|
-
if (startGateway) {
|
|
603
|
-
console.log(chalk.cyan(` ${L.gatewayYes}`));
|
|
604
|
-
try {
|
|
605
|
-
const { spawn } = require('child_process');
|
|
606
|
-
const gatewayBin = path.join(__dirname, '..', '..', 'bin', 'natureco.js');
|
|
607
|
-
spawn(process.execPath, [gatewayBin, 'gateway', 'start'], {
|
|
608
|
-
detached: true,
|
|
609
|
-
stdio: 'ignore',
|
|
610
|
-
}).unref();
|
|
611
|
-
printDone(L, 'Gateway');
|
|
612
|
-
if (integrations.includes('WhatsApp')) {
|
|
613
|
-
console.log('');
|
|
614
|
-
console.log(chalk.yellow(lang === 'tr'
|
|
615
|
-
? ' 📱 WhatsApp QR kodunu taratmak için: natureco whatsapp connect'
|
|
616
|
-
: ' 📱 To scan WhatsApp QR code: natureco whatsapp connect'));
|
|
617
|
-
}
|
|
618
|
-
} catch (e) {
|
|
619
|
-
console.log(chalk.yellow(` ⚠ ${e.message}`));
|
|
620
|
-
}
|
|
621
|
-
} else {
|
|
622
|
-
console.log(chalk.gray(` ${L.gatewaySkip}`));
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
// ── ADIM 6: Chat ───────────────────────────────────────────────────────────
|
|
626
|
-
printStep(L, 6, L.chatTitle);
|
|
627
|
-
|
|
628
|
-
const { startChat } = await inquirer.prompt([{
|
|
629
|
-
type: 'confirm',
|
|
630
|
-
name: 'startChat',
|
|
631
|
-
message: L.chatQ,
|
|
632
|
-
default: true,
|
|
633
|
-
}]);
|
|
634
|
-
|
|
635
|
-
console.log('');
|
|
636
|
-
|
|
637
|
-
if (startChat) {
|
|
638
|
-
console.log(chalk.cyan(` ${L.chatStart}`));
|
|
639
|
-
console.log('');
|
|
640
|
-
const chat = require('./chat');
|
|
641
|
-
// NatureCo provider'da seçilen bot adıyla başlat
|
|
642
|
-
await chat(safeBotName, {});
|
|
643
|
-
} else {
|
|
644
|
-
console.log(chalk.gray(` ${L.chatSkip}`));
|
|
645
|
-
console.log('');
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
module.exports = setup;
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
|
|
6
|
+
const BASE_DIR = path.join(os.homedir(), '.natureco');
|
|
7
|
+
const CONFIG_FILE = path.join(BASE_DIR, 'config.json');
|
|
8
|
+
|
|
9
|
+
const DIRS = ['sources', 'concepts', 'cache', 'skills', 'memory', 'sessions', 'backups'];
|
|
10
|
+
|
|
11
|
+
function setup(params) {
|
|
12
|
+
try {
|
|
13
|
+
const [action] = params || [];
|
|
14
|
+
|
|
15
|
+
if (!action || action === 'status') return cmdStatus();
|
|
16
|
+
if (action === 'config') return cmdConfig();
|
|
17
|
+
if (action === 'workspace') return cmdWorkspace();
|
|
18
|
+
if (action === 'dirs') return cmdDirs();
|
|
19
|
+
|
|
20
|
+
console.log(chalk.red(`\n Unknown setup action: ${action}\n`));
|
|
21
|
+
console.log(chalk.gray(' Usage: natureco setup [config|workspace|dirs|status]\n'));
|
|
22
|
+
} catch (err) {
|
|
23
|
+
console.log(chalk.red(`\n Setup error: ${err.message}\n`));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function cmdStatus() {
|
|
28
|
+
console.log(chalk.cyan('\n Setup Status\n'));
|
|
29
|
+
|
|
30
|
+
const configExists = fs.existsSync(CONFIG_FILE);
|
|
31
|
+
const dirExists = fs.existsSync(BASE_DIR);
|
|
32
|
+
|
|
33
|
+
console.log(chalk.white(' Config: ') + (configExists ? chalk.green('exists') : chalk.yellow('missing')));
|
|
34
|
+
console.log(chalk.white(' Directory: ') + (dirExists ? chalk.green('exists') : chalk.yellow('missing')));
|
|
35
|
+
|
|
36
|
+
if (dirExists) {
|
|
37
|
+
const existing = fs.readdirSync(BASE_DIR).filter(f => fs.statSync(path.join(BASE_DIR, f)).isDirectory());
|
|
38
|
+
const present = DIRS.filter(d => existing.includes(d));
|
|
39
|
+
const absent = DIRS.filter(d => !existing.includes(d));
|
|
40
|
+
if (present.length) console.log(chalk.white(' Dirs: ') + chalk.green(present.join(', ')));
|
|
41
|
+
if (absent.length) console.log(chalk.white(' Missing: ') + chalk.yellow(absent.join(', ')));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log('');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function cmdConfig() {
|
|
48
|
+
if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
|
|
49
|
+
|
|
50
|
+
const defaults = {
|
|
51
|
+
version: 1,
|
|
52
|
+
created: new Date().toISOString(),
|
|
53
|
+
updated: new Date().toISOString(),
|
|
54
|
+
setupCompleted: false,
|
|
55
|
+
skills: { enabled: true, list: [] },
|
|
56
|
+
mcpServers: {},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
60
|
+
console.log(chalk.yellow('\n Config already exists at: ' + CONFIG_FILE + '\n'));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(defaults, null, 2), 'utf8');
|
|
65
|
+
console.log(chalk.green('\n Config created at: ' + CONFIG_FILE + '\n'));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function cmdWorkspace() {
|
|
69
|
+
if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
|
|
70
|
+
|
|
71
|
+
const workspaceDir = path.join(BASE_DIR, 'workspace');
|
|
72
|
+
const logsDir = path.join(BASE_DIR, 'logs');
|
|
73
|
+
|
|
74
|
+
if (!fs.existsSync(workspaceDir)) fs.mkdirSync(workspaceDir, { recursive: true });
|
|
75
|
+
if (!fs.existsSync(logsDir)) fs.mkdirSync(logsDir, { recursive: true });
|
|
76
|
+
|
|
77
|
+
console.log(chalk.green('\n Workspace directories created:\n'));
|
|
78
|
+
console.log(chalk.gray(' ' + workspaceDir));
|
|
79
|
+
console.log(chalk.gray(' ' + logsDir));
|
|
80
|
+
console.log('');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function cmdDirs() {
|
|
84
|
+
if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
|
|
85
|
+
|
|
86
|
+
let created = 0;
|
|
87
|
+
for (const dir of DIRS) {
|
|
88
|
+
const p = path.join(BASE_DIR, dir);
|
|
89
|
+
if (!fs.existsSync(p)) {
|
|
90
|
+
fs.mkdirSync(p, { recursive: true });
|
|
91
|
+
created++;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log(chalk.green(`\n Created ${created} data director${created === 1 ? 'y' : 'ies'}`));
|
|
96
|
+
if (created > 0) {
|
|
97
|
+
console.log(chalk.gray(' Location: ' + BASE_DIR));
|
|
98
|
+
}
|
|
99
|
+
console.log('');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = setup;
|