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/channels.js
CHANGED
|
@@ -1,267 +1,422 @@
|
|
|
1
|
-
const chalk = require('chalk');
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (action === '
|
|
12
|
-
if (action === '
|
|
13
|
-
if (action === '
|
|
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
|
-
if (
|
|
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
|
-
if (
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
process.exit(1);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const F = require('../utils/format');
|
|
3
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
|
|
8
|
+
async function channels(args) {
|
|
9
|
+
const [action, ...params] = (args || []);
|
|
10
|
+
|
|
11
|
+
if (!action || action === 'list') return listChannels();
|
|
12
|
+
if (action === 'status') return statusChannels();
|
|
13
|
+
if (action === 'remove') return removeChannel(params[0]);
|
|
14
|
+
if (action === 'logs') return channelLogs(params[0]);
|
|
15
|
+
if (action === 'add') return addChannel();
|
|
16
|
+
if (action === 'login') return loginChannel(params[0]);
|
|
17
|
+
if (action === 'logout') return logoutChannel(params[0]);
|
|
18
|
+
if (action === 'capabilities') return capabilitiesChannels(params[0]);
|
|
19
|
+
if (action === 'resolve') return resolveIdentifier(params[0], params[1]);
|
|
20
|
+
|
|
21
|
+
F.error(`Unknown command: ${action}`);
|
|
22
|
+
F.info('Usage: natureco channels [list|status|add|remove|login|logout|capabilities|resolve|logs]');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function addChannel() {
|
|
27
|
+
F.section('Add Channel');
|
|
28
|
+
F.list([
|
|
29
|
+
'telegram - Connect Telegram bot',
|
|
30
|
+
'whatsapp - Connect WhatsApp bot',
|
|
31
|
+
'discord - Connect Discord bot',
|
|
32
|
+
'slack - Connect Slack bot',
|
|
33
|
+
'signal - Connect Signal bot',
|
|
34
|
+
'irc - Connect IRC bot',
|
|
35
|
+
'mattermost - Connect Mattermost bot',
|
|
36
|
+
'imessage - Connect iMessage bridge',
|
|
37
|
+
'sms - Connect SMS/Twilio',
|
|
38
|
+
'webhooks - Connect webhooks',
|
|
39
|
+
]);
|
|
40
|
+
F.info('Use: natureco <channel> connect');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function loginChannel(channel) {
|
|
44
|
+
if (!channel) {
|
|
45
|
+
F.error('Channel name required');
|
|
46
|
+
F.info('Usage: natureco channels login <telegram|whatsapp|discord|slack|signal|irc|mattermost|imessage|sms|webhooks>');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const config = getConfig();
|
|
51
|
+
const ch = channel.toLowerCase();
|
|
52
|
+
const channelKeys = {
|
|
53
|
+
telegram: 'telegramToken',
|
|
54
|
+
whatsapp: 'whatsappConnected',
|
|
55
|
+
discord: 'discordToken',
|
|
56
|
+
slack: 'slackToken',
|
|
57
|
+
signal: 'signalBotId',
|
|
58
|
+
irc: 'ircBotId',
|
|
59
|
+
mattermost: 'mattermostBotId',
|
|
60
|
+
imessage: 'imessageBotId',
|
|
61
|
+
sms: 'smsBotId',
|
|
62
|
+
webhooks: 'webhooks',
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const key = channelKeys[ch];
|
|
66
|
+
if (!key) {
|
|
67
|
+
F.error(`Unknown channel: ${channel}`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const isConfigured = key === 'webhooks'
|
|
72
|
+
? !!(config.webhooks && config.webhooks.length > 0)
|
|
73
|
+
: !!config[key];
|
|
74
|
+
|
|
75
|
+
if (!isConfigured) {
|
|
76
|
+
F.error(`${channel} channel not configured`);
|
|
77
|
+
F.info(`Configure first with: natureco ${ch} connect`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
F.success(`${channel} session opening...`);
|
|
82
|
+
F.info(`Authentication and session initialization to ${channel} server.`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function logoutChannel(channel) {
|
|
86
|
+
if (!channel) {
|
|
87
|
+
F.error('Channel name required');
|
|
88
|
+
F.info('Usage: natureco channels logout <telegram|whatsapp|discord|slack|signal|irc|mattermost|imessage|sms|webhooks>');
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const config = getConfig();
|
|
93
|
+
const ch = channel.toLowerCase();
|
|
94
|
+
|
|
95
|
+
if (ch === 'telegram') {
|
|
96
|
+
delete config.telegramToken;
|
|
97
|
+
delete config.telegramBotId;
|
|
98
|
+
delete config.telegramAllowedChats;
|
|
99
|
+
} else if (ch === 'whatsapp') {
|
|
100
|
+
if (config.whatsappBotId) {
|
|
101
|
+
const sessionDir = path.join(os.homedir(), '.natureco', 'whatsapp-sessions', config.whatsappBotId);
|
|
102
|
+
if (fs.existsSync(sessionDir)) {
|
|
103
|
+
fs.rmSync(sessionDir, { recursive: true, force: true });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
delete config.whatsappConnected;
|
|
107
|
+
delete config.whatsappBotId;
|
|
108
|
+
delete config.whatsappPhone;
|
|
109
|
+
delete config.whatsappAllowedNumbers;
|
|
110
|
+
} else if (ch === 'discord') {
|
|
111
|
+
delete config.discordToken;
|
|
112
|
+
delete config.discordBotId;
|
|
113
|
+
} else if (ch === 'slack') {
|
|
114
|
+
delete config.slackToken;
|
|
115
|
+
delete config.slackBotId;
|
|
116
|
+
} else if (ch === 'signal') {
|
|
117
|
+
delete config.signalHttpUrl;
|
|
118
|
+
delete config.signalAccount;
|
|
119
|
+
delete config.signalDmPolicy;
|
|
120
|
+
delete config.signalBotId;
|
|
121
|
+
} else if (ch === 'irc') {
|
|
122
|
+
delete config.ircHost; delete config.ircPort; delete config.ircTls;
|
|
123
|
+
delete config.ircNick; delete config.ircUsername; delete config.ircPassword;
|
|
124
|
+
delete config.ircChannels; delete config.ircDmPolicy; delete config.ircBotId;
|
|
125
|
+
} else if (ch === 'mattermost') {
|
|
126
|
+
delete config.mattermostBaseUrl; delete config.mattermostToken;
|
|
127
|
+
delete config.mattermostDmPolicy; delete config.mattermostBotId;
|
|
128
|
+
} else if (ch === 'imessage') {
|
|
129
|
+
delete config.imessageCliPath; delete config.imessageDmPolicy; delete config.imessageBotId;
|
|
130
|
+
} else if (ch === 'sms') {
|
|
131
|
+
delete config.smsAccountSid; delete config.smsAuthToken; delete config.smsFromNumber;
|
|
132
|
+
delete config.smsPublicWebhookUrl; delete config.smsDmPolicy; delete config.smsBotId;
|
|
133
|
+
} else if (ch === 'webhooks') {
|
|
134
|
+
delete config.webhooks; delete config.webhookEnabled;
|
|
135
|
+
} else {
|
|
136
|
+
F.error(`Unknown channel: ${channel}`);
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
saveConfig(config);
|
|
141
|
+
F.success(`${channel} session closed and config cleaned`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function capabilitiesChannels(channel) {
|
|
145
|
+
const capabilities = [
|
|
146
|
+
{ name: 'telegram', send: '✓', receive: '✓', media: '✓', polls: '✓', admin: '✓', webhooks: '✓', threads: '✓' },
|
|
147
|
+
{ name: 'whatsapp', send: '✓', receive: '✓', media: '✓', polls: '✗', admin: '✗', webhooks: '✓', threads: '✗' },
|
|
148
|
+
{ name: 'discord', send: '✓', receive: '✓', media: '✓', polls: '✓', admin: '✓', webhooks: '✓', threads: '✓' },
|
|
149
|
+
{ name: 'slack', send: '✓', receive: '✓', media: '✓', polls: '✓', admin: '✓', webhooks: '✓', threads: '✓' },
|
|
150
|
+
{ name: 'signal', send: '✓', receive: '✓', media: '✓', polls: '✗', admin: '✗', webhooks: '✗', threads: '✗' },
|
|
151
|
+
{ name: 'irc', send: '✓', receive: '✓', media: '✗', polls: '✗', admin: '✗', webhooks: '✗', threads: '✗' },
|
|
152
|
+
{ name: 'mattermost', send: '✓', receive: '✓', media: '✓', polls: '✓', admin: '✓', webhooks: '✓', threads: '✓' },
|
|
153
|
+
{ name: 'imessage', send: '✓', receive: '✓', media: '✓', polls: '✗', admin: '✗', webhooks: '✗', threads: '✓' },
|
|
154
|
+
{ name: 'sms', send: '✓', receive: '✓', media: '✗', polls: '✗', admin: '✗', webhooks: '✓', threads: '✗' },
|
|
155
|
+
{ name: 'webhooks', send: '✗', receive: '✓', media: '✗', polls: '✗', admin: '✗', webhooks: '✗', threads: '✗' },
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
const entries = channel
|
|
159
|
+
? capabilities.filter(c => c.name === channel.toLowerCase())
|
|
160
|
+
: capabilities;
|
|
161
|
+
|
|
162
|
+
if (channel && entries.length === 0) {
|
|
163
|
+
F.error(`Unknown channel: ${channel}`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const headers = ['Channel', 'Send', 'Recv', 'Media', 'Polls', 'Admin', 'WkHk', 'Threads'];
|
|
168
|
+
const rows = entries.map(c => [c.name, c.send, c.receive, c.media, c.polls, c.admin, c.webhooks, c.threads]);
|
|
169
|
+
|
|
170
|
+
F.table(headers, rows);
|
|
171
|
+
F.meta('WkHk = Webhook Callback support');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function resolveIdentifier(channel, identifier) {
|
|
175
|
+
if (!channel) {
|
|
176
|
+
F.error('Channel name required');
|
|
177
|
+
F.info('Usage: natureco channels resolve <channel> <user/group>');
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (!identifier) {
|
|
182
|
+
F.error('User/group identifier required');
|
|
183
|
+
F.info('Usage: natureco channels resolve <channel> <user/group>');
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const knownKinds = ['telegram', 'whatsapp', 'discord', 'slack', 'signal', 'irc', 'mattermost', 'imessage', 'sms', 'webhooks'];
|
|
188
|
+
const ch = channel.toLowerCase();
|
|
189
|
+
|
|
190
|
+
if (!knownKinds.includes(ch)) {
|
|
191
|
+
F.error(`Unknown channel: ${channel}`);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
F.header('Resolve Identifier');
|
|
196
|
+
F.kv('Channel', ch);
|
|
197
|
+
F.kv('Identifier', identifier);
|
|
198
|
+
F.kv('Action', `Query ${ch} API to resolve "${identifier}" to a canonical user/group ID`);
|
|
199
|
+
F.kv('Result', `[mock] resolved to ${ch}:${identifier.replace(/[^a-zA-Z0-9]/g, '_')}@${ch}.local`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function listChannels() {
|
|
203
|
+
const config = getConfig();
|
|
204
|
+
const channels = [];
|
|
205
|
+
|
|
206
|
+
if (config.telegramToken) {
|
|
207
|
+
channels.push({
|
|
208
|
+
name: 'Telegram',
|
|
209
|
+
type: '✈',
|
|
210
|
+
status: 'connected',
|
|
211
|
+
detail: `token: ${config.telegramToken.slice(0, 12)}...`,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (config.whatsappConnected) {
|
|
216
|
+
channels.push({
|
|
217
|
+
name: 'WhatsApp',
|
|
218
|
+
type: '📱',
|
|
219
|
+
status: 'connected',
|
|
220
|
+
detail: config.whatsappPhone ? `+${config.whatsappPhone.split(':')[0]}` : 'connected',
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (config.discordToken) {
|
|
225
|
+
channels.push({
|
|
226
|
+
name: 'Discord',
|
|
227
|
+
type: '🎮',
|
|
228
|
+
status: 'connected',
|
|
229
|
+
detail: `token: ${config.discordToken.slice(0, 12)}...`,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (config.slackToken) {
|
|
234
|
+
channels.push({
|
|
235
|
+
name: 'Slack',
|
|
236
|
+
type: '💼',
|
|
237
|
+
status: 'connected',
|
|
238
|
+
detail: `token: ${config.slackToken.slice(0, 12)}...`,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (config.signalBotId) {
|
|
243
|
+
channels.push({
|
|
244
|
+
name: 'Signal',
|
|
245
|
+
type: '🔒',
|
|
246
|
+
status: 'connected',
|
|
247
|
+
detail: `account: ${config.signalAccount || 'connected'}`,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (config.ircBotId) {
|
|
252
|
+
channels.push({
|
|
253
|
+
name: 'IRC',
|
|
254
|
+
type: '💬',
|
|
255
|
+
status: 'connected',
|
|
256
|
+
detail: `${config.ircHost}:${config.ircPort} (${config.ircNick})`,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (config.mattermostBotId) {
|
|
261
|
+
channels.push({
|
|
262
|
+
name: 'Mattermost',
|
|
263
|
+
type: '📢',
|
|
264
|
+
status: 'connected',
|
|
265
|
+
detail: `server: ${config.mattermostBaseUrl || 'connected'}`,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (config.imessageBotId) {
|
|
270
|
+
channels.push({
|
|
271
|
+
name: 'iMessage',
|
|
272
|
+
type: '💬',
|
|
273
|
+
status: 'connected',
|
|
274
|
+
detail: 'macOS bridge',
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (config.smsBotId) {
|
|
279
|
+
channels.push({
|
|
280
|
+
name: 'SMS (Twilio)',
|
|
281
|
+
type: '📨',
|
|
282
|
+
status: 'connected',
|
|
283
|
+
detail: `number: ${config.smsFromNumber || 'connected'}`,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (config.webhooks && config.webhooks.length > 0) {
|
|
288
|
+
channels.push({
|
|
289
|
+
name: 'Webhooks',
|
|
290
|
+
type: '🔗',
|
|
291
|
+
status: 'connected',
|
|
292
|
+
detail: `${config.webhooks.length} route`,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
F.header('Channels');
|
|
297
|
+
|
|
298
|
+
if (channels.length === 0) {
|
|
299
|
+
F.info('No connected channels.');
|
|
300
|
+
F.info('To connect:');
|
|
301
|
+
F.list([
|
|
302
|
+
'natureco telegram connect',
|
|
303
|
+
'natureco whatsapp connect',
|
|
304
|
+
'natureco discord connect',
|
|
305
|
+
'natureco slack connect',
|
|
306
|
+
'natureco signal connect',
|
|
307
|
+
'natureco irc connect',
|
|
308
|
+
'natureco mattermost connect',
|
|
309
|
+
'natureco imessage connect',
|
|
310
|
+
'natureco sms connect',
|
|
311
|
+
'natureco webhooks connect',
|
|
312
|
+
]);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
F.table(['Name', 'Type', 'Status', 'Detail'],
|
|
317
|
+
channels.map(ch => [ch.name, ch.type, ch.status, ch.detail])
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
F.meta(`Total: ${channels.length} channel(s) connected`);
|
|
321
|
+
F.info('To remove: natureco channels remove <channel>');
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function statusChannels() {
|
|
325
|
+
const config = getConfig();
|
|
326
|
+
|
|
327
|
+
const checks = [
|
|
328
|
+
{ name: 'Telegram', ok: !!config.telegramToken },
|
|
329
|
+
{ name: 'WhatsApp', ok: !!config.whatsappConnected },
|
|
330
|
+
{ name: 'Discord', ok: !!config.discordToken },
|
|
331
|
+
{ name: 'Slack', ok: !!config.slackToken },
|
|
332
|
+
{ name: 'Signal', ok: !!config.signalBotId },
|
|
333
|
+
{ name: 'IRC', ok: !!config.ircBotId },
|
|
334
|
+
{ name: 'Mattermost', ok: !!config.mattermostBotId },
|
|
335
|
+
{ name: 'iMessage', ok: !!config.imessageBotId },
|
|
336
|
+
{ name: 'SMS', ok: !!config.smsBotId },
|
|
337
|
+
{ name: 'Webhooks', ok: !!(config.webhooks && config.webhooks.length > 0) },
|
|
338
|
+
];
|
|
339
|
+
|
|
340
|
+
checks.forEach(ch => F.dot(ch.ok, ch.name));
|
|
341
|
+
|
|
342
|
+
const connected = checks.filter(c => c.ok).length;
|
|
343
|
+
F.kv('Active', `${connected}/${checks.length} channels`);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function removeChannel(channel) {
|
|
347
|
+
if (!channel) {
|
|
348
|
+
F.error('Channel name required');
|
|
349
|
+
F.info('Usage: natureco channels remove <telegram|whatsapp|discord|slack|signal|irc|mattermost|imessage|sms|webhooks>');
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const config = getConfig();
|
|
354
|
+
const ch = channel.toLowerCase();
|
|
355
|
+
|
|
356
|
+
if (ch === 'telegram') {
|
|
357
|
+
delete config.telegramToken;
|
|
358
|
+
delete config.telegramBotId;
|
|
359
|
+
delete config.telegramAllowedChats;
|
|
360
|
+
} else if (ch === 'whatsapp') {
|
|
361
|
+
if (config.whatsappBotId) {
|
|
362
|
+
const sessionDir = path.join(os.homedir(), '.natureco', 'whatsapp-sessions', config.whatsappBotId);
|
|
363
|
+
if (fs.existsSync(sessionDir)) {
|
|
364
|
+
fs.rmSync(sessionDir, { recursive: true, force: true });
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
delete config.whatsappConnected;
|
|
368
|
+
delete config.whatsappBotId;
|
|
369
|
+
delete config.whatsappPhone;
|
|
370
|
+
delete config.whatsappAllowedNumbers;
|
|
371
|
+
} else if (ch === 'discord') {
|
|
372
|
+
delete config.discordToken;
|
|
373
|
+
delete config.discordBotId;
|
|
374
|
+
} else if (ch === 'slack') {
|
|
375
|
+
delete config.slackToken;
|
|
376
|
+
delete config.slackBotId;
|
|
377
|
+
} else if (ch === 'signal') {
|
|
378
|
+
delete config.signalHttpUrl;
|
|
379
|
+
delete config.signalAccount;
|
|
380
|
+
delete config.signalDmPolicy;
|
|
381
|
+
delete config.signalBotId;
|
|
382
|
+
} else if (ch === 'irc') {
|
|
383
|
+
delete config.ircHost; delete config.ircPort; delete config.ircTls;
|
|
384
|
+
delete config.ircNick; delete config.ircUsername; delete config.ircPassword;
|
|
385
|
+
delete config.ircChannels; delete config.ircDmPolicy; delete config.ircBotId;
|
|
386
|
+
} else if (ch === 'mattermost') {
|
|
387
|
+
delete config.mattermostBaseUrl; delete config.mattermostToken;
|
|
388
|
+
delete config.mattermostDmPolicy; delete config.mattermostBotId;
|
|
389
|
+
} else if (ch === 'imessage') {
|
|
390
|
+
delete config.imessageCliPath; delete config.imessageDmPolicy; delete config.imessageBotId;
|
|
391
|
+
} else if (ch === 'sms') {
|
|
392
|
+
delete config.smsAccountSid; delete config.smsAuthToken; delete config.smsFromNumber;
|
|
393
|
+
delete config.smsPublicWebhookUrl; delete config.smsDmPolicy; delete config.smsBotId;
|
|
394
|
+
} else if (ch === 'webhooks') {
|
|
395
|
+
delete config.webhooks; delete config.webhookEnabled;
|
|
396
|
+
} else {
|
|
397
|
+
F.error(`Unknown channel: ${channel}`);
|
|
398
|
+
process.exit(1);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
saveConfig(config);
|
|
402
|
+
F.success(`${channel} removed`);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function channelLogs(channel) {
|
|
406
|
+
const logFile = path.join(os.homedir(), '.natureco', 'gateway.log');
|
|
407
|
+
if (!fs.existsSync(logFile)) {
|
|
408
|
+
F.meta('Log file not found.');
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const lines = fs.readFileSync(logFile, 'utf-8').split('\n').filter(l => l.trim());
|
|
413
|
+
const filtered = channel
|
|
414
|
+
? lines.filter(l => l.toLowerCase().includes(channel.toLowerCase()))
|
|
415
|
+
: lines;
|
|
416
|
+
|
|
417
|
+
const last = filtered.slice(-20);
|
|
418
|
+
F.header(`Channel Logs${channel ? ` (${channel})` : ''}`);
|
|
419
|
+
last.forEach(l => F.meta(l));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
module.exports = channels;
|