natureco-cli 2.23.29 → 2.23.30

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.
Files changed (71) hide show
  1. package/README.md +94 -11
  2. package/bin/natureco.js +402 -4
  3. package/package.json +1 -1
  4. package/src/commands/admin-rpc.js +219 -0
  5. package/src/commands/agent.js +89 -0
  6. package/src/commands/approvals.js +53 -0
  7. package/src/commands/backup.js +124 -0
  8. package/src/commands/bonjour.js +167 -0
  9. package/src/commands/capability.js +64 -0
  10. package/src/commands/clickclack.js +130 -0
  11. package/src/commands/commitments.js +32 -0
  12. package/src/commands/completion.js +76 -0
  13. package/src/commands/configure.js +93 -0
  14. package/src/commands/crestodian.js +92 -0
  15. package/src/commands/daemon.js +60 -0
  16. package/src/commands/device-pair.js +248 -0
  17. package/src/commands/devices.js +110 -0
  18. package/src/commands/directory.js +47 -0
  19. package/src/commands/dns.js +58 -0
  20. package/src/commands/docs.js +43 -0
  21. package/src/commands/exec-policy.js +71 -0
  22. package/src/commands/gateway-server.js +1155 -24
  23. package/src/commands/health.js +18 -0
  24. package/src/commands/imessage.js +128 -14
  25. package/src/commands/infer.js +73 -0
  26. package/src/commands/irc.js +64 -15
  27. package/src/commands/mattermost.js +114 -12
  28. package/src/commands/memory-cmd.js +134 -1
  29. package/src/commands/message.js +9 -3
  30. package/src/commands/migrate.js +213 -2
  31. package/src/commands/node.js +98 -0
  32. package/src/commands/nodes.js +106 -0
  33. package/src/commands/oc-path.js +200 -0
  34. package/src/commands/onboard.js +70 -0
  35. package/src/commands/open-prose.js +67 -0
  36. package/src/commands/policy.js +176 -0
  37. package/src/commands/proxy.js +155 -0
  38. package/src/commands/qr.js +28 -0
  39. package/src/commands/sandbox.js +125 -0
  40. package/src/commands/secrets.js +118 -0
  41. package/src/commands/setup.js +113 -7
  42. package/src/commands/signal.js +447 -18
  43. package/src/commands/sms.js +123 -19
  44. package/src/commands/system.js +53 -0
  45. package/src/commands/terminal.js +21 -0
  46. package/src/commands/thread-ownership.js +157 -0
  47. package/src/commands/transcripts.js +72 -0
  48. package/src/commands/voice.js +82 -0
  49. package/src/commands/vydra.js +98 -0
  50. package/src/commands/workboard.js +207 -0
  51. package/src/tools/audio_understanding.js +154 -0
  52. package/src/tools/browser.js +112 -0
  53. package/src/tools/canvas.js +104 -0
  54. package/src/tools/document_extract.js +84 -0
  55. package/src/tools/duckduckgo.js +54 -0
  56. package/src/tools/exa_search.js +66 -0
  57. package/src/tools/firecrawl.js +104 -0
  58. package/src/tools/image_generation.js +99 -0
  59. package/src/tools/llm_task.js +118 -0
  60. package/src/tools/media_understanding.js +128 -0
  61. package/src/tools/music_generation.js +113 -0
  62. package/src/tools/parallel_search.js +77 -0
  63. package/src/tools/phone_control.js +80 -0
  64. package/src/tools/phone_control_enhanced.js +184 -0
  65. package/src/tools/searxng.js +61 -0
  66. package/src/tools/speech_to_text.js +135 -0
  67. package/src/tools/text_to_speech.js +105 -0
  68. package/src/tools/thread_ownership.js +88 -0
  69. package/src/tools/video_generation.js +72 -0
  70. package/src/tools/web_readability.js +104 -0
  71. package/src/utils/memory.js +200 -0
@@ -1,13 +1,25 @@
1
1
  const chalk = require('chalk');
2
2
  const inquirer = require('../utils/inquirer-wrapper');
3
3
  const { getConfig, saveConfig } = require('../utils/config');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const os = require('os');
7
+ const { spawn, execSync } = require('child_process');
4
8
 
5
- async function signal(action) {
9
+ const SIGNAL_DIR = path.join(os.homedir(), '.natureco', 'signal');
10
+ const SIGNAL_PID_FILE = path.join(SIGNAL_DIR, 'daemon.pid');
11
+ const SIGNAL_LOG_FILE = path.join(SIGNAL_DIR, 'daemon.log');
12
+ const SIGNAL_CLI_VERSION = '0.13.6';
13
+
14
+ async function signal(action, subAction) {
6
15
  if (!action || action === 'connect') return connectSignal();
7
16
  if (action === 'disconnect') return disconnectSignal();
8
17
  if (action === 'status') return statusSignal();
18
+ if (action === 'install') return installSignalCli();
19
+ if (action === 'daemon') return manageDaemon(subAction);
20
+ if (action === 'probe') return probeSignalCli();
9
21
  console.log(chalk.red('\n❌ Unknown action\n'));
10
- console.log(chalk.gray('Available actions: connect, disconnect, status\n'));
22
+ console.log(chalk.gray('Available actions: connect, disconnect, status, install, daemon, probe\n'));
11
23
  process.exit(1);
12
24
  }
13
25
 
@@ -18,34 +30,90 @@ async function connectSignal() {
18
30
  process.exit(1);
19
31
  }
20
32
  console.log(chalk.yellow('\n⏳ Signal bağlantısı hazırlanıyor...\n'));
21
- console.log(chalk.gray('Signal, signal-cli REST API üzerinden bağlanır.'));
22
- console.log(chalk.gray('Önce signal-cli kurulu olmalı: https://github.com/AsamK/signal-cli\n'));
33
+ console.log(chalk.gray('Signal, signal-cli REST API üzerinden bağlanır.\n'));
34
+
35
+ const existing = config.signalHttpUrl || '';
36
+ const existingAccount = config.signalAccount || '';
37
+ const existingDm = config.signalDmPolicy || 'pairing';
38
+ const existingMode = config.signalApiMode || 'auto';
39
+
23
40
  const answers = await inquirer.prompt([
24
- { type: 'input', name: 'httpUrl', message: 'signal-cli REST API URL (örn: http://localhost:8080):', validate: v => v.trim() ? true : 'URL boş olamaz' },
25
- { type: 'input', name: 'account', message: 'Signal hesap numarası (+905551234567):', validate: v => v.trim() ? true : 'Numara boş olamaz' },
26
- { type: 'list', name: 'dmPolicy', message: 'DM politikası:', choices: [{ name: 'Pairing (önerilen)', value: 'pairing' }, { name: 'Allowlist', value: 'allowlist' }, { name: 'Open', value: 'open' }, { name: 'Disabled', value: 'disabled' }], default: 'pairing' },
41
+ { type: 'input', name: 'httpUrl', message: 'signal-cli REST API URL:', default: existing || 'http://localhost:8080', validate: v => v.trim() ? true : 'URL boş olamaz' },
42
+ { type: 'input', name: 'account', message: 'Signal hesap numarası (+905551234567):', default: existingAccount, validate: v => v.trim() ? true : 'Numara boş olamaz' },
43
+ {
44
+ type: 'list', name: 'apiMode', message: 'API modu:', default: existingMode,
45
+ choices: [
46
+ { name: 'Auto-detect (önerilen)', value: 'auto' },
47
+ { name: 'Native (signal-cli JSON-RPC)', value: 'native' },
48
+ { name: 'Container (bbernhard/signal-cli-rest-api)', value: 'container' },
49
+ ]
50
+ },
51
+ { type: 'confirm', name: 'autoStart', message: 'Gateway ile signal-cli daemon\'ı otomatik başlatılsın mı?', default: config.signalAutoStart !== undefined ? config.signalAutoStart : true },
52
+ {
53
+ type: 'list', name: 'receiveMode', message: 'Mesaj alma modu:', default: config.signalReceiveMode || 'on-start',
54
+ choices: [
55
+ { name: 'Gateway başlangıcında dinlemeye başla (önerilen)', value: 'on-start' },
56
+ { name: 'Manuel (sadece status kontrol)', value: 'manual' },
57
+ ]
58
+ },
59
+ { type: 'list', name: 'dmPolicy', message: 'DM politikası:', default: existingDm, choices: [
60
+ { name: 'Pairing (önerilen) — eşleşme onayı ile', value: 'pairing' },
61
+ { name: 'Allowlist — sadece izin listesi', value: 'allowlist' },
62
+ { name: 'Open — herkese açık', value: 'open' },
63
+ { name: 'Disabled — devre dışı', value: 'disabled' },
64
+ ]},
27
65
  ]);
66
+
28
67
  const botId = `signal_${Date.now()}`;
29
- config.signalHttpUrl = answers.httpUrl.trim();
68
+ config.signalHttpUrl = answers.httpUrl.trim().replace(/\/+$/, '');
30
69
  config.signalAccount = answers.account.trim();
70
+ config.signalApiMode = answers.apiMode;
71
+ config.signalAutoStart = answers.autoStart;
72
+ config.signalReceiveMode = answers.receiveMode;
31
73
  config.signalDmPolicy = answers.dmPolicy;
32
74
  config.signalBotId = botId;
33
75
  saveConfig(config);
76
+
34
77
  console.log(chalk.green('\n✅ Signal bağlantısı kaydedildi!\n'));
35
78
  console.log(chalk.cyan('Bot ID:'), chalk.white(botId));
36
- console.log(chalk.cyan('API URL:'), chalk.white(answers.httpUrl.trim()));
37
- console.log(chalk.cyan('Hesap:'), chalk.white(answers.account.trim()));
38
- console.log(chalk.gray('\nNot: signal-cli\'nin çalıştığından emin olun.'));
39
- console.log(chalk.gray('Gateway ile başlatmak için: natureco gateway start\n'));
79
+ console.log(chalk.cyan('REST API URL:'), chalk.white(config.signalHttpUrl));
80
+ console.log(chalk.cyan('Hesap:'), chalk.white(config.signalAccount));
81
+ console.log(chalk.cyan('API Modu:'), chalk.white(answers.apiMode));
82
+ console.log(chalk.cyan('DM Politikası:'), chalk.white(answers.dmPolicy));
83
+
84
+ if (answers.autoStart) {
85
+ const signalCliPath = findSignalCli();
86
+ if (signalCliPath) {
87
+ console.log(chalk.gray(`\nsignal-cli bulundu: ${signalCliPath}`));
88
+ } else {
89
+ console.log(chalk.yellow('\n⚠️ signal-cli bulunamadı. İndirmek için:'));
90
+ console.log(chalk.cyan(' natureco signal install'));
91
+ }
92
+ }
93
+ console.log(chalk.gray('\nGateway ile başlatmak için: natureco gateway start\n'));
40
94
  }
41
95
 
42
96
  async function disconnectSignal() {
43
97
  const config = getConfig();
44
- if (!config.signalBotId) { console.log(chalk.gray('\n⚠️ No Signal connection found\n')); return; }
45
- const { confirm } = await inquirer.prompt([{ type: 'confirm', name: 'confirm', message: 'Signal bağlantısını kaldırmak istediğinize emin misiniz?', default: false }]);
46
- if (!confirm) { console.log(chalk.gray('\nCancelled\n')); return; }
98
+ if (!config.signalBotId) {
99
+ console.log(chalk.gray('\n⚠️ No Signal connection found\n'));
100
+ return;
101
+ }
102
+ const { confirm } = await inquirer.prompt([
103
+ { type: 'confirm', name: 'confirm', message: 'Signal bağlantısını kaldırmak istediğinize emin misiniz?', default: false }
104
+ ]);
105
+ if (!confirm) {
106
+ console.log(chalk.gray('\nCancelled\n'));
107
+ return;
108
+ }
109
+ // Stop daemon if running
110
+ stopDaemonProcess();
111
+
47
112
  delete config.signalHttpUrl;
48
113
  delete config.signalAccount;
114
+ delete config.signalApiMode;
115
+ delete config.signalAutoStart;
116
+ delete config.signalReceiveMode;
49
117
  delete config.signalDmPolicy;
50
118
  delete config.signalBotId;
51
119
  saveConfig(config);
@@ -54,13 +122,374 @@ async function disconnectSignal() {
54
122
 
55
123
  function statusSignal() {
56
124
  const config = getConfig();
57
- if (!config.signalBotId) { console.log(chalk.gray('\n⚠️ Signal not connected\n')); console.log(chalk.gray('Connect with: natureco signal connect\n')); return; }
125
+ if (!config.signalBotId) {
126
+ console.log(chalk.gray('\n⚠️ Signal not connected\n'));
127
+ console.log(chalk.gray('Connect with: natureco signal connect\n'));
128
+ return;
129
+ }
130
+
131
+ const daemonRunning = isDaemonRunning();
132
+ const apiReachable = probeSync(config);
133
+
58
134
  console.log(chalk.green('\n✅ Signal connected\n'));
59
135
  console.log(chalk.cyan('Bot ID:'), chalk.white(config.signalBotId));
60
- console.log(chalk.cyan('API URL:'), chalk.white(config.signalHttpUrl));
136
+ console.log(chalk.cyan('REST API URL:'), chalk.white(config.signalHttpUrl));
61
137
  console.log(chalk.cyan('Hesap:'), chalk.white(config.signalAccount));
138
+ console.log(chalk.cyan('API Modu:'), chalk.white(config.signalApiMode || 'auto'));
62
139
  console.log(chalk.cyan('DM Politikası:'), chalk.white(config.signalDmPolicy || 'pairing'));
63
- console.log(chalk.gray('\nDisconnect with: natureco signal disconnect\n'));
140
+
141
+ console.log('');
142
+ console.log(chalk.cyan('Daemon Durumu:'), daemonRunning ? chalk.green('✓ Çalışıyor') : chalk.gray('✗ Durduruldu'));
143
+ console.log(chalk.cyan('API Erişilebilirlik:'), apiReachable ? chalk.green('✓ Ulaşılabilir') : chalk.red('✗ Ulaşılamıyor'));
144
+
145
+ if (config.signalCliPath) {
146
+ console.log(chalk.gray(`\nsignal-cli: ${config.signalCliPath}`));
147
+ }
148
+ const cliPath = findSignalCli();
149
+ if (cliPath) {
150
+ console.log(chalk.gray(`signal-cli binary: ${cliPath}`));
151
+ }
152
+ console.log(chalk.gray('\nActions: connect, disconnect, install, daemon start/stop/status, probe\n'));
153
+ }
154
+
155
+ async function installSignalCli() {
156
+ console.log(chalk.yellow('\n⏳ signal-cli indiriliyor...\n'));
157
+
158
+ if (!fs.existsSync(SIGNAL_DIR)) {
159
+ fs.mkdirSync(SIGNAL_DIR, { recursive: true });
160
+ }
161
+
162
+ const platform = process.platform;
163
+ let downloadUrl;
164
+ let archiveName;
165
+
166
+ if (platform === 'win32') {
167
+ archiveName = `signal-cli-${SIGNAL_CLI_VERSION}-Windows.tar.gz`;
168
+ downloadUrl = `https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/${archiveName}`;
169
+ } else if (platform === 'linux') {
170
+ archiveName = `signal-cli-${SIGNAL_CLI_VERSION}-Linux.tar.gz`;
171
+ downloadUrl = `https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/${archiveName}`;
172
+ } else if (platform === 'darwin') {
173
+ archiveName = `signal-cli-${SIGNAL_CLI_VERSION}-macOS.tar.gz`;
174
+ downloadUrl = `https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/${archiveName}`;
175
+ } else {
176
+ console.log(chalk.red(`\n❌ Platform desteklenmiyor: ${platform}\n`));
177
+ console.log(chalk.gray('Manual kurulum: https://github.com/AsamK/signal-cli#installation\n'));
178
+ process.exit(1);
179
+ }
180
+
181
+ const archivePath = path.join(SIGNAL_DIR, archiveName);
182
+ const extractDir = path.join(SIGNAL_DIR, `signal-cli-${SIGNAL_CLI_VERSION}`);
183
+
184
+ if (fs.existsSync(extractDir)) {
185
+ console.log(chalk.gray(`signal-cli ${SIGNAL_CLI_VERSION} zaten indirilmiş: ${extractDir}`));
186
+ const config = getConfig();
187
+ config.signalCliPath = path.join(extractDir, 'bin', 'signal-cli' + (platform === 'win32' ? '.bat' : ''));
188
+ saveConfig(config);
189
+ console.log(chalk.green('✅ Hazır\n'));
190
+ return;
191
+ }
192
+
193
+ try {
194
+ console.log(chalk.cyan(`İndiriliyor: ${downloadUrl}`));
195
+ const response = await fetch(downloadUrl);
196
+ if (!response.ok) {
197
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
198
+ }
199
+ const buffer = Buffer.from(await response.arrayBuffer());
200
+ fs.writeFileSync(archivePath, buffer);
201
+ console.log(chalk.green(`✓ İndirildi (${(buffer.length / 1024 / 1024).toFixed(1)} MB)`));
202
+
203
+ // Extract
204
+ console.log(chalk.cyan('Ayıklanıyor...'));
205
+ const tar = require('tar');
206
+ fs.mkdirSync(extractDir, { recursive: true });
207
+ await tar.x({ file: archivePath, cwd: SIGNAL_DIR });
208
+ console.log(chalk.green('✓ Ayıklandı'));
209
+
210
+ // Clean up archive
211
+ fs.unlinkSync(archivePath);
212
+
213
+ // Make executable on Unix
214
+ if (platform !== 'win32') {
215
+ const binaryPath = path.join(extractDir, 'bin', 'signal-cli');
216
+ if (fs.existsSync(binaryPath)) {
217
+ fs.chmodSync(binaryPath, 0o755);
218
+ }
219
+ }
220
+
221
+ // Save path to config
222
+ const config = getConfig();
223
+ config.signalCliPath = path.join(extractDir, 'bin', 'signal-cli' + (platform === 'win32' ? '.bat' : ''));
224
+ saveConfig(config);
225
+
226
+ console.log(chalk.green(`\n✅ signal-cli ${SIGNAL_CLI_VERSION} kuruldu!\n`));
227
+ console.log(chalk.cyan('Binary:'), chalk.white(config.signalCliPath));
228
+ console.log(chalk.gray('\nDaemon\'ı başlatmak için: natureco signal daemon start\n'));
229
+
230
+ } catch (err) {
231
+ console.log(chalk.red(`\n❌ Kurulum hatası: ${err.message}\n`));
232
+ console.log(chalk.gray('Manuel kurulum: https://github.com/AsamK/signal-cli#installation\n'));
233
+ process.exit(1);
234
+ }
235
+ }
236
+
237
+ async function manageDaemon(subAction) {
238
+ const config = getConfig();
239
+ if (!config.signalBotId) {
240
+ console.log(chalk.red('\n❌ Signal bağlı değil\n'));
241
+ process.exit(1);
242
+ }
243
+
244
+ if (subAction === 'start') {
245
+ return startDaemon(config);
246
+ } else if (subAction === 'stop') {
247
+ return stopDaemon();
248
+ } else if (subAction === 'status') {
249
+ return daemonStatus();
250
+ } else {
251
+ console.log(chalk.red('\n❌ Unknown daemon action\n'));
252
+ console.log(chalk.gray('Usage: natureco signal daemon <start|stop|status>\n'));
253
+ process.exit(1);
254
+ }
255
+ }
256
+
257
+ async function startDaemon(config) {
258
+ if (isDaemonRunning()) {
259
+ console.log(chalk.yellow('\n⚠️ Daemon already running\n'));
260
+ console.log(chalk.cyan('PID:'), chalk.white(fs.readFileSync(SIGNAL_PID_FILE, 'utf-8').trim()));
261
+ return;
262
+ }
263
+
264
+ const cliPath = config.signalCliPath || findSignalCli();
265
+ if (!cliPath) {
266
+ console.log(chalk.red('\n❌ signal-cli bulunamadı\n'));
267
+ console.log(chalk.yellow('Önce indirin:'), chalk.cyan('natureco signal install\n'));
268
+ process.exit(1);
269
+ }
270
+
271
+ if (!fs.existsSync(cliPath)) {
272
+ console.log(chalk.red(`\n❌ signal-cli binary bulunamadı: ${cliPath}\n`));
273
+ process.exit(1);
274
+ }
275
+
276
+ if (!fs.existsSync(SIGNAL_DIR)) {
277
+ fs.mkdirSync(SIGNAL_DIR, { recursive: true });
278
+ }
279
+
280
+ const httpUrl = config.signalHttpUrl || 'http://localhost:8080';
281
+ const urlObj = new URL(httpUrl);
282
+ const host = urlObj.hostname || '127.0.0.1';
283
+ const port = urlObj.port || '8080';
284
+ const account = config.signalAccount;
285
+
286
+ console.log(chalk.yellow(`\n⏳ signal-cli daemon başlatılıyor...\n`));
287
+ console.log(chalk.gray(`HTTP: ${host}:${port}`));
288
+ console.log(chalk.gray(`Hesap: ${account}`));
289
+
290
+ const args = [
291
+ 'daemon',
292
+ '--http', `${host}:${port}`,
293
+ '--no-receive-stdout',
294
+ ];
295
+ if (account) {
296
+ args.push('-a', account);
297
+ }
298
+
299
+ const logFd = fs.openSync(SIGNAL_LOG_FILE, 'a');
300
+ const child = spawn(cliPath, args, {
301
+ detached: true,
302
+ stdio: ['ignore', logFd, logFd],
303
+ windowsHide: true,
304
+ });
305
+
306
+ child.unref();
307
+ fs.writeFileSync(SIGNAL_PID_FILE, String(child.pid), 'utf-8');
308
+
309
+ console.log(chalk.green('✅ Daemon başlatıldı'));
310
+ console.log(chalk.cyan('PID:'), chalk.white(child.pid));
311
+ console.log(chalk.cyan('Log:'), chalk.white(SIGNAL_LOG_FILE));
312
+
313
+ // Wait for API to be ready
314
+ console.log(chalk.gray('\nAPI hazır olana kadar bekleniyor...'));
315
+ for (let i = 0; i < 30; i++) {
316
+ await new Promise(r => setTimeout(r, 1000));
317
+ if (probeSync(config)) {
318
+ console.log(chalk.green('✓ API hazır\n'));
319
+ return;
320
+ }
321
+ process.stdout.write('.');
322
+ }
323
+ console.log(chalk.yellow('\n⚠️ API yanıt vermedi, logları kontrol edin\n'));
324
+ }
325
+
326
+ function stopDaemon() {
327
+ if (!isDaemonRunning()) {
328
+ console.log(chalk.gray('\n⚠️ Daemon not running\n'));
329
+ return;
330
+ }
331
+
332
+ const pid = parseInt(fs.readFileSync(SIGNAL_PID_FILE, 'utf-8').trim());
333
+ try {
334
+ if (process.platform === 'win32') {
335
+ execSync(`taskkill /F /PID ${pid}`, { stdio: 'ignore' });
336
+ } else {
337
+ process.kill(pid, 'SIGTERM');
338
+ setTimeout(() => {
339
+ try { process.kill(pid, 0); process.kill(pid, 'SIGKILL'); } catch {}
340
+ }, 3000);
341
+ }
342
+ if (fs.existsSync(SIGNAL_PID_FILE)) {
343
+ fs.unlinkSync(SIGNAL_PID_FILE);
344
+ }
345
+ console.log(chalk.green('\n✅ Daemon durduruldu\n'));
346
+ } catch (err) {
347
+ console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
348
+ }
349
+ }
350
+
351
+ function stopDaemonProcess() {
352
+ if (isDaemonRunning()) {
353
+ const pid = parseInt(fs.readFileSync(SIGNAL_PID_FILE, 'utf-8').trim());
354
+ try {
355
+ if (process.platform === 'win32') {
356
+ execSync(`taskkill /F /PID ${pid}`, { stdio: 'ignore' });
357
+ } else {
358
+ process.kill(pid, 'SIGTERM');
359
+ }
360
+ } catch {}
361
+ if (fs.existsSync(SIGNAL_PID_FILE)) {
362
+ fs.unlinkSync(SIGNAL_PID_FILE);
363
+ }
364
+ }
365
+ }
366
+
367
+ function daemonStatus() {
368
+ const running = isDaemonRunning();
369
+ console.log(running
370
+ ? chalk.green(`\n✅ Daemon is running (PID: ${fs.readFileSync(SIGNAL_PID_FILE, 'utf-8').trim()})\n`)
371
+ : chalk.gray('\n⚠️ Daemon is not running\n'));
372
+ }
373
+
374
+ function isDaemonRunning() {
375
+ if (!fs.existsSync(SIGNAL_PID_FILE)) return false;
376
+ try {
377
+ const pid = parseInt(fs.readFileSync(SIGNAL_PID_FILE, 'utf-8').trim());
378
+ process.kill(pid, 0);
379
+ return true;
380
+ } catch {
381
+ if (fs.existsSync(SIGNAL_PID_FILE)) {
382
+ fs.unlinkSync(SIGNAL_PID_FILE);
383
+ }
384
+ return false;
385
+ }
386
+ }
387
+
388
+ async function probeSignalCli() {
389
+ const config = getConfig();
390
+ if (!config.signalHttpUrl) {
391
+ console.log(chalk.red('\n❌ Signal bağlantısı yapılmamış\n'));
392
+ console.log(chalk.gray('Önce: natureco signal connect\n'));
393
+ process.exit(1);
394
+ }
395
+
396
+ const baseUrl = config.signalHttpUrl;
397
+ const mode = config.signalApiMode || 'auto';
398
+ console.log(chalk.yellow(`\n⏳ Problanıyor: ${baseUrl}\n`));
399
+
400
+ let nativeOk = false;
401
+ let containerOk = false;
402
+
403
+ // Try native mode
404
+ try {
405
+ const res = await fetch(`${baseUrl}/api/v1/check`, { signal: AbortSignal.timeout(5000) });
406
+ nativeOk = res.ok;
407
+ if (nativeOk) {
408
+ const text = await res.text();
409
+ console.log(chalk.green('✓ Native JSON-RPC API:'), chalk.white(res.status, text.slice(0, 100)));
410
+ }
411
+ } catch (err) {
412
+ console.log(chalk.gray(`✗ Native JSON-RPC API: ${err.message}`));
413
+ }
414
+
415
+ // Try container mode
416
+ try {
417
+ const res = await fetch(`${baseUrl}/v1/about`, { signal: AbortSignal.timeout(5000) });
418
+ containerOk = res.ok;
419
+ if (containerOk) {
420
+ const data = await res.json();
421
+ console.log(chalk.green('✓ Container REST API:'), chalk.white(JSON.stringify(data).slice(0, 100)));
422
+ }
423
+ } catch (err) {
424
+ console.log(chalk.gray(`✗ Container REST API: ${err.message}`));
425
+ }
426
+
427
+ if (mode === 'auto') {
428
+ const detected = nativeOk ? 'native' : containerOk ? 'container' : 'none';
429
+ console.log(chalk.cyan(`\nAuto-detect sonucu: ${detected}`));
430
+ }
431
+
432
+ const cliPath = findSignalCli();
433
+ if (cliPath) {
434
+ console.log(chalk.gray(`\nsignal-cli binary: ${cliPath}`));
435
+ try {
436
+ const versionOut = execSync(`"${cliPath}" --version`, { encoding: 'utf-8', timeout: 10000 });
437
+ console.log(chalk.gray(`Version: ${versionOut.trim()}`));
438
+ } catch {
439
+ console.log(chalk.gray('Version sorgulanamadı'));
440
+ }
441
+ }
442
+
443
+ console.log('');
444
+ }
445
+
446
+ function probeSync(config) {
447
+ if (!config.signalHttpUrl) return false;
448
+ const baseUrl = config.signalHttpUrl;
449
+ try {
450
+ const res = execSync(
451
+ `powershell -Command "try { $r = Invoke-WebRequest -Uri '${baseUrl}/api/v1/check' -TimeoutSec 3 -UseBasicParsing; exit 0 } catch { exit 1 }"`,
452
+ { timeout: 10000, stdio: 'pipe' }
453
+ );
454
+ return true;
455
+ } catch {
456
+ // Also check container mode
457
+ try {
458
+ execSync(
459
+ `powershell -Command "try { $r = Invoke-WebRequest -Uri '${baseUrl}/v1/about' -TimeoutSec 3 -UseBasicParsing; exit 0 } catch { exit 1 }"`,
460
+ { timeout: 10000, stdio: 'pipe' }
461
+ );
462
+ return true;
463
+ } catch {
464
+ return false;
465
+ }
466
+ }
467
+ }
468
+
469
+ function findSignalCli() {
470
+ const config = getConfig();
471
+ if (config.signalCliPath && fs.existsSync(config.signalCliPath)) {
472
+ return config.signalCliPath;
473
+ }
474
+
475
+ // Check installed locations
476
+ const candidates = [
477
+ path.join(SIGNAL_DIR, `signal-cli-${SIGNAL_CLI_VERSION}`, 'bin', 'signal-cli' + (process.platform === 'win32' ? '.bat' : '')),
478
+ path.join(SIGNAL_DIR, `signal-cli-${SIGNAL_CLI_VERSION}`, 'bin', 'signal-cli'),
479
+ ];
480
+
481
+ for (const candidate of candidates) {
482
+ if (fs.existsSync(candidate)) return candidate;
483
+ }
484
+
485
+ // Check PATH
486
+ try {
487
+ const which = execSync(process.platform === 'win32' ? 'where signal-cli' : 'which signal-cli', { encoding: 'utf-8', timeout: 5000 });
488
+ const p = which.trim().split('\n')[0];
489
+ if (p && fs.existsSync(p)) return p;
490
+ } catch {}
491
+
492
+ return null;
64
493
  }
65
494
 
66
495
  module.exports = signal;