natureco-cli 2.23.29 β†’ 2.23.31

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 (111) hide show
  1. package/README.md +94 -11
  2. package/bin/natureco.js +495 -94
  3. package/package.json +1 -1
  4. package/src/commands/acp.js +39 -0
  5. package/src/commands/admin-rpc.js +302 -0
  6. package/src/commands/agent.js +280 -0
  7. package/src/commands/agents.js +114 -30
  8. package/src/commands/approvals.js +214 -0
  9. package/src/commands/backup.js +124 -0
  10. package/src/commands/bonjour.js +167 -0
  11. package/src/commands/browser.js +815 -0
  12. package/src/commands/capability.js +237 -0
  13. package/src/commands/channels.js +422 -267
  14. package/src/commands/chat.js +5 -8
  15. package/src/commands/clawbot.js +19 -0
  16. package/src/commands/clickclack.js +130 -0
  17. package/src/commands/code.js +3 -2
  18. package/src/commands/commitments.js +148 -0
  19. package/src/commands/completion.js +84 -0
  20. package/src/commands/config.js +219 -30
  21. package/src/commands/configure.js +110 -0
  22. package/src/commands/crestodian.js +92 -0
  23. package/src/commands/cron.js +239 -19
  24. package/src/commands/daemon.js +90 -0
  25. package/src/commands/dashboard.js +47 -374
  26. package/src/commands/device-pair.js +248 -0
  27. package/src/commands/devices.js +137 -0
  28. package/src/commands/directory.js +179 -0
  29. package/src/commands/dns.js +196 -0
  30. package/src/commands/docs.js +136 -0
  31. package/src/commands/doctor.js +143 -492
  32. package/src/commands/exec-policy.js +80 -0
  33. package/src/commands/gateway-server.js +1155 -24
  34. package/src/commands/gateway.js +492 -249
  35. package/src/commands/health.js +148 -0
  36. package/src/commands/help.js +24 -25
  37. package/src/commands/hooks.js +141 -87
  38. package/src/commands/imessage.js +128 -14
  39. package/src/commands/infer.js +1474 -0
  40. package/src/commands/irc.js +64 -15
  41. package/src/commands/logs.js +122 -99
  42. package/src/commands/mattermost.js +114 -12
  43. package/src/commands/mcp.js +121 -309
  44. package/src/commands/memory-cmd.js +134 -1
  45. package/src/commands/memory.js +128 -0
  46. package/src/commands/message.js +720 -134
  47. package/src/commands/migrate.js +213 -2
  48. package/src/commands/models.js +39 -1
  49. package/src/commands/node.js +98 -0
  50. package/src/commands/nodes.js +362 -0
  51. package/src/commands/oc-path.js +200 -0
  52. package/src/commands/onboard.js +129 -0
  53. package/src/commands/open-prose.js +67 -0
  54. package/src/commands/pairing.js +108 -107
  55. package/src/commands/path.js +206 -0
  56. package/src/commands/plugins.js +35 -1
  57. package/src/commands/policy.js +176 -0
  58. package/src/commands/proxy.js +306 -0
  59. package/src/commands/qr.js +70 -0
  60. package/src/commands/reset.js +101 -94
  61. package/src/commands/sandbox.js +125 -0
  62. package/src/commands/secrets.js +201 -0
  63. package/src/commands/sessions.js +110 -51
  64. package/src/commands/setup.js +102 -543
  65. package/src/commands/signal.js +447 -18
  66. package/src/commands/skills.js +67 -1
  67. package/src/commands/sms.js +123 -19
  68. package/src/commands/status.js +101 -127
  69. package/src/commands/system.js +53 -0
  70. package/src/commands/tasks.js +208 -100
  71. package/src/commands/terminal.js +139 -0
  72. package/src/commands/thread-ownership.js +157 -0
  73. package/src/commands/transcripts.js +95 -0
  74. package/src/commands/tui.js +41 -0
  75. package/src/commands/uninstall.js +73 -92
  76. package/src/commands/update.js +146 -91
  77. package/src/commands/voice.js +82 -0
  78. package/src/commands/vydra.js +98 -0
  79. package/src/commands/webhooks.js +58 -66
  80. package/src/commands/wiki.js +783 -0
  81. package/src/commands/workboard.js +207 -0
  82. package/src/tools/audio_understanding.js +154 -0
  83. package/src/tools/browser.js +112 -0
  84. package/src/tools/canvas.js +104 -0
  85. package/src/tools/document_extract.js +84 -0
  86. package/src/tools/duckduckgo.js +54 -0
  87. package/src/tools/exa_search.js +66 -0
  88. package/src/tools/firecrawl.js +104 -0
  89. package/src/tools/image_generation.js +99 -0
  90. package/src/tools/llm_task.js +118 -0
  91. package/src/tools/media_understanding.js +128 -0
  92. package/src/tools/music_generation.js +113 -0
  93. package/src/tools/parallel_search.js +77 -0
  94. package/src/tools/phone_control.js +80 -0
  95. package/src/tools/phone_control_enhanced.js +184 -0
  96. package/src/tools/searxng.js +61 -0
  97. package/src/tools/speech_to_text.js +135 -0
  98. package/src/tools/text_to_speech.js +105 -0
  99. package/src/tools/thread_ownership.js +88 -0
  100. package/src/tools/video_generation.js +72 -0
  101. package/src/tools/web_readability.js +104 -0
  102. package/src/utils/agents-md.js +85 -0
  103. package/src/utils/api.js +39 -40
  104. package/src/utils/format.js +144 -0
  105. package/src/utils/headless.js +2 -1
  106. package/src/utils/memory.js +200 -0
  107. package/src/utils/parallel-tools.js +106 -0
  108. package/src/utils/sub-agent.js +148 -0
  109. package/src/utils/token-budget.js +304 -0
  110. package/src/utils/tool-runner.js +7 -5
  111. package/src/utils/web-fetch.js +107 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "2.23.29",
3
+ "version": "2.23.31",
4
4
  "description": "NatureCo AI Bot Terminal Interface",
5
5
  "bin": {
6
6
  "natureco": "bin/natureco.js"
@@ -0,0 +1,39 @@
1
+ const chalk = require('chalk');
2
+
3
+ function acp(args) {
4
+ const [action, ...params] = args || [];
5
+
6
+ if (!action || action === 'status') return cmdStatus();
7
+ if (action === 'info') return cmdInfo();
8
+
9
+ console.log(chalk.red(`\n Unknown acp action: ${action}\n`));
10
+ console.log(chalk.gray(' Usage: natureco acp <action>'));
11
+ console.log(chalk.gray(' Actions: status, info\n'));
12
+ process.exit(1);
13
+ }
14
+
15
+ function cmdStatus() {
16
+ console.log(chalk.cyan('\n ACP (Agent Communication Protocol) Status\n'));
17
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
18
+ console.log(` ${chalk.white('Endpoint:')} ${chalk.green('http://127.0.0.1:3847/acp')}`);
19
+ console.log(` ${chalk.white('Status:')} ${chalk.gray('Stub β€” no real implementation')}`);
20
+ console.log('');
21
+ console.log(chalk.gray(' Available endpoints:'));
22
+ console.log(chalk.gray(' GET /acp β€” Protocol root'));
23
+ console.log(chalk.gray(' GET /acp/health β€” Health check'));
24
+ console.log(chalk.gray(' POST /acp/message β€” Send agent message'));
25
+ console.log(chalk.gray(' GET /acp/agents β€” List agents'));
26
+ console.log('');
27
+ }
28
+
29
+ function cmdInfo() {
30
+ console.log(chalk.cyan('\n ACP Protocol Info\n'));
31
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
32
+ console.log(` ${chalk.white('Protocol:')} ${chalk.cyan('Agent Communication Protocol')}`);
33
+ console.log(` ${chalk.white('Version:')} ${chalk.cyan('1.0.0')}`);
34
+ console.log(` ${chalk.white('Port:')} ${chalk.cyan('3847')}`);
35
+ console.log(` ${chalk.white('Transport:')} ${chalk.cyan('HTTP/JSON')}`);
36
+ console.log('');
37
+ }
38
+
39
+ module.exports = acp;
@@ -0,0 +1,302 @@
1
+ const chalk = require('chalk');
2
+ const http = require('http');
3
+ const { getConfig } = require('../utils/config');
4
+
5
+ const ALLOWED_METHODS = [
6
+ 'health', 'status',
7
+ 'config.get', 'config.set',
8
+ 'channels.status', 'channels.start', 'channels.stop',
9
+ 'agents.list',
10
+ 'logs.tail',
11
+ 'cron.list', 'cron.status',
12
+ 'tasks.list',
13
+ 'plugins.list'
14
+ ];
15
+
16
+ let serverInstance = null;
17
+
18
+ function adminRpc(args) {
19
+ const [action, ...params] = args || [];
20
+
21
+ if (!action || action === 'status') return statusAdmin();
22
+ if (action === 'start') return startAdmin(params[0]);
23
+ if (action === 'stop') return stopAdmin();
24
+ if (action === 'call') return callMethod(params[0], params.slice(1).join(' '));
25
+ if (action === 'methods') return listMethods();
26
+
27
+ console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
28
+ console.log(chalk.gray(' KullanΔ±m: natureco admin-rpc [status|start|stop|call|methods]\n'));
29
+ process.exit(1);
30
+ }
31
+
32
+ function statusAdmin() {
33
+ const running = serverInstance !== null;
34
+ console.log(chalk.cyan('\n πŸ–₯️ Admin HTTP RPC\n'));
35
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
36
+ console.log(` ${chalk.white('Server:')} ${running ? chalk.green(`http://localhost:${serverInstance?.port || 3847}`) : chalk.red('Durduruldu')}`);
37
+ console.log(` ${chalk.white('Methods:')} ${ALLOWED_METHODS.length}`);
38
+ console.log(chalk.gray('\n Commands:'));
39
+ console.log(chalk.cyan(' start [port]') + chalk.gray(' Start RPC server (default: 3847)'));
40
+ console.log(chalk.cyan(' stop') + chalk.gray(' Stop RPC server'));
41
+ console.log(chalk.cyan(' call <method>') + chalk.gray(' Call RPC method'));
42
+ console.log(chalk.cyan(' methods') + chalk.gray(' List methods'));
43
+ console.log();
44
+ }
45
+
46
+ function listMethods() {
47
+ console.log(chalk.cyan('\n πŸ“‹ Admin RPC Methods\n'));
48
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
49
+ for (const m of ALLOWED_METHODS) {
50
+ console.log(` ${chalk.white(m)}`);
51
+ }
52
+ console.log();
53
+ }
54
+
55
+ async function callMethod(method, jsonParams) {
56
+ if (!method) {
57
+ console.log(chalk.red('\n ❌ Method adı gerekli\n'));
58
+ console.log(chalk.cyan(' natureco admin-rpc call health\n'));
59
+ process.exit(1);
60
+ }
61
+
62
+ if (!ALLOWED_METHODS.includes(method)) {
63
+ console.log(chalk.red(`\n ❌ Desteklenmeyen method: ${method}\n`));
64
+ process.exit(1);
65
+ }
66
+
67
+ let params = {};
68
+ if (jsonParams) {
69
+ try { params = JSON.parse(jsonParams); }
70
+ catch { console.log(chalk.red('\n ❌ Geçersiz JSON\n')); process.exit(1); }
71
+ }
72
+
73
+ console.log(chalk.cyan(`\n πŸ“‘ Calling: ${method}\n`));
74
+
75
+ if (method === 'health') {
76
+ console.log(chalk.green(' βœ… System healthy'));
77
+ console.log(chalk.gray(` Node: ${process.version}`));
78
+ console.log(chalk.gray(` Platform: ${process.platform}`));
79
+ console.log(chalk.gray(` Memory: ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB\n`));
80
+ return;
81
+ }
82
+
83
+ if (method === 'status') {
84
+ const config = getConfig();
85
+ console.log(chalk.green(' βœ… Status\n'));
86
+ console.log(chalk.gray(` Gateway: ${config.gatewayUrl || 'not configured'}`));
87
+ console.log(chalk.gray(` Provider: ${config.provider || 'not set'}`));
88
+ console.log(chalk.gray(` Model: ${config.model || 'not set'}\n`));
89
+ return;
90
+ }
91
+
92
+ if (method === 'plugins.list') {
93
+ const { loadTools } = require('../utils/tool-runner');
94
+ const tools = loadTools();
95
+ console.log(chalk.green(` πŸ“¦ ${Object.keys(tools).length} tools loaded\n`));
96
+ for (const [name, t] of Object.entries(tools)) {
97
+ console.log(` ${chalk.white('●')} ${name} ${chalk.gray('- ' + (t.description || '').substring(0, 60))}`);
98
+ }
99
+ console.log();
100
+ return;
101
+ }
102
+
103
+ if (method === 'config.get') {
104
+ const config = getConfig();
105
+ const key = params.key;
106
+ if (key) {
107
+ const value = key.split('.').reduce((o, k) => o?.[k], config);
108
+ console.log(chalk.white(` ${key}: `) + chalk.cyan(JSON.stringify(value)));
109
+ } else {
110
+ console.log(chalk.cyan(JSON.stringify(config, null, 2)));
111
+ }
112
+ console.log();
113
+ return;
114
+ }
115
+
116
+ if (method === 'logs.tail') {
117
+ const lines = params.lines || 20;
118
+ const { execSync } = require('child_process');
119
+ try {
120
+ const logPath = require('path').join(require('os').homedir(), '.natureco', 'logs', 'gateway.log');
121
+ const output = execSync(`tail -${lines} "${logPath}"`, { encoding: 'utf8', maxBuffer: 1024 * 1024 });
122
+ console.log(output);
123
+ } catch {
124
+ console.log(chalk.yellow(' ⚠️ Log bulunamadı\n'));
125
+ }
126
+ return;
127
+ }
128
+
129
+ if (method === 'config.set') {
130
+ const { setConfigValue } = require('../utils/config');
131
+ if (!params.key) { console.log(chalk.red('\n ❌ params.key gerekli\n')); process.exit(1); }
132
+ setConfigValue(params.key, params.value);
133
+ console.log(chalk.green(`\n βœ… config.${params.key} = ${JSON.stringify(params.value)}\n`));
134
+ return;
135
+ }
136
+
137
+ if (method === 'channels.status' || method === 'channels.start' || method === 'channels.stop') {
138
+ const { getAllConfig } = require('../utils/config');
139
+ const cfg = getAllConfig();
140
+ const channels = ['telegram', 'discord', 'slack', 'whatsapp'];
141
+ console.log(chalk.cyan(`\n πŸ“‘ Channel: ${method}\n`));
142
+ if (method === 'channels.status') {
143
+ for (const ch of channels) {
144
+ const token = cfg[`${ch}Token`];
145
+ console.log(` ${token ? chalk.green('●') : chalk.gray('β—‹')} ${ch} ${token ? chalk.gray('(configured)') : chalk.gray('(not set)')}`);
146
+ }
147
+ } else {
148
+ const ch = params.name || 'all';
149
+ console.log(chalk.gray(` ${method.split('.')[1]} ${ch} (simulated)\n`));
150
+ }
151
+ console.log();
152
+ return;
153
+ }
154
+
155
+ if (method === 'agents.list') {
156
+ const { listTasks, getTaskSummary } = require('../utils/background');
157
+ const tasks = listTasks({ limit: 20 });
158
+ const summary = getTaskSummary();
159
+ console.log(chalk.cyan(`\n πŸ‘€ Agents (${summary.active} active, ${summary.total} total)\n`));
160
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
161
+ for (const t of tasks.slice(0, 10)) {
162
+ const icon = t.status === 'succeeded' ? chalk.green('βœ“') : t.status === 'running' ? chalk.yellow('●') : chalk.gray('β—‹');
163
+ console.log(` ${icon} ${chalk.white(t.message || '(no message)')}`);
164
+ console.log(chalk.gray(` [${t.id}] ${t.runtime} β€” ${t.status}`));
165
+ }
166
+ console.log();
167
+ return;
168
+ }
169
+
170
+ if (method === 'cron.list' || method === 'cron.status') {
171
+ const { getConfig } = require('../utils/config');
172
+ const config = getConfig();
173
+ const jobs = config.cronJobs || [];
174
+ console.log(chalk.cyan(`\n ⏰ ${method} (${jobs.length} jobs)\n`));
175
+ if (jobs.length === 0) {
176
+ console.log(chalk.gray(' Cron job yapılandırılmamış.\n'));
177
+ return;
178
+ }
179
+ for (const j of jobs) {
180
+ console.log(` ${chalk.white(j.name || '(unnamed)')} β€” ${chalk.gray(j.schedule || j.interval)}`);
181
+ }
182
+ console.log();
183
+ return;
184
+ }
185
+
186
+ if (method === 'tasks.list') {
187
+ const { listTasks, getTaskSummary } = require('../utils/background');
188
+ const tasks = listTasks({ limit: 20 });
189
+ const summary = getTaskSummary();
190
+ console.log(chalk.cyan(`\n πŸ“‹ Tasks (${summary.active} active, ${summary.total} total)\n`));
191
+ for (const t of tasks.slice(0, 15)) {
192
+ console.log(` ${chalk.white(t.id)} β€” ${chalk.cyan(t.status)} β€” ${chalk.gray(t.message?.substring(0, 50) || '')}`);
193
+ }
194
+ console.log();
195
+ return;
196
+ }
197
+
198
+ console.log(chalk.yellow(` ⚠️ Method "${method}" henüz implemente edilmedi\n`));
199
+ }
200
+
201
+ function startAdmin(portStr) {
202
+ if (serverInstance) {
203
+ console.log(chalk.yellow('\n ⚠️ Server zaten çalışıyor\n'));
204
+ return;
205
+ }
206
+
207
+ const port = parseInt(portStr, 10) || 3847;
208
+
209
+ const server = http.createServer((req, res) => {
210
+ if (req.method !== 'POST') {
211
+ res.writeHead(405, { 'Allow': 'POST', 'Content-Type': 'application/json' });
212
+ res.end(JSON.stringify({ ok: false, error: 'Method not allowed' }));
213
+ return;
214
+ }
215
+
216
+ let body = '';
217
+ req.on('data', chunk => { body += chunk; });
218
+ req.on('end', async () => {
219
+ try {
220
+ const rpc = JSON.parse(body);
221
+ if (!rpc.method || typeof rpc.method !== 'string') {
222
+ res.writeHead(400, { 'Content-Type': 'application/json' });
223
+ res.end(JSON.stringify({ ok: false, error: 'method required' }));
224
+ return;
225
+ }
226
+
227
+ if (!ALLOWED_METHODS.includes(rpc.method)) {
228
+ res.writeHead(400, { 'Content-Type': 'application/json' });
229
+ res.end(JSON.stringify({ ok: false, error: `Method not allowed: ${rpc.method}` }));
230
+ return;
231
+ }
232
+
233
+ const config = getConfig();
234
+ let payload;
235
+
236
+ if (rpc.method === 'health') {
237
+ payload = { status: 'ok', node: process.version, uptime: process.uptime() };
238
+ } else if (rpc.method === 'status') {
239
+ payload = { gateway: config.gatewayUrl, provider: config.provider, model: config.model };
240
+ } else if (rpc.method === 'config.get') {
241
+ const key = rpc.params?.key;
242
+ payload = key ? { [key]: key.split('.').reduce((o, k) => o?.[k], config) } : config;
243
+ } else if (rpc.method === 'plugins.list') {
244
+ const { loadTools } = require('../utils/tool-runner');
245
+ payload = { tools: Object.keys(loadTools()) };
246
+ } else if (rpc.method === 'config.set') {
247
+ const { setConfigValue } = require('../utils/config');
248
+ setConfigValue(rpc.params.key, rpc.params.value);
249
+ payload = { ok: true, key: rpc.params.key, value: rpc.params.value };
250
+ } else if (rpc.method === 'channels.status' || rpc.method === 'channels.start' || rpc.method === 'channels.stop') {
251
+ const channels = ['telegram', 'discord', 'slack', 'whatsapp'];
252
+ const status = {};
253
+ for (const ch of channels) status[ch] = !!config[`${ch}Token`];
254
+ payload = { action: rpc.method, channels: status };
255
+ } else if (rpc.method === 'agents.list' || rpc.method === 'tasks.list') {
256
+ const { listTasks, getTaskSummary } = require('../utils/background');
257
+ payload = { summary: getTaskSummary(), tasks: listTasks({ limit: 20 }) };
258
+ } else if (rpc.method === 'cron.list' || rpc.method === 'cron.status') {
259
+ payload = { jobs: config.cronJobs || [] };
260
+ } else {
261
+ payload = { message: `Method "${rpc.method}" called`, params: rpc.params };
262
+ }
263
+
264
+ res.writeHead(200, { 'Content-Type': 'application/json' });
265
+ res.end(JSON.stringify({ ok: true, id: rpc.id || 'rpc-1', payload }));
266
+ } catch (err) {
267
+ res.writeHead(400, { 'Content-Type': 'application/json' });
268
+ res.end(JSON.stringify({ ok: false, error: 'Invalid JSON' }));
269
+ }
270
+ });
271
+ });
272
+
273
+ serverInstance = server;
274
+ serverInstance.port = port;
275
+
276
+ server.listen(port, () => {
277
+ console.log(chalk.green(`\n βœ… Admin RPC server started on http://localhost:${port}\n`));
278
+ console.log(chalk.gray(' POST requests with JSON body:'));
279
+ console.log(chalk.white(' { "method": "health", "id": "req-1" }'));
280
+ console.log(chalk.white(' { "method": "config.get", "params": { "key": "provider" } }'));
281
+ console.log(chalk.gray('\n Press Ctrl+C to stop\n'));
282
+ });
283
+
284
+ server.on('error', (err) => {
285
+ console.log(chalk.red(`\n ❌ Server error: ${err.message}\n`));
286
+ serverInstance = null;
287
+ });
288
+ }
289
+
290
+ function stopAdmin() {
291
+ if (!serverInstance) {
292
+ console.log(chalk.yellow('\n ⚠️ Server çalışmıyor\n'));
293
+ return;
294
+ }
295
+
296
+ serverInstance.close(() => {
297
+ console.log(chalk.gray('\n πŸ›‘ Admin RPC server durduruldu\n'));
298
+ serverInstance = null;
299
+ });
300
+ }
301
+
302
+ module.exports = adminRpc;
@@ -0,0 +1,280 @@
1
+ const chalk = require('chalk');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const os = require('os');
5
+
6
+ const BINDINGS_FILE = path.join(os.homedir(), '.natureco', 'agent-bindings.json');
7
+ const IDENTITIES_FILE = path.join(os.homedir(), '.natureco', 'agent-identities.json');
8
+
9
+ async function agent(args) {
10
+ const opts = {};
11
+ for (let i = 0; i < args.length; i++) {
12
+ if (args[i] === '--to' || args[i] === '-t') opts.to = args[++i];
13
+ else if (args[i] === '--message' || args[i] === '-m') opts.message = args[++i];
14
+ else if (args[i] === '--channel' || args[i] === '-c') opts.channel = args[++i];
15
+ else if (args[i] === '--deliver') opts.deliver = true;
16
+ else if (args[i] === '--model') opts.model = args[++i];
17
+ else if (args[i] === '--provider') opts.provider = args[++i];
18
+ else if (!opts.action) opts.action = args[i];
19
+ else (opts._positional = opts._positional || []).push(args[i]);
20
+ }
21
+
22
+ if (!opts.action || opts.action === 'help') return showHelp();
23
+ if (opts.action === 'run') return runAgent(opts);
24
+ if (opts.action === 'abort') return abortAgent(opts.message);
25
+ if (opts.action === 'tail') return tailAgent(opts.message);
26
+ if (opts.action === 'logs') return logsAgent(opts.message);
27
+ if (opts.action === 'bindings') return listBindings();
28
+ if (opts.action === 'bind') return bindAgent(opts);
29
+ if (opts.action === 'unbind') return unbindAgent(opts);
30
+ if (opts.action === 'set-identity') return setIdentity(opts);
31
+
32
+ console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${opts.action}\n`));
33
+ process.exit(1);
34
+ }
35
+
36
+ async function runAgent(opts) {
37
+ const { getConfig } = require('../utils/config');
38
+ const { createTask } = require('../utils/background');
39
+ const { getProviderConfig } = require('../utils/api');
40
+ const config = getConfig();
41
+ const pc = getProviderConfig();
42
+
43
+ const provider = opts.provider || (pc?.url?.includes('groq') ? 'groq' : config.provider || 'openai');
44
+ const model = opts.model || config.providerModel || config.model || 'llama-3.3-70b-versatile';
45
+ const message = opts.message || 'Hello';
46
+ const apiKey = pc?.apiKey || config[`${provider}ApiKey`] || process.env[`${provider.toUpperCase()}_API_KEY`];
47
+
48
+ if (!apiKey) {
49
+ console.log(chalk.red(`\n ❌ ${provider} API key gerekli\n`));
50
+ process.exit(1);
51
+ }
52
+
53
+ const task = createTask({
54
+ runtime: 'cli',
55
+ message: message.substring(0, 80),
56
+ botName: opts.to || 'default',
57
+ });
58
+
59
+ console.log(chalk.cyan(`\n πŸ€– Agent Turn [${task.id}]\n`));
60
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
61
+ console.log(` ${chalk.white('Message:')} ${message}`);
62
+ if (opts.to) console.log(` ${chalk.white('To:')} ${opts.to}`);
63
+ if (opts.channel) console.log(` ${chalk.white('Channel:')} ${opts.channel}`);
64
+ console.log(` ${chalk.white('Provider:')} ${provider}`);
65
+ console.log(` ${chalk.white('Model:')} ${model}`);
66
+ console.log(chalk.gray('\n Running...\n'));
67
+
68
+ try {
69
+ const { updateTask } = require('../utils/background');
70
+ updateTask(task.id, { status: 'running' });
71
+
72
+ const apiUrl = pc?.url || `https://api.${provider}.com/v1`;
73
+ const response = await fetch(`${apiUrl}/chat/completions`, {
74
+ method: 'POST',
75
+ headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` },
76
+ body: JSON.stringify({ model, messages: [{ role: 'user', content: message }], max_tokens: 2048 })
77
+ });
78
+
79
+ if (!response.ok) {
80
+ updateTask(task.id, { status: 'failed', error: `API error ${response.status}` });
81
+ throw new Error(`API error ${response.status}`);
82
+ }
83
+
84
+ const data = await response.json();
85
+ const reply = data.choices?.[0]?.message?.content || 'No response';
86
+
87
+ updateTask(task.id, { status: 'succeeded', result: reply.substring(0, 500) });
88
+
89
+ console.log(chalk.white(' Response:'));
90
+ console.log(chalk.gray(` ${reply.substring(0, 500)}`));
91
+
92
+ if (opts.deliver && opts.channel) {
93
+ console.log(chalk.gray(`\n πŸ“¨ Delivering via ${opts.channel}...`));
94
+ }
95
+
96
+ console.log();
97
+ } catch (err) {
98
+ console.log(chalk.red(` ❌ ${err.message}\n`));
99
+ process.exit(1);
100
+ }
101
+ }
102
+
103
+ function abortAgent(taskId) {
104
+ const { cancelTask, listTasks } = require('../utils/background');
105
+ if (taskId) {
106
+ const t = cancelTask(taskId);
107
+ if (!t) { console.log(chalk.red(`\n ❌ Task bulunamadı: ${taskId}\n`)); process.exit(1); }
108
+ console.log(chalk.yellow(`\n πŸ›‘ Task iptal edildi: ${taskId}\n`));
109
+ return;
110
+ }
111
+ const running = listTasks({ status: 'running' });
112
+ if (running.length === 0) {
113
+ console.log(chalk.gray('\n Γ‡alışan task yok\n'));
114
+ return;
115
+ }
116
+ for (const t of running) {
117
+ cancelTask(t.id);
118
+ console.log(chalk.yellow(` πŸ›‘ Task iptal edildi: ${t.id} β€” ${t.message}`));
119
+ }
120
+ console.log();
121
+ }
122
+
123
+ function tailAgent(taskId) {
124
+ const { getTask } = require('../utils/background');
125
+ if (!taskId) {
126
+ console.log(chalk.red('\n ❌ Task ID gerekli. Kullanım: natureco agent tail <id>\n'));
127
+ process.exit(1);
128
+ }
129
+ const task = getTask(taskId);
130
+ if (!task) { console.log(chalk.red(`\n ❌ Task bulunamadı: ${taskId}\n`)); process.exit(1); }
131
+ console.log(chalk.cyan(`\n πŸ“‹ Task: ${task.id}\n`));
132
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
133
+ console.log(` ${chalk.white('Message:')} ${task.message}`);
134
+ console.log(` ${chalk.white('Status:')} ${statusColor(task.status)}`);
135
+ if (task.result) console.log(` ${chalk.white('Result:')} ${chalk.gray(task.result.substring(0, 300))}`);
136
+ if (task.error) console.log(` ${chalk.white('Error:')} ${chalk.red(task.error)}`);
137
+ if (task.createdAt) console.log(` ${chalk.white('Created:')} ${chalk.gray(task.createdAt)}`);
138
+ if (task.endedAt) console.log(` ${chalk.white('Ended:')} ${chalk.gray(task.endedAt)}`);
139
+ console.log();
140
+ }
141
+
142
+ function logsAgent(statusFilter) {
143
+ const { listTasks } = require('../utils/background');
144
+ const tasks = listTasks(statusFilter ? { status: statusFilter } : {});
145
+ console.log(chalk.cyan(`\n πŸ“œ Agent Logs${statusFilter ? ` (${statusFilter})` : ''}\n`));
146
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
147
+ if (tasks.length === 0) {
148
+ console.log(chalk.gray(' Task bulunamadΔ±.\n'));
149
+ return;
150
+ }
151
+ for (const t of tasks.slice(0, 20)) {
152
+ console.log(` ${statusColor(t.status)} ${chalk.white(t.message || '(boş)')}`);
153
+ console.log(chalk.gray(` [${t.id}] ${t.createdAt?.slice(0, 16) || ''} β€” ${t.runtime}`));
154
+ }
155
+ console.log();
156
+ }
157
+
158
+ // ── bindings ──────────────────────────────────────────────────────────
159
+ function listBindings() {
160
+ const bindings = loadBindings();
161
+ const ids = loadIdentities();
162
+ console.log(chalk.cyan('\n Agent Bindings\n'));
163
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
164
+ const entries = Object.entries(bindings);
165
+ if (entries.length === 0) {
166
+ console.log(chalk.gray(' No agents bound to any channels.\n'));
167
+ return;
168
+ }
169
+ for (const [agentId, channels] of entries) {
170
+ const identity = ids[agentId];
171
+ console.log(` ${chalk.white(agentId)}${identity ? chalk.gray(' (' + identity + ')') : ''}`);
172
+ for (const ch of channels) {
173
+ console.log(chalk.gray(' └─ ') + chalk.cyan(ch));
174
+ }
175
+ }
176
+ console.log('');
177
+ }
178
+
179
+ function loadBindings() {
180
+ if (!fs.existsSync(BINDINGS_FILE)) return {};
181
+ try { return JSON.parse(fs.readFileSync(BINDINGS_FILE, 'utf8')); } catch { return {}; }
182
+ }
183
+
184
+ function saveBindings(data) {
185
+ const dir = path.dirname(BINDINGS_FILE);
186
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
187
+ fs.writeFileSync(BINDINGS_FILE, JSON.stringify(data, null, 2), 'utf8');
188
+ }
189
+
190
+ function bindAgent(opts) {
191
+ const pos = opts._positional || [];
192
+ const agentId = pos[0];
193
+ const channel = pos[1] || opts.channel;
194
+ if (!agentId || !channel) {
195
+ console.log(chalk.red('\nUsage: natureco agents bind <agentId> <channel>\n'));
196
+ process.exit(1);
197
+ }
198
+ const bindings = loadBindings();
199
+ if (!bindings[agentId]) bindings[agentId] = [];
200
+ if (!bindings[agentId].includes(channel)) bindings[agentId].push(channel);
201
+ saveBindings(bindings);
202
+ console.log(chalk.green('\nAgent "' + agentId + '" bound to ' + channel + '\n'));
203
+ }
204
+
205
+ function unbindAgent(opts) {
206
+ const pos = opts._positional || [];
207
+ const agentId = pos[0];
208
+ const channel = pos[1] || opts.channel;
209
+ if (!agentId || !channel) {
210
+ console.log(chalk.red('\nUsage: natureco agents unbind <agentId> <channel>\n'));
211
+ process.exit(1);
212
+ }
213
+ const bindings = loadBindings();
214
+ if (bindings[agentId]) {
215
+ bindings[agentId] = bindings[agentId].filter(c => c !== channel);
216
+ if (bindings[agentId].length === 0) delete bindings[agentId];
217
+ }
218
+ saveBindings(bindings);
219
+ console.log(chalk.green('\nAgent "' + agentId + '" unbound from ' + channel + '\n'));
220
+ }
221
+
222
+ // ── identities ────────────────────────────────────────────────────────
223
+ function loadIdentities() {
224
+ if (!fs.existsSync(IDENTITIES_FILE)) return {};
225
+ try { return JSON.parse(fs.readFileSync(IDENTITIES_FILE, 'utf8')); } catch { return {}; }
226
+ }
227
+
228
+ function saveIdentities(data) {
229
+ const dir = path.dirname(IDENTITIES_FILE);
230
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
231
+ fs.writeFileSync(IDENTITIES_FILE, JSON.stringify(data, null, 2), 'utf8');
232
+ }
233
+
234
+ function setIdentity(opts) {
235
+ const pos = opts._positional || [];
236
+ const agentId = pos[0];
237
+ const identity = pos.slice(1).join(' ') || opts.message;
238
+ if (!agentId || !identity) {
239
+ console.log(chalk.red('\nUsage: natureco agents set-identity <agentId> <identity>\n'));
240
+ process.exit(1);
241
+ }
242
+ const ids = loadIdentities();
243
+ ids[agentId] = identity;
244
+ saveIdentities(ids);
245
+ console.log(chalk.green('\nIdentity set for agent "' + agentId + '": ' + identity + '\n'));
246
+ }
247
+
248
+ function statusColor(s) {
249
+ const m = { succeeded: chalk.green('βœ“'), failed: chalk.red('βœ—'), running: chalk.yellow('●'), queued: chalk.cyan('β—‹'), cancelled: chalk.gray('βˆ’'), timed_out: chalk.red('⚠'), lost: chalk.magenta('?') };
250
+ return m[s] || chalk.gray('β—‹');
251
+ }
252
+
253
+ function showHelp() {
254
+ console.log(chalk.cyan('\n πŸ€– Agent\n'));
255
+ console.log(chalk.gray(' Run, manage, and monitor agent tasks.\n'));
256
+ console.log(chalk.gray(' Usage: natureco agent <action> [options]'));
257
+ console.log(chalk.gray('\n Actions:'));
258
+ console.log(chalk.cyan(' run') + chalk.gray(' Run an agent turn'));
259
+ console.log(chalk.cyan(' abort [id]') + chalk.gray(' Cancel a running task'));
260
+ console.log(chalk.cyan(' tail <id>') + chalk.gray(' Show task details'));
261
+ console.log(chalk.cyan(' logs [status]') + chalk.gray(' List recent tasks'));
262
+ console.log(chalk.cyan(' bindings') + chalk.gray(' List agent bindings'));
263
+ console.log(chalk.cyan(' bind <id> <ch>') + chalk.gray(' Bind agent to channel'));
264
+ console.log(chalk.cyan(' unbind <id> <ch>') + chalk.gray(' Unbind agent from channel'));
265
+ console.log(chalk.cyan(' set-identity <id> <persona>') + chalk.gray(' Set agent identity'));
266
+ console.log(chalk.gray('\n Options for run:'));
267
+ console.log(chalk.cyan(' --message, -m <text>') + chalk.gray(' Message to send'));
268
+ console.log(chalk.cyan(' --to, -t <target>') + chalk.gray(' Target channel/contact'));
269
+ console.log(chalk.cyan(' --channel, -c <name>') + chalk.gray(' Channel to use'));
270
+ console.log(chalk.cyan(' --deliver') + chalk.gray(' Deliver reply via channel'));
271
+ console.log(chalk.cyan(' --model <model>') + chalk.gray(' Model override'));
272
+ console.log(chalk.cyan(' --provider <name>') + chalk.gray(' Provider override'));
273
+ console.log(chalk.gray('\n Examples:'));
274
+ console.log(chalk.gray(' natureco agent run --message "Merhaba"'));
275
+ console.log(chalk.gray(' natureco agent abort'));
276
+ console.log(chalk.gray(' natureco agent tail <id>'));
277
+ console.log(chalk.gray(' natureco agent logs running\n'));
278
+ }
279
+
280
+ module.exports = agent;