natureco-cli 2.23.30 → 2.23.32
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 +178 -167
- 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/ask.js +1 -1
- 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 +228 -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 +229 -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/web-fetch.js +34 -0
- 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 +40 -41
- 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,229 @@
|
|
|
1
|
-
const chalk = require('chalk');
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
console.log('');
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
console.log('');
|
|
206
|
-
console.log(chalk.
|
|
207
|
-
console.log(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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
|
+
const readline = require('readline');
|
|
6
|
+
const inquirer = require('../utils/inquirer-wrapper');
|
|
7
|
+
|
|
8
|
+
const BASE_DIR = path.join(os.homedir(), '.natureco');
|
|
9
|
+
const CONFIG_FILE = path.join(BASE_DIR, 'config.json');
|
|
10
|
+
|
|
11
|
+
const DIRS = ['sources', 'concepts', 'cache', 'skills', 'memory', 'sessions', 'backups'];
|
|
12
|
+
|
|
13
|
+
const PROVIDER_PRESETS = {
|
|
14
|
+
groq: { url: 'https://api.groq.com/openai/v1', model: 'llama-3.3-70b-versatile' },
|
|
15
|
+
openai: { url: 'https://api.openai.com/v1', model: 'gpt-4o' },
|
|
16
|
+
anthropic:{ url: 'https://api.anthropic.com', model: 'claude-sonnet-4-6' },
|
|
17
|
+
deepseek: { url: 'https://api.deepseek.com/v1', model: 'deepseek-chat' },
|
|
18
|
+
ollama: { url: 'http://localhost:11434/v1', model: 'llama3.3' },
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function rlQuestion(query) {
|
|
22
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
23
|
+
return new Promise(resolve => {
|
|
24
|
+
rl.question(query, answer => { rl.close(); resolve(answer.trim()); });
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getConfig() {
|
|
29
|
+
if (!fs.existsSync(CONFIG_FILE)) return {};
|
|
30
|
+
try { return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); }
|
|
31
|
+
catch { return {}; }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function saveConfig(data) {
|
|
35
|
+
if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
|
|
36
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), 'utf8');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function setup(params) {
|
|
40
|
+
try {
|
|
41
|
+
const [action] = params || [];
|
|
42
|
+
|
|
43
|
+
if (!action || action === 'wizard') return await cmdWizard();
|
|
44
|
+
if (action === 'status') return cmdStatus();
|
|
45
|
+
if (action === 'config') return cmdConfig();
|
|
46
|
+
if (action === 'workspace') return cmdWorkspace();
|
|
47
|
+
if (action === 'dirs') return cmdDirs();
|
|
48
|
+
|
|
49
|
+
console.log(chalk.yellow('\n Usage:'));
|
|
50
|
+
console.log(chalk.gray(' natureco setup Interactive setup wizard'));
|
|
51
|
+
console.log(chalk.gray(' natureco setup config Create default config'));
|
|
52
|
+
console.log(chalk.gray(' natureco setup workspace Create workspace directories'));
|
|
53
|
+
console.log(chalk.gray(' natureco setup dirs Create data directories'));
|
|
54
|
+
console.log(chalk.gray(' natureco setup status Show setup status\n'));
|
|
55
|
+
} catch (err) {
|
|
56
|
+
console.log(chalk.red(`\n Setup error: ${err.message}\n`));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function cmdWizard() {
|
|
61
|
+
console.clear();
|
|
62
|
+
console.log('');
|
|
63
|
+
console.log(chalk.green.bold(' (\\_/)'));
|
|
64
|
+
console.log(chalk.green.bold(' (•ᴥ•)'));
|
|
65
|
+
console.log(chalk.green(' />🌿'));
|
|
66
|
+
console.log('');
|
|
67
|
+
console.log(chalk.green.bold(' NatureCo CLI — Setup Wizard'));
|
|
68
|
+
console.log(chalk.gray(' Choose your AI provider and enter your API key.\n'));
|
|
69
|
+
|
|
70
|
+
// Ensure directories
|
|
71
|
+
if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
|
|
72
|
+
for (const dir of DIRS) {
|
|
73
|
+
const p = path.join(BASE_DIR, dir);
|
|
74
|
+
if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const cfg = getConfig();
|
|
78
|
+
|
|
79
|
+
// Step 1: Provider selection
|
|
80
|
+
console.log(chalk.white(' Step 1: Provider'));
|
|
81
|
+
console.log(chalk.gray(' ─────────────────────────────────────────────'));
|
|
82
|
+
const providerKeys = Object.keys(PROVIDER_PRESETS);
|
|
83
|
+
const { provider } = await inquirer.prompt([{
|
|
84
|
+
type: 'list',
|
|
85
|
+
name: 'provider',
|
|
86
|
+
message: ' AI Provider:',
|
|
87
|
+
choices: [
|
|
88
|
+
...providerKeys.map(k => ({
|
|
89
|
+
name: `${k.charAt(0).toUpperCase() + k.slice(1)} (${PROVIDER_PRESETS[k].model})`,
|
|
90
|
+
value: k,
|
|
91
|
+
})),
|
|
92
|
+
{ name: 'Custom URL', value: 'custom' },
|
|
93
|
+
],
|
|
94
|
+
}]);
|
|
95
|
+
|
|
96
|
+
let providerUrl, providerModel;
|
|
97
|
+
if (provider === 'custom') {
|
|
98
|
+
providerUrl = await rlQuestion(` Provider URL (${cfg.providerUrl || 'https://api.openai.com/v1'}): `);
|
|
99
|
+
providerModel = await rlQuestion(` Model (${cfg.providerModel || 'gpt-4o'}): `);
|
|
100
|
+
providerUrl = providerUrl || cfg.providerUrl || 'https://api.openai.com/v1';
|
|
101
|
+
providerModel = providerModel || cfg.providerModel || 'gpt-4o';
|
|
102
|
+
} else {
|
|
103
|
+
const preset = PROVIDER_PRESETS[provider];
|
|
104
|
+
providerUrl = preset.url;
|
|
105
|
+
providerModel = preset.model;
|
|
106
|
+
console.log(chalk.gray(` URL: ${providerUrl}`));
|
|
107
|
+
console.log(chalk.gray(` Model: ${providerModel}`));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Step 2: API Key
|
|
111
|
+
console.log('');
|
|
112
|
+
console.log(chalk.white(' Step 2: API Key'));
|
|
113
|
+
console.log(chalk.gray(' ─────────────────────────────────────────────'));
|
|
114
|
+
console.log(chalk.gray(' Get a key from: ') + chalk.cyan('developers.natureco.me'));
|
|
115
|
+
console.log(chalk.gray(' Or use your own provider API key.\n'));
|
|
116
|
+
|
|
117
|
+
const currentKey = cfg.providerApiKey || '';
|
|
118
|
+
const apiKey = await rlQuestion(` API Key ${currentKey ? '(leave blank to keep current)' : ''}: `);
|
|
119
|
+
if (apiKey) {
|
|
120
|
+
cfg.providerApiKey = apiKey;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Step 3: Save
|
|
124
|
+
cfg.providerUrl = providerUrl;
|
|
125
|
+
cfg.providerModel = providerModel;
|
|
126
|
+
cfg.setupCompleted = true;
|
|
127
|
+
cfg.updated = new Date().toISOString();
|
|
128
|
+
if (!cfg.created) cfg.created = new Date().toISOString();
|
|
129
|
+
if (!cfg.version) cfg.version = 1;
|
|
130
|
+
if (cfg.skills === undefined) cfg.skills = { enabled: true, list: [] };
|
|
131
|
+
if (cfg.mcpServers === undefined) cfg.mcpServers = {};
|
|
132
|
+
|
|
133
|
+
saveConfig(cfg);
|
|
134
|
+
|
|
135
|
+
console.log('');
|
|
136
|
+
console.log(chalk.green(' ✓ Setup complete!\n'));
|
|
137
|
+
console.log(chalk.white(' Config saved to: ') + chalk.gray(CONFIG_FILE));
|
|
138
|
+
console.log('');
|
|
139
|
+
console.log(chalk.white(' Next steps:'));
|
|
140
|
+
console.log(chalk.cyan(' natureco chat Start chatting'));
|
|
141
|
+
console.log(chalk.cyan(' natureco login Login with API key'));
|
|
142
|
+
console.log(chalk.cyan(' natureco help View all commands'));
|
|
143
|
+
console.log('');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function cmdStatus() {
|
|
147
|
+
console.log(chalk.cyan('\n Setup Status\n'));
|
|
148
|
+
|
|
149
|
+
const configExists = fs.existsSync(CONFIG_FILE);
|
|
150
|
+
const dirExists = fs.existsSync(BASE_DIR);
|
|
151
|
+
|
|
152
|
+
console.log(chalk.white(' Config: ') + (configExists ? chalk.green('exists') : chalk.yellow('missing')));
|
|
153
|
+
console.log(chalk.white(' Directory: ') + (dirExists ? chalk.green('exists') : chalk.yellow('missing')));
|
|
154
|
+
|
|
155
|
+
if (configExists) {
|
|
156
|
+
const cfg = getConfig();
|
|
157
|
+
console.log(chalk.white(' Provider: ') + chalk.gray(cfg.providerUrl || 'not set'));
|
|
158
|
+
console.log(chalk.white(' Model: ') + chalk.gray(cfg.providerModel || 'not set'));
|
|
159
|
+
console.log(chalk.white(' API Key: ') + (cfg.providerApiKey ? chalk.green('set') : chalk.yellow('not set')));
|
|
160
|
+
console.log(chalk.white(' Setup: ') + (cfg.setupCompleted ? chalk.green('completed') : chalk.yellow('incomplete')));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (dirExists) {
|
|
164
|
+
const existing = fs.readdirSync(BASE_DIR).filter(f => fs.statSync(path.join(BASE_DIR, f)).isDirectory());
|
|
165
|
+
const present = DIRS.filter(d => existing.includes(d));
|
|
166
|
+
const absent = DIRS.filter(d => !existing.includes(d));
|
|
167
|
+
if (present.length) console.log(chalk.white(' Dirs: ') + chalk.green(present.join(', ')));
|
|
168
|
+
if (absent.length) console.log(chalk.white(' Missing: ') + chalk.yellow(absent.join(', ')));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
console.log('');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function cmdConfig() {
|
|
175
|
+
if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
|
|
176
|
+
|
|
177
|
+
const defaults = {
|
|
178
|
+
version: 1,
|
|
179
|
+
created: new Date().toISOString(),
|
|
180
|
+
updated: new Date().toISOString(),
|
|
181
|
+
setupCompleted: false,
|
|
182
|
+
skills: { enabled: true, list: [] },
|
|
183
|
+
mcpServers: {},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
187
|
+
console.log(chalk.yellow('\n Config already exists at: ' + CONFIG_FILE + '\n'));
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(defaults, null, 2), 'utf8');
|
|
192
|
+
console.log(chalk.green('\n Config created at: ' + CONFIG_FILE + '\n'));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function cmdWorkspace() {
|
|
196
|
+
if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
|
|
197
|
+
|
|
198
|
+
const workspaceDir = path.join(BASE_DIR, 'workspace');
|
|
199
|
+
const logsDir = path.join(BASE_DIR, 'logs');
|
|
200
|
+
|
|
201
|
+
if (!fs.existsSync(workspaceDir)) fs.mkdirSync(workspaceDir, { recursive: true });
|
|
202
|
+
if (!fs.existsSync(logsDir)) fs.mkdirSync(logsDir, { recursive: true });
|
|
203
|
+
|
|
204
|
+
console.log(chalk.green('\n Workspace directories created:\n'));
|
|
205
|
+
console.log(chalk.gray(' ' + workspaceDir));
|
|
206
|
+
console.log(chalk.gray(' ' + logsDir));
|
|
207
|
+
console.log('');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function cmdDirs() {
|
|
211
|
+
if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
|
|
212
|
+
|
|
213
|
+
let created = 0;
|
|
214
|
+
for (const dir of DIRS) {
|
|
215
|
+
const p = path.join(BASE_DIR, dir);
|
|
216
|
+
if (!fs.existsSync(p)) {
|
|
217
|
+
fs.mkdirSync(p, { recursive: true });
|
|
218
|
+
created++;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
console.log(chalk.green(`\n Created ${created} data director${created === 1 ? 'y' : 'ies'}`));
|
|
223
|
+
if (created > 0) {
|
|
224
|
+
console.log(chalk.gray(' Location: ' + BASE_DIR));
|
|
225
|
+
}
|
|
226
|
+
console.log('');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
module.exports = setup;
|