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/config.js
CHANGED
|
@@ -1,26 +1,41 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const F = require('../utils/format');
|
|
2
3
|
const path = require('path');
|
|
3
|
-
const
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const { getConfig, setConfigValue, getAllConfig, listBackups, restoreConfig, saveConfig, CONFIG_FILE, CONFIG_BACKUP_DIR } = require('../utils/config');
|
|
6
|
+
const TB = require('../utils/token-budget');
|
|
4
7
|
|
|
5
8
|
function config(args) {
|
|
6
9
|
const [action, key, ...valueParts] = args;
|
|
7
10
|
|
|
8
11
|
if (!action) {
|
|
9
|
-
|
|
12
|
+
F.error('Kullanım: natureco config <get|set|unset|list|file|schema|validate|backups|restore> [key] [value]');
|
|
10
13
|
process.exit(1);
|
|
11
14
|
}
|
|
12
15
|
|
|
16
|
+
const SENSITIVE_KEYS = ['apiKey', 'providerApiKey', 'providerApiKey1', 'providerApiKey2', 'secret', 'token', 'password', 'webhookSecret'];
|
|
17
|
+
|
|
18
|
+
function maskSensitive(key, value) {
|
|
19
|
+
if (typeof value !== 'string' || value.length < 8) return value;
|
|
20
|
+
const lower = key.toLowerCase();
|
|
21
|
+
if (!SENSITIVE_KEYS.some(sk => lower.includes(sk.toLowerCase()))) return value;
|
|
22
|
+
return value.slice(0, 4) + '*'.repeat(Math.min(value.length - 8, 16)) + value.slice(-4);
|
|
23
|
+
}
|
|
24
|
+
|
|
13
25
|
if (action === 'list') {
|
|
14
26
|
const cfg = getAllConfig();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
27
|
+
F.header('Configuration');
|
|
28
|
+
const rows = Object.entries(cfg).map(([k, v]) => [
|
|
29
|
+
k,
|
|
30
|
+
maskSensitive(k, typeof v === 'string' ? v : JSON.stringify(v)),
|
|
31
|
+
]);
|
|
32
|
+
F.table(['Key', 'Value'], rows);
|
|
18
33
|
return;
|
|
19
34
|
}
|
|
20
35
|
|
|
21
36
|
if (action === 'get') {
|
|
22
37
|
if (!key) {
|
|
23
|
-
|
|
38
|
+
F.error('Key belirtilmedi.');
|
|
24
39
|
process.exit(1);
|
|
25
40
|
}
|
|
26
41
|
const cfg = getConfig();
|
|
@@ -30,21 +45,20 @@ function config(args) {
|
|
|
30
45
|
value = value?.[k];
|
|
31
46
|
}
|
|
32
47
|
if (value === undefined) {
|
|
33
|
-
|
|
48
|
+
F.info(`${key}: (tanımlı değil)`);
|
|
34
49
|
} else {
|
|
35
|
-
|
|
36
|
-
console.log('');
|
|
50
|
+
F.kv(key, maskSensitive(key, JSON.stringify(value, null, 2)));
|
|
37
51
|
}
|
|
38
52
|
return;
|
|
39
53
|
}
|
|
40
54
|
|
|
41
55
|
if (action === 'set') {
|
|
42
56
|
if (!key) {
|
|
43
|
-
|
|
57
|
+
F.error('Key belirtilmedi.');
|
|
44
58
|
process.exit(1);
|
|
45
59
|
}
|
|
46
60
|
if (valueParts.length === 0) {
|
|
47
|
-
|
|
61
|
+
F.error('Value belirtilmedi.');
|
|
48
62
|
process.exit(1);
|
|
49
63
|
}
|
|
50
64
|
const value = valueParts.join(' ');
|
|
@@ -55,24 +69,121 @@ function config(args) {
|
|
|
55
69
|
} catch {}
|
|
56
70
|
|
|
57
71
|
setConfigValue(key, parsedValue);
|
|
58
|
-
|
|
72
|
+
F.success(`${key} = ${JSON.stringify(parsedValue)}`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (action === 'unset') {
|
|
77
|
+
if (!key) {
|
|
78
|
+
F.error('Key belirtilmedi.');
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
const cfg = getConfig();
|
|
82
|
+
const keys = key.split('.');
|
|
83
|
+
let obj = cfg;
|
|
84
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
85
|
+
obj = obj?.[keys[i]];
|
|
86
|
+
}
|
|
87
|
+
if (obj && keys[keys.length - 1] in obj) {
|
|
88
|
+
delete obj[keys[keys.length - 1]];
|
|
89
|
+
}
|
|
90
|
+
saveConfig(cfg);
|
|
91
|
+
F.success(`Unset: ${key}`);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (action === 'file') {
|
|
96
|
+
const configPath = CONFIG_FILE;
|
|
97
|
+
const exists = fs.existsSync(configPath);
|
|
98
|
+
F.header('Config File');
|
|
99
|
+
F.kv('Path', configPath);
|
|
100
|
+
if (exists) {
|
|
101
|
+
const stats = fs.statSync(configPath);
|
|
102
|
+
const sizeKB = (stats.size / 1024).toFixed(2);
|
|
103
|
+
F.kv('Size', `${sizeKB} KB`);
|
|
104
|
+
F.kv('Last Modified', String(stats.mtime));
|
|
105
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
106
|
+
try {
|
|
107
|
+
const parsed = JSON.parse(content);
|
|
108
|
+
const keys = Object.keys(parsed);
|
|
109
|
+
F.kv('Keys', keys.length ? keys.join(', ') : '(empty)');
|
|
110
|
+
} catch {
|
|
111
|
+
F.error('(invalid JSON)');
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
F.warning('(file does not exist)');
|
|
115
|
+
}
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (action === 'schema') {
|
|
120
|
+
F.section('Config Schema');
|
|
121
|
+
const schema = {
|
|
122
|
+
apiKey: { type: 'string', description: 'API key for the provider', required: true },
|
|
123
|
+
providerUrl: { type: 'string', description: 'Base URL of the provider API', required: true },
|
|
124
|
+
providerModel: { type: 'string', description: 'Default model identifier', required: false, default: 'gpt-4' },
|
|
125
|
+
temperature: { type: 'number', description: 'Sampling temperature (0-2)', required: false, default: 0.7 },
|
|
126
|
+
maxTokens: { type: 'number', description: 'Maximum tokens per response', required: false, default: 2048 },
|
|
127
|
+
systemPrompt: { type: 'string', description: 'Custom system prompt', required: false },
|
|
128
|
+
proxy: { type: 'object', description: 'Proxy configuration', required: false, properties: { host: { type: 'string' }, port: { type: 'number' } } },
|
|
129
|
+
timeout: { type: 'number', description: 'Request timeout in milliseconds', required: false, default: 30000 },
|
|
130
|
+
organization: { type: 'string', description: 'Organization ID for multi-tenant setups', required: false },
|
|
131
|
+
};
|
|
132
|
+
const rows = Object.entries(schema).map(([k, v]) => [
|
|
133
|
+
v.required ? `${k}*` : k,
|
|
134
|
+
v.type,
|
|
135
|
+
v.description,
|
|
136
|
+
v.default !== undefined ? JSON.stringify(v.default) : '—',
|
|
137
|
+
]);
|
|
138
|
+
F.table(['Field', 'Type', 'Description', 'Default'], rows);
|
|
139
|
+
F.meta('* = required');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (action === 'validate') {
|
|
144
|
+
const cfg = getConfig();
|
|
145
|
+
F.section('Config Validation');
|
|
146
|
+
const checks = [
|
|
147
|
+
{ field: 'apiKey', label: 'API Key', required: true },
|
|
148
|
+
{ field: 'providerUrl', label: 'Provider URL', required: true },
|
|
149
|
+
{ field: 'providerModel', label: 'Provider Model', required: false },
|
|
150
|
+
];
|
|
151
|
+
let allPass = true;
|
|
152
|
+
for (const check of checks) {
|
|
153
|
+
const value = cfg[check.field];
|
|
154
|
+
if (check.required && (!value || typeof value !== 'string')) {
|
|
155
|
+
F.error(`${check.label}: FAIL (required)`);
|
|
156
|
+
allPass = false;
|
|
157
|
+
} else if (value && typeof value !== 'string') {
|
|
158
|
+
F.warning(`${check.label}: WARN (expected string, got ${typeof value})`);
|
|
159
|
+
} else if (value) {
|
|
160
|
+
F.success(`${check.label}: PASS`);
|
|
161
|
+
} else {
|
|
162
|
+
F.info(`${check.label}: not set`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (allPass) {
|
|
166
|
+
F.success('All required fields are set.');
|
|
167
|
+
} else {
|
|
168
|
+
F.error('Some required fields are missing.');
|
|
169
|
+
}
|
|
59
170
|
return;
|
|
60
171
|
}
|
|
61
172
|
|
|
62
173
|
if (action === 'backups' || action === 'backup') {
|
|
63
174
|
const backups = listBackups();
|
|
64
|
-
|
|
175
|
+
F.section('Config Yedekleri');
|
|
65
176
|
if (backups.length === 0) {
|
|
66
|
-
|
|
177
|
+
F.info('Hen\u00fcz yedek al\u0131nmam\u0131\u015f.');
|
|
67
178
|
return;
|
|
68
179
|
}
|
|
69
|
-
backups.
|
|
180
|
+
const rows = backups.map((f, i) => {
|
|
70
181
|
const ts = f.replace(/^config-|\.json$/g, '').replace(/T/, ' ').replace(/-/g, ':').replace(/:[^:]*$/, '');
|
|
71
|
-
|
|
72
|
-
console.log(chalk.gray(` ${path.join(CONFIG_BACKUP_DIR, f)}`));
|
|
182
|
+
return [String(i + 1), ts, path.join(CONFIG_BACKUP_DIR, f)];
|
|
73
183
|
});
|
|
74
|
-
|
|
75
|
-
|
|
184
|
+
F.table(['#', 'Tarih', 'Dosya'], rows);
|
|
185
|
+
F.meta('Geri y\u00fcklemek i\u00e7in: natureco config restore <dosya-ad\u0131>');
|
|
186
|
+
F.meta(`\u00d6rnek: natureco config restore ${backups[0] || 'config-....json'}`);
|
|
76
187
|
return;
|
|
77
188
|
}
|
|
78
189
|
|
|
@@ -81,31 +192,118 @@ function config(args) {
|
|
|
81
192
|
if (!backupId) {
|
|
82
193
|
const backups = listBackups();
|
|
83
194
|
if (backups.length === 0) {
|
|
84
|
-
|
|
195
|
+
F.error('Geri y\u00fcklenecek yedek bulunamad\u0131.');
|
|
85
196
|
process.exit(1);
|
|
86
197
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
console.log(chalk.gray(' Yedekleri listelemek için: ') + chalk.cyan('natureco config backups\n'));
|
|
198
|
+
F.section('Geri Y\u00fckleme');
|
|
199
|
+
F.kv('En son yedek', backups[0]);
|
|
200
|
+
F.meta(`Kullan\u0131m: natureco config restore ${backups[0]}`);
|
|
201
|
+
F.meta('Yedekleri listelemek i\u00e7in: natureco config backups');
|
|
92
202
|
return;
|
|
93
203
|
}
|
|
94
204
|
|
|
95
205
|
try {
|
|
96
206
|
const result = restoreConfig(backupId);
|
|
97
|
-
|
|
98
|
-
|
|
207
|
+
F.success(`Config geri y\u00fcklendi: ${result.timestamp}`);
|
|
208
|
+
F.meta(`Kaynak: ${result.path}`);
|
|
99
209
|
} catch (err) {
|
|
100
|
-
|
|
210
|
+
F.error(`Geri y\u00fckleme ba\u015far\u0131s\u0131z: ${err.message}`);
|
|
101
211
|
process.exit(1);
|
|
102
212
|
}
|
|
103
213
|
return;
|
|
104
214
|
}
|
|
105
215
|
|
|
106
|
-
|
|
107
|
-
|
|
216
|
+
if (action === 'budget') {
|
|
217
|
+
return configBudget(key, valueParts);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
F.error(`Ge\u00e7ersiz action: ${action}`);
|
|
221
|
+
F.meta('Kullan\u0131m: natureco config <get|set|unset|list|file|schema|validate|backups|restore|budget> [key] [value]');
|
|
108
222
|
process.exit(1);
|
|
109
223
|
}
|
|
110
224
|
|
|
225
|
+
function configBudget(sub, args) {
|
|
226
|
+
if (!sub || sub === 'show') {
|
|
227
|
+
const b = TB.load();
|
|
228
|
+
F.header('Token Budget');
|
|
229
|
+
F.kv('Preset', b.preset || 'balanced');
|
|
230
|
+
F.kv('Max Context Tokens', String(b.maxContextTokens));
|
|
231
|
+
F.kv('Preserve Recent Tokens', String(b.preserveRecentTokens));
|
|
232
|
+
F.kv('Tail Turns', String(b.tailTurns));
|
|
233
|
+
F.divider();
|
|
234
|
+
F.section('Output Limits');
|
|
235
|
+
F.kv('Tool Max Lines', String(b.toolMaxLines));
|
|
236
|
+
F.kv('Tool Max Chars', String(b.toolMaxChars));
|
|
237
|
+
F.kv('MCP Desc Max Chars', String(b.mcpDescMaxChars));
|
|
238
|
+
F.divider();
|
|
239
|
+
F.section('Content Truncation');
|
|
240
|
+
F.kv('System Prompt Max', String(b.systemPromptMaxChars));
|
|
241
|
+
F.kv('Memory Max Facts', String(b.memoryMaxFacts));
|
|
242
|
+
F.kv('Project Memory Max', String(b.projectMemoryMaxChars));
|
|
243
|
+
F.kv('File Content Max', String(b.fileContentMaxChars));
|
|
244
|
+
F.divider();
|
|
245
|
+
F.section('Conversation');
|
|
246
|
+
F.kv('Messages on Disk', String(b.conversationOnDisk));
|
|
247
|
+
F.kv('Messages in Context', String(b.conversationInContext));
|
|
248
|
+
F.kv('Auto Compact', String(b.autoCompact));
|
|
249
|
+
F.kv('Reserved Tokens', String(b.reservedTokens));
|
|
250
|
+
F.meta('');
|
|
251
|
+
F.meta('Switch preset: natureco config budget preset <efficient|balanced|quality>');
|
|
252
|
+
F.meta('Set a value: natureco config budget set <key> <value>');
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (sub === 'preset') {
|
|
257
|
+
const name = args[0];
|
|
258
|
+
if (!name || !['efficient', 'balanced', 'quality'].includes(name)) {
|
|
259
|
+
F.error('Preset: efficient, balanced, quality');
|
|
260
|
+
F.table(['Preset', 'Description', 'Context'], TB.getPresets().map(p => [p.key, p.label, String(p.maxContextTokens)]));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
TB.setPreset(name);
|
|
264
|
+
F.success('Token budget preset: ' + name);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (sub === 'set') {
|
|
269
|
+
const key = args[0];
|
|
270
|
+
const val = args[1];
|
|
271
|
+
if (!key || val === undefined) {
|
|
272
|
+
F.error('Kullan\u0131m: natureco config budget set <key> <value>');
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const budget = TB.load();
|
|
276
|
+
if (!(key in budget)) {
|
|
277
|
+
F.error('Bilinmeyen budget key: ' + key);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const num = Number(val);
|
|
281
|
+
budget[key] = isNaN(num) ? val : num;
|
|
282
|
+
TB.save(budget);
|
|
283
|
+
F.success(key + ' = ' + budget[key]);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (sub === 'usage') {
|
|
288
|
+
const usage = TB.getAllUsage();
|
|
289
|
+
if (!usage || Object.keys(usage).length === 0) {
|
|
290
|
+
F.info('Hen\u00fcz token kullan\u0131m\u0131 kaydedilmedi.');
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
F.header('Token Usage');
|
|
294
|
+
const rows = Object.entries(usage).map(([sid, u]) => [
|
|
295
|
+
sid.slice(0, 20),
|
|
296
|
+
String(u.total || 0),
|
|
297
|
+
String(u.input || 0),
|
|
298
|
+
String(u.output || 0),
|
|
299
|
+
String(u.count || 0)
|
|
300
|
+
]);
|
|
301
|
+
F.table(['Session', 'Total', 'Input', 'Output', 'Calls'], rows);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
F.error('Budget alt komutu: ' + sub);
|
|
306
|
+
F.meta('Kullan\u0131m: natureco config budget <show|preset|set|usage>');
|
|
307
|
+
}
|
|
308
|
+
|
|
111
309
|
module.exports = config;
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
2
5
|
const readline = require('readline');
|
|
3
6
|
|
|
7
|
+
const BASE_DIR = path.join(os.homedir(), '.natureco');
|
|
8
|
+
const CONFIG_FILE = path.join(BASE_DIR, 'config.json');
|
|
9
|
+
|
|
10
|
+
function getConfig() {
|
|
11
|
+
if (!fs.existsSync(CONFIG_FILE)) return {};
|
|
12
|
+
try { return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); }
|
|
13
|
+
catch { return {}; }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function saveConfig(data) {
|
|
17
|
+
if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
|
|
18
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), 'utf8');
|
|
19
|
+
}
|
|
20
|
+
|
|
4
21
|
function rlQuestion(query) {
|
|
5
22
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
6
23
|
return new Promise(resolve => {
|
|
@@ -8,86 +25,86 @@ function rlQuestion(query) {
|
|
|
8
25
|
});
|
|
9
26
|
}
|
|
10
27
|
|
|
11
|
-
async function configure(
|
|
12
|
-
|
|
13
|
-
|
|
28
|
+
async function configure(params) {
|
|
29
|
+
try {
|
|
30
|
+
const [action] = params || [];
|
|
14
31
|
|
|
15
|
-
|
|
16
|
-
|
|
32
|
+
if (!action) return cmdMenu();
|
|
33
|
+
if (action === 'gateway') return await cmdGateway();
|
|
34
|
+
if (action === 'auth') return await cmdAuth();
|
|
35
|
+
if (action === 'channels') return cmdChannels();
|
|
36
|
+
if (action === 'plugins') return cmdPlugins();
|
|
37
|
+
if (action === 'skills') return cmdSkills();
|
|
17
38
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
console.log(' 7) Cancel');
|
|
25
|
-
console.log();
|
|
39
|
+
console.log(chalk.red(`\n Unknown configure action: ${action}\n`));
|
|
40
|
+
console.log(chalk.gray(' Usage: natureco configure [gateway|auth|channels|plugins|skills]\n'));
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.log(chalk.red(`\n Configure error: ${err.message}\n`));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
26
45
|
|
|
27
|
-
|
|
46
|
+
function cmdMenu() {
|
|
47
|
+
console.log(chalk.cyan('\n Configure\n'));
|
|
48
|
+
console.log(chalk.gray(' Run with an action:'));
|
|
49
|
+
console.log(chalk.gray(' natureco configure gateway Update gateway config'));
|
|
50
|
+
console.log(chalk.gray(' natureco configure auth Update provider keys'));
|
|
51
|
+
console.log(chalk.gray(' natureco configure channels Re-run channels setup'));
|
|
52
|
+
console.log(chalk.gray(' natureco configure plugins Re-run plugin setup'));
|
|
53
|
+
console.log(chalk.gray(' natureco configure skills Re-run skills setup\n'));
|
|
54
|
+
}
|
|
28
55
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
56
|
+
async function cmdGateway() {
|
|
57
|
+
const cfg = getConfig();
|
|
58
|
+
console.log(chalk.cyan('\n Gateway Configuration\n'));
|
|
59
|
+
console.log(chalk.gray(' Current: ') + chalk.white(cfg.gatewayUrl || 'not set'));
|
|
33
60
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
61
|
+
const url = await rlQuestion(` Gateway URL (${cfg.gatewayUrl || 'ws://localhost:3848'}): `);
|
|
62
|
+
const port = await rlQuestion(` Port (${cfg.gatewayPort || 3848}): `);
|
|
38
63
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
config.provider = provider || config.provider || 'openai';
|
|
43
|
-
config.model = model || config.model || 'gpt-4o';
|
|
44
|
-
saveConfig(config);
|
|
45
|
-
console.log(chalk.green(`\n ✅ Provider: ${config.provider}, Model: ${config.model}\n`));
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
64
|
+
cfg.gatewayUrl = url || cfg.gatewayUrl || 'ws://localhost:3848';
|
|
65
|
+
cfg.gatewayPort = parseInt(port) || cfg.gatewayPort || 3848;
|
|
66
|
+
saveConfig(cfg);
|
|
48
67
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const port = await rlQuestion(` Gateway port (${config.gatewayPort || 3848}): `);
|
|
52
|
-
config.gatewayUrl = url || config.gatewayUrl || 'ws://localhost:3848';
|
|
53
|
-
config.gatewayPort = parseInt(port) || config.gatewayPort || 3848;
|
|
54
|
-
saveConfig(config);
|
|
55
|
-
console.log(chalk.green(`\n ✅ Gateway: ${config.gatewayUrl}\n`));
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
68
|
+
console.log(chalk.green(`\n Gateway updated: ${cfg.gatewayUrl}:${cfg.gatewayPort}\n`));
|
|
69
|
+
}
|
|
58
70
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
console.log(chalk.cyan(' natureco whatsapp connect\n'));
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
71
|
+
async function cmdAuth() {
|
|
72
|
+
const cfg = getConfig();
|
|
73
|
+
console.log(chalk.cyan('\n Auth Configuration\n'));
|
|
74
|
+
console.log(chalk.gray(' Current provider key: ') + chalk.white(cfg.providerApiKey ? '(set)' : '(not set)'));
|
|
66
75
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
console.log(chalk.green(`\n ✅ Voice: ${config.tts.provider}\n`));
|
|
75
|
-
return;
|
|
76
|
+
const key = await rlQuestion(' Provider API Key (leave blank to keep current): ');
|
|
77
|
+
if (key) {
|
|
78
|
+
cfg.providerApiKey = key;
|
|
79
|
+
saveConfig(cfg);
|
|
80
|
+
console.log(chalk.green('\n API key updated.\n'));
|
|
81
|
+
} else {
|
|
82
|
+
console.log(chalk.gray('\n No changes made.\n'));
|
|
76
83
|
}
|
|
84
|
+
}
|
|
77
85
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (tavily) config.tavilyApiKey = tavily;
|
|
85
|
-
saveConfig(config);
|
|
86
|
-
console.log(chalk.green('\n ✅ API Keys saved\n'));
|
|
87
|
-
return;
|
|
86
|
+
function cmdChannels() {
|
|
87
|
+
console.log(chalk.cyan('\n Channels Setup\n'));
|
|
88
|
+
console.log(chalk.gray(' To connect a channel:'));
|
|
89
|
+
const channels = ['telegram', 'whatsapp', 'discord', 'slack', 'signal', 'irc', 'mattermost', 'imessage'];
|
|
90
|
+
for (const ch of channels) {
|
|
91
|
+
console.log(chalk.gray(' natureco ' + ch + ' connect'));
|
|
88
92
|
}
|
|
93
|
+
console.log('');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function cmdPlugins() {
|
|
97
|
+
console.log(chalk.cyan('\n Plugin Setup\n'));
|
|
98
|
+
console.log(chalk.gray(' To manage plugins:'));
|
|
99
|
+
console.log(chalk.cyan(' natureco plugins list'));
|
|
100
|
+
console.log(chalk.cyan(' natureco plugins add <url>\n'));
|
|
101
|
+
}
|
|
89
102
|
|
|
90
|
-
|
|
103
|
+
function cmdSkills() {
|
|
104
|
+
console.log(chalk.cyan('\n Skills Setup\n'));
|
|
105
|
+
console.log(chalk.gray(' To manage skills:'));
|
|
106
|
+
console.log(chalk.cyan(' natureco skills list'));
|
|
107
|
+
console.log(chalk.cyan(' natureco skills add <name>\n'));
|
|
91
108
|
}
|
|
92
109
|
|
|
93
110
|
module.exports = configure;
|