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/health.js
CHANGED
|
@@ -1,18 +1,148 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const F = require('../utils/format');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
2
5
|
const os = require('os');
|
|
3
6
|
|
|
7
|
+
const CHECKS = {
|
|
8
|
+
config: { label: 'Configuration', desc: 'Check if config file exists and is valid' },
|
|
9
|
+
gateway: { label: 'Gateway', desc: 'Check if gateway is running' },
|
|
10
|
+
nodes: { label: 'Nodes', desc: 'Check node connectivity' },
|
|
11
|
+
disk: { label: 'Disk', desc: 'Check disk space for ~/.natureco' },
|
|
12
|
+
};
|
|
13
|
+
|
|
4
14
|
function health(args) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
console.log(
|
|
12
|
-
console.log(
|
|
13
|
-
console.log(
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
const [action, ...params] = args || [];
|
|
16
|
+
|
|
17
|
+
if (!action || action === 'run') return cmdRun();
|
|
18
|
+
if (action === 'list') return cmdList();
|
|
19
|
+
if (action === 'check') return cmdCheck(params[0]);
|
|
20
|
+
|
|
21
|
+
console.log(chalk.red(`\n Unknown health action: ${action}\n`));
|
|
22
|
+
console.log(chalk.gray(' Usage: natureco health <action> [params]'));
|
|
23
|
+
console.log(chalk.gray(' Actions: run, list, check <name>\n'));
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function cmdRun() {
|
|
28
|
+
const results = [];
|
|
29
|
+
|
|
30
|
+
results.push(runCheck('config', checkConfig));
|
|
31
|
+
results.push(runCheck('gateway', checkGateway));
|
|
32
|
+
results.push(runCheck('nodes', checkNodes));
|
|
33
|
+
results.push(runCheck('disk', checkDisk));
|
|
34
|
+
|
|
35
|
+
const passed = results.filter(r => r.status === 'pass').length;
|
|
36
|
+
const failed = results.filter(r => r.status === 'fail').length;
|
|
37
|
+
const warnings = results.filter(r => r.status === 'warn').length;
|
|
38
|
+
|
|
39
|
+
F.header('Health Check');
|
|
40
|
+
|
|
41
|
+
const statusMap = { pass: 'ā', fail: 'ā', warn: 'ā ' };
|
|
42
|
+
const rows = results.map(r => [
|
|
43
|
+
r.label,
|
|
44
|
+
statusMap[r.status] || '?',
|
|
45
|
+
r.message,
|
|
46
|
+
]);
|
|
47
|
+
F.table(['Check', 'Status', 'Detail'], rows);
|
|
48
|
+
|
|
49
|
+
for (const r of results) {
|
|
50
|
+
F.dot(r.status === 'pass', r.label);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const summary = `${passed} passed, ${warnings} warnings, ${failed} failed`;
|
|
54
|
+
if (failed > 0) {
|
|
55
|
+
F.error(summary);
|
|
56
|
+
} else {
|
|
57
|
+
F.success(summary);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function cmdList() {
|
|
62
|
+
F.list(Object.entries(CHECKS).map(([key, check]) => ({
|
|
63
|
+
label: key,
|
|
64
|
+
desc: `${check.label} ā ${check.desc}`,
|
|
65
|
+
})));
|
|
66
|
+
F.info(`Run all: ${F.cmd('natureco health run')}`);
|
|
67
|
+
F.info(`Run one: ${F.cmd('natureco health check <name>')}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function cmdCheck(name) {
|
|
71
|
+
if (!name || !CHECKS[name]) {
|
|
72
|
+
console.log(chalk.red(`\n Unknown check: ${name}\n`));
|
|
73
|
+
console.log(chalk.gray(' Available checks: ' + Object.keys(CHECKS).join(', ') + '\n'));
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const handlers = { config: checkConfig, gateway: checkGateway, nodes: checkNodes, disk: checkDisk };
|
|
78
|
+
const result = runCheck(name, handlers[name]);
|
|
79
|
+
|
|
80
|
+
if (result.status === 'pass') {
|
|
81
|
+
F.success(`${result.label}: ${result.message}`);
|
|
82
|
+
} else if (result.status === 'warn') {
|
|
83
|
+
F.warning(`${result.label}: ${result.message}`);
|
|
84
|
+
} else {
|
|
85
|
+
F.error(`${result.label}: ${result.message}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function runCheck(name, fn) {
|
|
90
|
+
try { return { name, ...CHECKS[name], ...fn() }; }
|
|
91
|
+
catch (err) { return { name, ...CHECKS[name], status: 'fail', message: err.message }; }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function checkConfig() {
|
|
95
|
+
const configDir = path.join(os.homedir(), '.natureco');
|
|
96
|
+
const configFile = path.join(configDir, 'config.json');
|
|
97
|
+
|
|
98
|
+
if (!fs.existsSync(configDir)) return { status: 'fail', message: '~/.natureco directory does not exist' };
|
|
99
|
+
if (!fs.existsSync(configFile)) return { status: 'fail', message: 'config.json not found' };
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
|
103
|
+
return { status: 'pass', message: 'Config file exists and is valid' };
|
|
104
|
+
} catch {
|
|
105
|
+
return { status: 'fail', message: 'config.json is not valid JSON' };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function checkGateway() {
|
|
110
|
+
const pidFile = path.join(os.homedir(), '.natureco', 'gateway.pid');
|
|
111
|
+
if (!fs.existsSync(pidFile)) return { status: 'warn', message: 'Gateway is not running' };
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10);
|
|
115
|
+
process.kill(pid, 0);
|
|
116
|
+
return { status: 'pass', message: `Gateway running (PID: ${pid})` };
|
|
117
|
+
} catch {
|
|
118
|
+
return { status: 'warn', message: 'Gateway PID file exists but process is not running' };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function checkNodes() {
|
|
123
|
+
const nodesFile = path.join(os.homedir(), '.natureco', 'nodes.json');
|
|
124
|
+
if (!fs.existsSync(nodesFile)) return { status: 'warn', message: 'No nodes configured' };
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
const nodes = JSON.parse(fs.readFileSync(nodesFile, 'utf8'));
|
|
128
|
+
const names = Object.keys(nodes);
|
|
129
|
+
const online = names.filter(n => nodes[n].online);
|
|
130
|
+
return { status: 'pass', message: `${online.length}/${names.length} nodes online` };
|
|
131
|
+
} catch {
|
|
132
|
+
return { status: 'fail', message: 'nodes.json is invalid' };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function checkDisk() {
|
|
137
|
+
const dir = path.join(os.homedir(), '.natureco');
|
|
138
|
+
if (!fs.existsSync(dir)) return { status: 'warn', message: '~/.natureco does not exist' };
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
const stat = fs.statSync(dir);
|
|
142
|
+
return { status: 'pass', message: `Directory exists, last modified: ${stat.mtime.toISOString().slice(0, 10)}` };
|
|
143
|
+
} catch {
|
|
144
|
+
return { status: 'fail', message: 'Cannot access ~/.natureco' };
|
|
145
|
+
}
|
|
16
146
|
}
|
|
17
147
|
|
|
18
148
|
module.exports = health;
|
package/src/commands/help.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const F = require('../utils/format');
|
|
2
3
|
const { getConfig } = require('../utils/config');
|
|
3
4
|
|
|
4
5
|
function help() {
|
|
@@ -15,10 +16,10 @@ function help() {
|
|
|
15
16
|
console.log('');
|
|
16
17
|
console.log(chalk.green.bold(` NatureCo CLI `) + chalk.gray(`v${version}`));
|
|
17
18
|
console.log(chalk.gray(' Terminal-native AI agent\n'));
|
|
18
|
-
|
|
19
|
+
F.divider();
|
|
19
20
|
|
|
20
21
|
// āā Kurulum & GiriÅ āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
21
|
-
|
|
22
|
+
F.section('Kurulum & GiriÅ');
|
|
22
23
|
printCmd('natureco setup', 'İlk kurulum sihirbazı (provider, bot, entegrasyon)');
|
|
23
24
|
printCmd('natureco login', 'API key ile giriÅ yap');
|
|
24
25
|
printCmd('natureco logout', 'ĆıkıŠyap');
|
|
@@ -26,7 +27,7 @@ function help() {
|
|
|
26
27
|
printCmd('natureco doctor', 'Sistem saÄlıÄı kontrolü');
|
|
27
28
|
|
|
28
29
|
// āā Chat āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
29
|
-
|
|
30
|
+
F.section('Chat');
|
|
30
31
|
printCmd('natureco chat', 'Varsayılan bot ile sohbet baÅlat');
|
|
31
32
|
printCmd('natureco chat <bot>', 'Belirli bot ile sohbet (boÅluklu isim desteklenir)');
|
|
32
33
|
printCmd('natureco chat --resume', 'Son oturuma devam et');
|
|
@@ -35,7 +36,7 @@ function help() {
|
|
|
35
36
|
printCmd('natureco bots', 'Bot listesini gƶster');
|
|
36
37
|
|
|
37
38
|
// āā Entegrasyonlar āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
38
|
-
|
|
39
|
+
F.section('Entegrasyonlar');
|
|
39
40
|
printCmd('natureco telegram connect', 'Telegram bot baÄla');
|
|
40
41
|
printCmd('natureco whatsapp connect', 'WhatsApp QR kod ile baÄla');
|
|
41
42
|
printCmd('natureco discord connect', 'Discord bot baÄla');
|
|
@@ -48,14 +49,14 @@ function help() {
|
|
|
48
49
|
printCmd('natureco webhooks connect', 'Webhook ekle');
|
|
49
50
|
|
|
50
51
|
// āā Gateway & Dashboard āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
51
|
-
|
|
52
|
+
F.section('Gateway & Dashboard');
|
|
52
53
|
printCmd('natureco gateway start', 'Gateway\'i arka planda baÅlat (WhatsApp dahil)');
|
|
53
54
|
printCmd('natureco gateway stop', 'Gateway\'i durdur');
|
|
54
55
|
printCmd('natureco gateway status', 'Gateway durumu ve son loglar');
|
|
55
56
|
printCmd('natureco dashboard', 'Web arayüzünü aç (localhost:3848)');
|
|
56
57
|
|
|
57
58
|
// āā Skill & MCP āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
58
|
-
|
|
59
|
+
F.section('Skill & MCP');
|
|
59
60
|
printCmd('natureco skills', 'Yüklü skill\'leri listele');
|
|
60
61
|
printCmd('natureco skills install <s>', 'NatureHub\'dan skill yükle');
|
|
61
62
|
printCmd('natureco skills install clawhub:<s>', 'ClawHub\'dan skill yükle');
|
|
@@ -67,7 +68,7 @@ function help() {
|
|
|
67
68
|
printCmd('natureco mcp templates', 'Hazır MCP Åablonları');
|
|
68
69
|
|
|
69
70
|
// āā Otomasyon āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
70
|
-
|
|
71
|
+
F.section('Otomasyon');
|
|
71
72
|
printCmd('natureco cron add', 'ZamanlanmıŠgƶrev oluÅtur');
|
|
72
73
|
printCmd('natureco cron list', 'Cron gƶrevlerini listele');
|
|
73
74
|
printCmd('natureco cron remove', 'Cron gƶrevi sil');
|
|
@@ -79,7 +80,7 @@ function help() {
|
|
|
79
80
|
printCmd('natureco migrate --from openclaw', 'OpenClaw\'dan geƧiÅ');
|
|
80
81
|
|
|
81
82
|
// āā DiÄer āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
82
|
-
|
|
83
|
+
F.section('DiÄer');
|
|
83
84
|
printCmd('natureco channels [action]', 'Kanal yƶnetimi (list|status|remove|logs)');
|
|
84
85
|
printCmd('natureco models [action]', 'Model yƶnetimi (list|set|scan|aliases)');
|
|
85
86
|
printCmd('natureco memory [action]', 'Hafıza yƶnetimi (status|list|search|show|clear)');
|
|
@@ -98,8 +99,8 @@ function help() {
|
|
|
98
99
|
printCmd('natureco init', 'Proje klasƶrü oluÅtur (.natureco/)');
|
|
99
100
|
|
|
100
101
|
// āā Chat iƧi komutlar āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
F.section('Chat İƧi Komutlar');
|
|
103
|
+
F.divider();
|
|
103
104
|
printInChat('/clear', 'Ekranı temizle');
|
|
104
105
|
printInChat('/bot [ad]', 'Bot deÄiÅtir');
|
|
105
106
|
printInChat('/skills', 'Aktif skill\'leri gƶster');
|
|
@@ -113,42 +114,40 @@ function help() {
|
|
|
113
114
|
|
|
114
115
|
// āā Mevcut config ƶzeti āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
115
116
|
if (config.providerUrl || config.botName) {
|
|
116
|
-
|
|
117
|
+
F.section('Mevcut Yapılandırma');
|
|
117
118
|
if (config.providerUrl) {
|
|
118
119
|
const provider = config.providerUrl.replace('https://', '').split('/')[0];
|
|
119
|
-
|
|
120
|
+
F.kv('Provider', provider);
|
|
120
121
|
}
|
|
121
122
|
if (config.providerModel) {
|
|
122
|
-
|
|
123
|
+
F.kv('Model', config.providerModel);
|
|
123
124
|
}
|
|
124
125
|
if (config.botName) {
|
|
125
|
-
|
|
126
|
+
F.kv('Bot', config.botName);
|
|
126
127
|
}
|
|
127
128
|
if (config.userName) {
|
|
128
|
-
|
|
129
|
+
F.kv('Kullanıcı', config.userName);
|
|
129
130
|
}
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
console.log(chalk.gray(' API Key : ') + chalk.cyan('developers.natureco.me'));
|
|
137
|
-
console.log(chalk.gray(' npm : ') + chalk.cyan('npmjs.com/package/natureco-cli'));
|
|
133
|
+
F.divider();
|
|
134
|
+
F.kv('Döküman', 'natureco.me/cli');
|
|
135
|
+
F.kv('API Key', 'developers.natureco.me');
|
|
136
|
+
F.kv('npm', 'npmjs.com/package/natureco-cli');
|
|
138
137
|
console.log('');
|
|
139
138
|
}
|
|
140
139
|
|
|
141
140
|
function printCmd(cmd, desc) {
|
|
142
141
|
console.log(
|
|
143
|
-
|
|
144
|
-
chalk.
|
|
142
|
+
' ' + F.flag(cmd.padEnd(38)) +
|
|
143
|
+
chalk.dim(desc)
|
|
145
144
|
);
|
|
146
145
|
}
|
|
147
146
|
|
|
148
147
|
function printInChat(cmd, desc) {
|
|
149
148
|
console.log(
|
|
150
|
-
|
|
151
|
-
chalk.
|
|
149
|
+
' ' + F.cmd(cmd.padEnd(20)) +
|
|
150
|
+
chalk.dim(desc)
|
|
152
151
|
);
|
|
153
152
|
}
|
|
154
153
|
|
package/src/commands/hooks.js
CHANGED
|
@@ -1,87 +1,141 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
hooks
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
console.log(chalk.
|
|
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
|
-
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
|
|
6
|
+
const HOOKS_FILE = path.join(os.homedir(), '.natureco', 'hooks.json');
|
|
7
|
+
|
|
8
|
+
function loadHooks() {
|
|
9
|
+
if (!fs.existsSync(HOOKS_FILE)) return [];
|
|
10
|
+
try { return JSON.parse(fs.readFileSync(HOOKS_FILE, 'utf8')); }
|
|
11
|
+
catch { return []; }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function saveHooks(hooks) {
|
|
15
|
+
const dir = path.dirname(HOOKS_FILE);
|
|
16
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
17
|
+
fs.writeFileSync(HOOKS_FILE, JSON.stringify(hooks, null, 2), 'utf8');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function hooks(args) {
|
|
21
|
+
const [action, ...params] = args || [];
|
|
22
|
+
|
|
23
|
+
if (!action || action === 'list') return cmdList();
|
|
24
|
+
if (action === 'info') return cmdInfo(params[0]);
|
|
25
|
+
if (action === 'check') return cmdCheck(params[0]);
|
|
26
|
+
if (action === 'enable') return cmdEnable(params[0]);
|
|
27
|
+
if (action === 'disable') return cmdDisable(params[0]);
|
|
28
|
+
if (action === 'install') return cmdInstall(params[0]);
|
|
29
|
+
if (action === 'update') return cmdUpdate(params[0]);
|
|
30
|
+
|
|
31
|
+
console.log(chalk.red(`\n Unknown hooks action: ${action}\n`));
|
|
32
|
+
console.log(chalk.gray(' Usage: natureco hooks <action> [params]'));
|
|
33
|
+
console.log(chalk.gray(' Actions: list, info <name>, check <name>, enable <name>, disable <name>, install <url>, update <name>\n'));
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function cmdList() {
|
|
38
|
+
const hooks = loadHooks();
|
|
39
|
+
|
|
40
|
+
console.log(chalk.cyan(`\n Hooks (${hooks.length})\n`));
|
|
41
|
+
console.log(chalk.gray(' ' + 'ā'.repeat(48)));
|
|
42
|
+
|
|
43
|
+
if (hooks.length === 0) {
|
|
44
|
+
console.log(chalk.gray(' No hooks installed.\n'));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
for (const h of hooks) {
|
|
49
|
+
const status = h.disabled ? chalk.red('disabled') : chalk.green('enabled');
|
|
50
|
+
console.log(` ${chalk.white(h.name)} ${chalk.gray(`ā ${status}`)}`);
|
|
51
|
+
if (h.type) console.log(chalk.gray(` Type: ${h.type}`));
|
|
52
|
+
if (h.url) console.log(chalk.gray(` URL: ${h.url}`));
|
|
53
|
+
}
|
|
54
|
+
console.log('');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function cmdInfo(name) {
|
|
58
|
+
if (!name) { console.log(chalk.red('\n Usage: natureco hooks info <name>\n')); process.exit(1); }
|
|
59
|
+
|
|
60
|
+
const hooks = loadHooks();
|
|
61
|
+
const h = hooks.find(x => x.name === name);
|
|
62
|
+
|
|
63
|
+
if (!h) { console.log(chalk.yellow(`\n Hook "${name}" not found.\n`)); return; }
|
|
64
|
+
|
|
65
|
+
console.log(chalk.cyan(`\n Hook: ${h.name}\n`));
|
|
66
|
+
console.log(chalk.gray(' ' + 'ā'.repeat(48)));
|
|
67
|
+
for (const [key, val] of Object.entries(h)) {
|
|
68
|
+
console.log(` ${chalk.white(key)}: ${chalk.white(typeof val === 'object' ? JSON.stringify(val) : val)}`);
|
|
69
|
+
}
|
|
70
|
+
console.log('');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function cmdCheck(name) {
|
|
74
|
+
if (!name) { console.log(chalk.red('\n Usage: natureco hooks check <name>\n')); process.exit(1); }
|
|
75
|
+
|
|
76
|
+
const hooks = loadHooks();
|
|
77
|
+
const h = hooks.find(x => x.name === name);
|
|
78
|
+
|
|
79
|
+
if (!h) { console.log(chalk.yellow(`\n Hook "${name}" not found.\n`)); return; }
|
|
80
|
+
|
|
81
|
+
const issues = [];
|
|
82
|
+
if (!h.type) issues.push('Missing type');
|
|
83
|
+
if (!h.run) issues.push('Missing run script/command');
|
|
84
|
+
if (h.disabled) issues.push('Hook is disabled');
|
|
85
|
+
|
|
86
|
+
if (issues.length === 0) {
|
|
87
|
+
console.log(chalk.green(`\n Hook "${name}" is valid.\n`));
|
|
88
|
+
} else {
|
|
89
|
+
console.log(chalk.yellow(`\n Hook "${name}" has ${issues.length} issue(s):\n`));
|
|
90
|
+
for (const issue of issues) console.log(chalk.yellow(` - ${issue}`));
|
|
91
|
+
console.log('');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function cmdEnable(name) {
|
|
96
|
+
if (!name) { console.log(chalk.red('\n Usage: natureco hooks enable <name>\n')); process.exit(1); }
|
|
97
|
+
|
|
98
|
+
const hooks = loadHooks();
|
|
99
|
+
const h = hooks.find(x => x.name === name);
|
|
100
|
+
if (!h) { console.log(chalk.yellow(`\n Hook "${name}" not found.\n`)); return; }
|
|
101
|
+
|
|
102
|
+
h.disabled = false;
|
|
103
|
+
saveHooks(hooks);
|
|
104
|
+
console.log(chalk.green(`\n Hook "${name}" enabled.\n`));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function cmdDisable(name) {
|
|
108
|
+
if (!name) { console.log(chalk.red('\n Usage: natureco hooks disable <name>\n')); process.exit(1); }
|
|
109
|
+
|
|
110
|
+
const hooks = loadHooks();
|
|
111
|
+
const h = hooks.find(x => x.name === name);
|
|
112
|
+
if (!h) { console.log(chalk.yellow(`\n Hook "${name}" not found.\n`)); return; }
|
|
113
|
+
|
|
114
|
+
h.disabled = true;
|
|
115
|
+
saveHooks(hooks);
|
|
116
|
+
console.log(chalk.gray(`\n Hook "${name}" disabled.\n`));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function cmdInstall(url) {
|
|
120
|
+
if (!url) { console.log(chalk.red('\n Usage: natureco hooks install <url>\n')); process.exit(1); }
|
|
121
|
+
|
|
122
|
+
const hooks = loadHooks();
|
|
123
|
+
const name = path.basename(url, path.extname(url));
|
|
124
|
+
hooks.push({ name, url, type: 'custom', disabled: false, installedAt: new Date().toISOString() });
|
|
125
|
+
saveHooks(hooks);
|
|
126
|
+
console.log(chalk.green(`\n Hook "${name}" installed from ${url}.\n`));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function cmdUpdate(name) {
|
|
130
|
+
if (!name) { console.log(chalk.red('\n Usage: natureco hooks update <name>\n')); process.exit(1); }
|
|
131
|
+
|
|
132
|
+
const hooks = loadHooks();
|
|
133
|
+
const h = hooks.find(x => x.name === name);
|
|
134
|
+
if (!h) { console.log(chalk.yellow(`\n Hook "${name}" not found.\n`)); return; }
|
|
135
|
+
|
|
136
|
+
h.updatedAt = new Date().toISOString();
|
|
137
|
+
saveHooks(hooks);
|
|
138
|
+
console.log(chalk.green(`\n Hook "${name}" updated.\n`));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
module.exports = hooks;
|