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.
- package/README.md +94 -11
- package/bin/natureco.js +495 -94
- package/package.json +1 -1
- package/src/commands/acp.js +39 -0
- package/src/commands/admin-rpc.js +302 -0
- package/src/commands/agent.js +280 -0
- package/src/commands/agents.js +114 -30
- package/src/commands/approvals.js +214 -0
- package/src/commands/backup.js +124 -0
- package/src/commands/bonjour.js +167 -0
- package/src/commands/browser.js +815 -0
- package/src/commands/capability.js +237 -0
- package/src/commands/channels.js +422 -267
- package/src/commands/chat.js +5 -8
- package/src/commands/clawbot.js +19 -0
- package/src/commands/clickclack.js +130 -0
- package/src/commands/code.js +3 -2
- package/src/commands/commitments.js +148 -0
- package/src/commands/completion.js +84 -0
- package/src/commands/config.js +219 -30
- package/src/commands/configure.js +110 -0
- package/src/commands/crestodian.js +92 -0
- package/src/commands/cron.js +239 -19
- package/src/commands/daemon.js +90 -0
- package/src/commands/dashboard.js +47 -374
- package/src/commands/device-pair.js +248 -0
- package/src/commands/devices.js +137 -0
- package/src/commands/directory.js +179 -0
- package/src/commands/dns.js +196 -0
- package/src/commands/docs.js +136 -0
- package/src/commands/doctor.js +143 -492
- package/src/commands/exec-policy.js +80 -0
- package/src/commands/gateway-server.js +1155 -24
- package/src/commands/gateway.js +492 -249
- package/src/commands/health.js +148 -0
- package/src/commands/help.js +24 -25
- package/src/commands/hooks.js +141 -87
- package/src/commands/imessage.js +128 -14
- package/src/commands/infer.js +1474 -0
- package/src/commands/irc.js +64 -15
- package/src/commands/logs.js +122 -99
- package/src/commands/mattermost.js +114 -12
- package/src/commands/mcp.js +121 -309
- package/src/commands/memory-cmd.js +134 -1
- package/src/commands/memory.js +128 -0
- package/src/commands/message.js +720 -134
- package/src/commands/migrate.js +213 -2
- package/src/commands/models.js +39 -1
- package/src/commands/node.js +98 -0
- package/src/commands/nodes.js +362 -0
- package/src/commands/oc-path.js +200 -0
- package/src/commands/onboard.js +129 -0
- package/src/commands/open-prose.js +67 -0
- package/src/commands/pairing.js +108 -107
- package/src/commands/path.js +206 -0
- package/src/commands/plugins.js +35 -1
- package/src/commands/policy.js +176 -0
- package/src/commands/proxy.js +306 -0
- package/src/commands/qr.js +70 -0
- package/src/commands/reset.js +101 -94
- package/src/commands/sandbox.js +125 -0
- package/src/commands/secrets.js +201 -0
- package/src/commands/sessions.js +110 -51
- package/src/commands/setup.js +102 -543
- package/src/commands/signal.js +447 -18
- package/src/commands/skills.js +67 -1
- package/src/commands/sms.js +123 -19
- package/src/commands/status.js +101 -127
- package/src/commands/system.js +53 -0
- package/src/commands/tasks.js +208 -100
- package/src/commands/terminal.js +139 -0
- package/src/commands/thread-ownership.js +157 -0
- package/src/commands/transcripts.js +95 -0
- package/src/commands/tui.js +41 -0
- package/src/commands/uninstall.js +73 -92
- package/src/commands/update.js +146 -91
- package/src/commands/voice.js +82 -0
- package/src/commands/vydra.js +98 -0
- package/src/commands/webhooks.js +58 -66
- package/src/commands/wiki.js +783 -0
- package/src/commands/workboard.js +207 -0
- package/src/tools/audio_understanding.js +154 -0
- package/src/tools/browser.js +112 -0
- package/src/tools/canvas.js +104 -0
- package/src/tools/document_extract.js +84 -0
- package/src/tools/duckduckgo.js +54 -0
- package/src/tools/exa_search.js +66 -0
- package/src/tools/firecrawl.js +104 -0
- package/src/tools/image_generation.js +99 -0
- package/src/tools/llm_task.js +118 -0
- package/src/tools/media_understanding.js +128 -0
- package/src/tools/music_generation.js +113 -0
- package/src/tools/parallel_search.js +77 -0
- package/src/tools/phone_control.js +80 -0
- package/src/tools/phone_control_enhanced.js +184 -0
- package/src/tools/searxng.js +61 -0
- package/src/tools/speech_to_text.js +135 -0
- package/src/tools/text_to_speech.js +105 -0
- package/src/tools/thread_ownership.js +88 -0
- package/src/tools/video_generation.js +72 -0
- package/src/tools/web_readability.js +104 -0
- package/src/utils/agents-md.js +85 -0
- package/src/utils/api.js +39 -40
- package/src/utils/format.js +144 -0
- package/src/utils/headless.js +2 -1
- package/src/utils/memory.js +200 -0
- 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/tasks.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const F = require('../utils/format');
|
|
2
3
|
const { listTasks, getTask, cancelTask, auditTasks, maintenanceTasks, getTaskSummary, TASK_STATUSES, RUNTIME_TYPES } = require('../utils/background');
|
|
4
|
+
const { spawnSubAgent, spawnParallel, getStatus } = require('../utils/sub-agent');
|
|
3
5
|
|
|
4
6
|
function parseFlags(args) {
|
|
5
7
|
return {
|
|
@@ -54,9 +56,17 @@ async function tasks(args) {
|
|
|
54
56
|
if (flowAction === 'cancel') return flowCancelHandler(flowParams[0]);
|
|
55
57
|
}
|
|
56
58
|
if (action === 'summary' || action === 'status') return summaryHandler(opts);
|
|
59
|
+
if (action === 'notify') {
|
|
60
|
+
const taskId = params[0];
|
|
61
|
+
const notifyMsg = params.slice(1).join(' ');
|
|
62
|
+
return notifyTaskHandler(taskId, notifyMsg);
|
|
63
|
+
}
|
|
64
|
+
if (action === 'delegate') return delegateHandler(params[0], params.slice(1).join(' '));
|
|
65
|
+
if (action === 'delegate-parallel') return delegateParallelHandler(params.join(' '));
|
|
66
|
+
if (action === 'sub-status') return subStatusHandler();
|
|
57
67
|
|
|
58
68
|
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
59
|
-
console.log(chalk.gray(' Kullanım: natureco tasks [list|show|cancel|audit|maintenance|flow|summary]\n'));
|
|
69
|
+
console.log(chalk.gray(' Kullanım: natureco tasks [list|show|cancel|audit|maintenance|flow|summary|notify|delegate|delegate-parallel|sub-status]\n'));
|
|
60
70
|
process.exit(1);
|
|
61
71
|
}
|
|
62
72
|
|
|
@@ -68,49 +78,40 @@ function listTasksHandler(opts) {
|
|
|
68
78
|
return;
|
|
69
79
|
}
|
|
70
80
|
|
|
71
|
-
|
|
72
|
-
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
73
|
-
console.log(chalk.cyan.bold('\n Background Tasks\n'));
|
|
81
|
+
F.header('Background Tasks');
|
|
74
82
|
|
|
75
83
|
if (tasks.length === 0) {
|
|
76
|
-
|
|
77
|
-
if (opts.runtime)
|
|
78
|
-
if (opts.status)
|
|
79
|
-
console.log('');
|
|
84
|
+
F.meta('Hiç task bulunamadı.');
|
|
85
|
+
if (opts.runtime) F.meta('Filtre: runtime=' + opts.runtime);
|
|
86
|
+
if (opts.status) F.meta('Filtre: status=' + opts.status);
|
|
80
87
|
return;
|
|
81
88
|
}
|
|
82
89
|
|
|
83
|
-
tasks.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
console.log(chalk.gray(` ${msg}`));
|
|
92
|
-
}
|
|
93
|
-
console.log(chalk.gray(` ${age} | notify: ${t.notifyPolicy || 'done_only'}`));
|
|
94
|
-
console.log('');
|
|
95
|
-
});
|
|
90
|
+
const rows = tasks.map(t => [
|
|
91
|
+
t.id.slice(0, 12),
|
|
92
|
+
(t.message || t.runtime || '').slice(0, 40),
|
|
93
|
+
t.status,
|
|
94
|
+
t.runtime || '—',
|
|
95
|
+
getAgeString(t.createdAt)
|
|
96
|
+
]);
|
|
97
|
+
F.table(['ID', 'Name', 'Status', 'Runtime', 'Time'], rows);
|
|
96
98
|
|
|
97
99
|
const summary = getTaskSummary();
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
console.log(chalk.gray(" JSON: ") + chalk.cyan('natureco tasks list --json\n'));
|
|
100
|
+
F.meta('Toplam: ' + tasks.length + ' (gösterilen) | Aktif: ' + summary.active + ' | Hata: ' + summary.failures);
|
|
101
|
+
F.meta('Filtre: --runtime <type> --status <status>');
|
|
102
|
+
F.meta('JSON: natureco tasks list --json');
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
function showTaskHandler(id, opts) {
|
|
105
106
|
if (!id) {
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
F.error('Task ID gerekli');
|
|
108
|
+
F.meta('Kullanım: natureco tasks show <id>');
|
|
108
109
|
process.exit(1);
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
const task = getTask(id);
|
|
112
113
|
if (!task) {
|
|
113
|
-
|
|
114
|
+
F.error('Task bulunamadı: ' + id);
|
|
114
115
|
process.exit(1);
|
|
115
116
|
}
|
|
116
117
|
|
|
@@ -119,58 +120,53 @@ function showTaskHandler(id, opts) {
|
|
|
119
120
|
return;
|
|
120
121
|
}
|
|
121
122
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (task.
|
|
132
|
-
|
|
133
|
-
if (task.startedAt) console.log(` ${chalk.gray('Başlangıç:')} ${chalk.white(formatTime(task.startedAt))}`);
|
|
134
|
-
if (task.endedAt) console.log(` ${chalk.gray('Bitiş :')} ${chalk.white(formatTime(task.endedAt))}`);
|
|
135
|
-
if (task.notifyPolicy) console.log(` ${chalk.gray('Bildirim :')} ${chalk.white(task.notifyPolicy)}`);
|
|
136
|
-
if (task.childSessionKey) console.log(` ${chalk.gray('Çocuk :')} ${chalk.gray(task.childSessionKey)}`);
|
|
137
|
-
if (task.runId) console.log(` ${chalk.gray('Run ID :')} ${chalk.gray(task.runId)}`);
|
|
123
|
+
F.header('Task: ' + task.id);
|
|
124
|
+
F.kv('Durum', task.status);
|
|
125
|
+
F.kv('Runtime', task.runtime);
|
|
126
|
+
F.kv('Bot', task.botName);
|
|
127
|
+
if (task.message) F.kv('Mesaj', task.message);
|
|
128
|
+
F.kv('Oluşturma', formatTime(task.createdAt));
|
|
129
|
+
if (task.startedAt) F.kv('Başlangıç', formatTime(task.startedAt));
|
|
130
|
+
if (task.endedAt) F.kv('Bitiş', formatTime(task.endedAt));
|
|
131
|
+
if (task.notifyPolicy) F.kv('Bildirim', task.notifyPolicy);
|
|
132
|
+
if (task.childSessionKey) F.kv('Çocuk', task.childSessionKey);
|
|
133
|
+
if (task.runId) F.kv('Run ID', task.runId);
|
|
138
134
|
|
|
139
135
|
if (task.result) {
|
|
140
|
-
console.log(
|
|
141
|
-
|
|
136
|
+
console.log('');
|
|
137
|
+
F.kv('Sonuç', task.result);
|
|
142
138
|
}
|
|
143
139
|
if (task.error) {
|
|
144
|
-
console.log(
|
|
145
|
-
|
|
140
|
+
console.log('');
|
|
141
|
+
F.kv('Hata', task.error);
|
|
146
142
|
}
|
|
147
143
|
if (task.cleanupAfter) {
|
|
148
|
-
|
|
144
|
+
F.meta('Temizlik: ' + formatTime(task.cleanupAfter));
|
|
149
145
|
}
|
|
150
146
|
if (task.metadata && Object.keys(task.metadata).length > 0) {
|
|
151
|
-
console.log(
|
|
152
|
-
|
|
147
|
+
console.log('');
|
|
148
|
+
F.meta('Metadata:');
|
|
149
|
+
Object.entries(task.metadata).forEach(([k, v]) => F.meta(k + ': ' + v));
|
|
153
150
|
}
|
|
154
|
-
console.log('');
|
|
155
151
|
}
|
|
156
152
|
|
|
157
153
|
function cancelTaskHandler(id) {
|
|
158
154
|
if (!id) {
|
|
159
|
-
|
|
160
|
-
|
|
155
|
+
F.error('Task ID gerekli');
|
|
156
|
+
F.meta('Kullanım: natureco tasks cancel <id>');
|
|
161
157
|
process.exit(1);
|
|
162
158
|
}
|
|
163
159
|
|
|
164
160
|
const result = cancelTask(id);
|
|
165
161
|
if (!result) {
|
|
166
|
-
|
|
162
|
+
F.error('Task bulunamadı: ' + id);
|
|
167
163
|
process.exit(1);
|
|
168
164
|
}
|
|
169
165
|
|
|
170
166
|
if (result.status === 'cancelled') {
|
|
171
|
-
|
|
167
|
+
F.success('Task iptal edildi: ' + id);
|
|
172
168
|
} else {
|
|
173
|
-
|
|
169
|
+
F.warning('Task zaten terminal durumda: ' + result.status);
|
|
174
170
|
}
|
|
175
171
|
}
|
|
176
172
|
|
|
@@ -182,12 +178,10 @@ function auditHandler(opts) {
|
|
|
182
178
|
return;
|
|
183
179
|
}
|
|
184
180
|
|
|
185
|
-
|
|
186
|
-
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
187
|
-
console.log(chalk.cyan.bold('\n Task Denetimi\n'));
|
|
181
|
+
F.header('Task Denetimi');
|
|
188
182
|
|
|
189
183
|
if (findings.length === 0) {
|
|
190
|
-
|
|
184
|
+
F.success('Sorun bulunamadı.');
|
|
191
185
|
return;
|
|
192
186
|
}
|
|
193
187
|
|
|
@@ -196,54 +190,47 @@ function auditHandler(opts) {
|
|
|
196
190
|
filtered = findings.filter(f => f.severity === opts.severity);
|
|
197
191
|
}
|
|
198
192
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (errors.length > 0) {
|
|
203
|
-
console.log(chalk.red(`\n ${errors.length} HATA\n`));
|
|
204
|
-
errors.forEach(f => {
|
|
205
|
-
console.log(` ${chalk.red('✗')} ${chalk.white(f.id.slice(0, 12))} ${chalk.red(f.code)}`);
|
|
206
|
-
console.log(chalk.gray(` ${f.message}`));
|
|
207
|
-
});
|
|
193
|
+
if (filtered.length === 0) {
|
|
194
|
+
F.meta('Filtreye uygun bulgu yok (severity=' + opts.severity + ')');
|
|
195
|
+
return;
|
|
208
196
|
}
|
|
209
197
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
198
|
+
const rows = filtered.map(f => [
|
|
199
|
+
f.id.slice(0, 12),
|
|
200
|
+
f.code,
|
|
201
|
+
f.severity,
|
|
202
|
+
f.message.slice(0, 60)
|
|
203
|
+
]);
|
|
204
|
+
F.table(['ID', 'Code', 'Severity', 'Message'], rows);
|
|
217
205
|
|
|
218
|
-
|
|
219
|
-
|
|
206
|
+
F.meta('Toplam: ' + filtered.length + ' bulgu');
|
|
207
|
+
F.meta('Bakım: natureco tasks maintenance --apply');
|
|
220
208
|
}
|
|
221
209
|
|
|
222
210
|
function maintenanceHandler(opts) {
|
|
223
|
-
|
|
211
|
+
F.header('Task Bakımı');
|
|
224
212
|
|
|
225
213
|
const dryRun = !opts.apply;
|
|
226
214
|
const result = maintenanceTasks(dryRun);
|
|
227
215
|
|
|
228
216
|
if (dryRun) {
|
|
229
|
-
|
|
217
|
+
F.info('Kuru çalışma (--apply ile uygula)');
|
|
230
218
|
}
|
|
231
219
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
220
|
+
F.kv('Temizlenen', result.pruned);
|
|
221
|
+
F.kv('Düzeltilen', result.reconciled);
|
|
222
|
+
F.kv('Etiketlenen', result.cleaned);
|
|
223
|
+
F.kv('Kalan task', result.remaining);
|
|
236
224
|
|
|
237
225
|
if (result.pruned > 0 || result.reconciled > 0 || result.cleaned > 0) {
|
|
238
226
|
if (dryRun) {
|
|
239
|
-
|
|
227
|
+
F.meta('Uygulamak için: natureco tasks maintenance --apply');
|
|
240
228
|
} else {
|
|
241
|
-
|
|
229
|
+
F.success('Bakım uygulandı.');
|
|
242
230
|
}
|
|
243
231
|
} else {
|
|
244
|
-
|
|
232
|
+
F.success('Bakım gerekmiyor.');
|
|
245
233
|
}
|
|
246
|
-
console.log('');
|
|
247
234
|
}
|
|
248
235
|
|
|
249
236
|
function flowListHandler(opts) {
|
|
@@ -254,22 +241,21 @@ function flowListHandler(opts) {
|
|
|
254
241
|
return;
|
|
255
242
|
}
|
|
256
243
|
|
|
257
|
-
|
|
258
|
-
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
259
|
-
console.log(chalk.cyan.bold('\n Task Flow\n'));
|
|
244
|
+
F.header('Task Flow');
|
|
260
245
|
|
|
261
246
|
if (tasks.length === 0) {
|
|
262
|
-
|
|
247
|
+
F.meta('Task Flow kaydı yok.');
|
|
263
248
|
return;
|
|
264
249
|
}
|
|
265
250
|
|
|
266
|
-
tasks.
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
251
|
+
const rows = tasks.map(t => [
|
|
252
|
+
t.id.slice(0, 12),
|
|
253
|
+
t.status,
|
|
254
|
+
t.message ? t.message.slice(0, 60) : '—'
|
|
255
|
+
]);
|
|
256
|
+
F.table(['ID', 'Status', 'Message'], rows);
|
|
257
|
+
|
|
258
|
+
F.meta('Toplam: ' + tasks.length + ' flow');
|
|
273
259
|
}
|
|
274
260
|
|
|
275
261
|
function flowShowHandler(id, opts) {
|
|
@@ -325,4 +311,126 @@ function formatTime(dateStr) {
|
|
|
325
311
|
return new Date(dateStr).toLocaleString('tr-TR');
|
|
326
312
|
}
|
|
327
313
|
|
|
314
|
+
function notifyTaskHandler(id, message) {
|
|
315
|
+
if (!id) {
|
|
316
|
+
F.error('Task ID gerekli');
|
|
317
|
+
F.meta('Kullanım: natureco tasks notify <id> [message]');
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
const task = getTask(id);
|
|
321
|
+
if (!task) {
|
|
322
|
+
F.error('Task bulunamadı: ' + id);
|
|
323
|
+
process.exit(1);
|
|
324
|
+
}
|
|
325
|
+
F.header('Task Notification');
|
|
326
|
+
F.kv('Task', id);
|
|
327
|
+
F.kv('Message', message || '(default notification)');
|
|
328
|
+
F.kv('Channel', task.notifyPolicy || 'done_only');
|
|
329
|
+
F.success('Notification will be sent when task completes');
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async function delegateHandler(type, task) {
|
|
333
|
+
if (!type || !task) {
|
|
334
|
+
F.error('Kullanım: natureco tasks delegate <type> <task>');
|
|
335
|
+
F.meta('Tipler: explore, general, review');
|
|
336
|
+
process.exit(1);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
F.header('Sub-agent Delegate');
|
|
340
|
+
F.kv('Type', type);
|
|
341
|
+
F.kv('Task', task.slice(0, 80));
|
|
342
|
+
|
|
343
|
+
try {
|
|
344
|
+
const result = await spawnSubAgent(type, task);
|
|
345
|
+
F.success('Sub-agent tamamlandı');
|
|
346
|
+
F.divider();
|
|
347
|
+
console.log(chalk.white(result.result));
|
|
348
|
+
if (result.duration) {
|
|
349
|
+
F.meta(`Süre: ${(result.duration / 1000).toFixed(1)}s`);
|
|
350
|
+
}
|
|
351
|
+
if (result.usage) {
|
|
352
|
+
F.meta(`Token: ${result.usage.prompt_tokens || result.usage.input_tokens || '?'} → ${result.usage.completion_tokens || result.usage.output_tokens || '?'}`);
|
|
353
|
+
}
|
|
354
|
+
} catch (err) {
|
|
355
|
+
F.error('Sub-agent hatası: ' + err.message);
|
|
356
|
+
process.exit(1);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
async function delegateParallelHandler(input) {
|
|
361
|
+
if (!input) {
|
|
362
|
+
F.error('Kullanım: natureco tasks delegate-parallel <type1> <task1> | <type2> <task2>');
|
|
363
|
+
F.meta('Birden çok agent\'ı " | " (pipe) ile ayırın');
|
|
364
|
+
process.exit(1);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const parts = input.split(/\s+\|\s+/);
|
|
368
|
+
if (parts.length < 2) {
|
|
369
|
+
F.error('En az 2 agent belirtin, " | " ile ayırın');
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const agents = parts.map(p => {
|
|
374
|
+
const trimmed = p.trim();
|
|
375
|
+
const spaceIdx = trimmed.indexOf(' ');
|
|
376
|
+
if (spaceIdx === -1) throw new Error(`Geçersiz agent: "${trimmed}" (type + task gerekli)`);
|
|
377
|
+
return {
|
|
378
|
+
type: trimmed.slice(0, spaceIdx),
|
|
379
|
+
task: trimmed.slice(spaceIdx + 1).trim(),
|
|
380
|
+
};
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
F.header('Parallel Sub-agents (' + agents.length + ')');
|
|
384
|
+
agents.forEach(a => F.kv(a.type, a.task.slice(0, 60)));
|
|
385
|
+
|
|
386
|
+
F.info('Çalıştırılıyor...');
|
|
387
|
+
|
|
388
|
+
const { results, failed } = await spawnParallel(agents);
|
|
389
|
+
|
|
390
|
+
F.divider();
|
|
391
|
+
|
|
392
|
+
results.forEach((r, i) => {
|
|
393
|
+
const agent = agents[i];
|
|
394
|
+
if (r.status === 'fulfilled') {
|
|
395
|
+
F.success(`${agent.type} — tamamlandı (${(r.value.duration / 1000).toFixed(1)}s)`);
|
|
396
|
+
} else {
|
|
397
|
+
F.error(`${agent.type} — hata: ${r.reason}`);
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
if (failed.length > 0) {
|
|
402
|
+
F.warning(`${failed.length}/${agents.length} agent başarısız`);
|
|
403
|
+
} else {
|
|
404
|
+
F.success('Tüm agent' + (agents.length > 1 ? 'lar' : '') + ' tamamlandı');
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function subStatusHandler() {
|
|
409
|
+
const status = getStatus();
|
|
410
|
+
|
|
411
|
+
if (status.total === 0) {
|
|
412
|
+
F.header('Sub-agent Status');
|
|
413
|
+
F.meta('Henüz sub-agent kaydı yok.');
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
F.header('Sub-agent Status');
|
|
418
|
+
F.kv('Toplam', status.total);
|
|
419
|
+
F.kv('Çalışan', String(status.running));
|
|
420
|
+
F.kv('Tamamlanan', String(status.completed));
|
|
421
|
+
F.kv('Hatalı', String(status.failed));
|
|
422
|
+
|
|
423
|
+
if (status.agents.length > 0) {
|
|
424
|
+
console.log('');
|
|
425
|
+
const rows = status.agents.map(a => [
|
|
426
|
+
a.id.slice(0, 10),
|
|
427
|
+
a.type,
|
|
428
|
+
a.status === 'completed' ? chalk.green('✓') : a.status === 'failed' ? chalk.red('✗') : chalk.cyan('⟳'),
|
|
429
|
+
a.task.slice(0, 40),
|
|
430
|
+
a.completedAt ? new Date(a.completedAt).toLocaleString('tr-TR') : '—',
|
|
431
|
+
]);
|
|
432
|
+
F.table(['ID', 'Type', '', 'Task', 'Completed'], rows);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
328
436
|
module.exports = tasks;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const { execSync, spawn } = require('child_process');
|
|
6
|
+
|
|
7
|
+
const SESSIONS_FILE = path.join(os.homedir(), '.natureco', 'terminal-sessions.json');
|
|
8
|
+
|
|
9
|
+
function loadSessions() {
|
|
10
|
+
if (!fs.existsSync(SESSIONS_FILE)) return [];
|
|
11
|
+
try { return JSON.parse(fs.readFileSync(SESSIONS_FILE, 'utf-8')); }
|
|
12
|
+
catch { return []; }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function saveSessions(sessions) {
|
|
16
|
+
const dir = path.dirname(SESSIONS_FILE);
|
|
17
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
18
|
+
fs.writeFileSync(SESSIONS_FILE, JSON.stringify(sessions, null, 2), 'utf-8');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function genId() { return Date.now().toString(36) + Math.random().toString(36).slice(2, 6); }
|
|
22
|
+
|
|
23
|
+
function terminal(args) {
|
|
24
|
+
const [action, ...params] = args || [];
|
|
25
|
+
|
|
26
|
+
if (!action || action === 'help') return showHelp();
|
|
27
|
+
if (action === 'exec') return execCmd(params.join(' '));
|
|
28
|
+
if (action === 'connect') return connectSession(params[0], params.slice(1).join(' '));
|
|
29
|
+
if (action === 'disconnect') return disconnectSession(params[0]);
|
|
30
|
+
if (action === 'list') return listSessions();
|
|
31
|
+
|
|
32
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
33
|
+
console.log(chalk.gray(' Kullanım: natureco terminal [exec|connect|disconnect|list]\n'));
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function execCmd(cmd) {
|
|
38
|
+
if (!cmd) {
|
|
39
|
+
console.log(chalk.red('\n ❌ Komut gerekli\n'));
|
|
40
|
+
console.log(chalk.gray(' Örnek: natureco terminal exec "ls -la"\n'));
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
console.log(chalk.cyan(`\n 🖥️ $ ${cmd}\n`));
|
|
44
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
45
|
+
try {
|
|
46
|
+
const output = execSync(cmd, { encoding: 'utf8', timeout: 30000, maxBuffer: 1024 * 1024 });
|
|
47
|
+
if (output) console.log(output);
|
|
48
|
+
console.log(chalk.green(`\n ✅ Komut başarıyla tamamlandı (${output.length} bytes)\n`));
|
|
49
|
+
} catch (err) {
|
|
50
|
+
if (err.stdout) console.log(err.stdout.toString());
|
|
51
|
+
if (err.stderr) console.log(chalk.red(err.stderr.toString()));
|
|
52
|
+
console.log(chalk.red(`\n ❌ Hata: ${err.message}\n`));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function connectSession(target, cmd) {
|
|
57
|
+
if (!target) {
|
|
58
|
+
console.log(chalk.red('\n ❌ Hedef gerekli (örn: local, ssh://user@host)\n'));
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const sessions = loadSessions();
|
|
63
|
+
const existing = sessions.find(s => s.target === target && s.status === 'active');
|
|
64
|
+
if (existing) {
|
|
65
|
+
console.log(chalk.yellow(`\n ⚠️ ${target} üzerinde zaten aktif oturum var: ${existing.id}\n`));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const session = { id: genId(), target, status: 'active', cmd: cmd || 'powershell', createdAt: new Date().toISOString() };
|
|
70
|
+
sessions.push(session);
|
|
71
|
+
saveSessions(sessions);
|
|
72
|
+
|
|
73
|
+
console.log(chalk.green(`\n ✅ Oturum başlatıldı: ${session.id}\n`));
|
|
74
|
+
console.log(` ${chalk.white('Target:')} ${target}`);
|
|
75
|
+
console.log(` ${chalk.white('Shell:')} ${session.cmd}`);
|
|
76
|
+
console.log();
|
|
77
|
+
|
|
78
|
+
if (target === 'local' || target.startsWith('local')) {
|
|
79
|
+
const shell = session.cmd;
|
|
80
|
+
console.log(chalk.gray(` ${shell} başlatılıyor... (Ctrl+D çıkış)\n`));
|
|
81
|
+
try {
|
|
82
|
+
const child = spawn(shell, [], { stdio: 'inherit', shell: true });
|
|
83
|
+
child.on('exit', () => {
|
|
84
|
+
session.status = 'closed';
|
|
85
|
+
session.endedAt = new Date().toISOString();
|
|
86
|
+
saveSessions(sessions);
|
|
87
|
+
console.log(chalk.gray(`\n Oturum sonlandı: ${session.id}\n`));
|
|
88
|
+
});
|
|
89
|
+
} catch (err) {
|
|
90
|
+
console.log(chalk.red(`\n ❌ ${err.message}\n`));
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log(chalk.gray(` Uzak oturum: ssh veya winrm ile ${target} bağlanın\n`));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function disconnectSession(id) {
|
|
99
|
+
const sessions = loadSessions();
|
|
100
|
+
const idx = sessions.findIndex(s => s.id === id);
|
|
101
|
+
if (idx === -1) { console.log(chalk.red(`\n ❌ Oturum bulunamadı: ${id}\n`)); process.exit(1); }
|
|
102
|
+
sessions[idx].status = 'closed';
|
|
103
|
+
sessions[idx].endedAt = new Date().toISOString();
|
|
104
|
+
saveSessions(sessions);
|
|
105
|
+
console.log(chalk.gray(`\n 🛑 Oturum sonlandı: ${id} — ${sessions[idx].target}\n`));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function listSessions() {
|
|
109
|
+
const sessions = loadSessions();
|
|
110
|
+
console.log(chalk.cyan('\n 📋 Terminal Sessions\n'));
|
|
111
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
112
|
+
if (sessions.length === 0) {
|
|
113
|
+
console.log(chalk.gray(' Oturum bulunamadı.\n'));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
for (const s of sessions.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))) {
|
|
117
|
+
const icon = s.status === 'active' ? chalk.green('●') : chalk.gray('○');
|
|
118
|
+
console.log(` ${icon} ${chalk.white(s.target)} — ${s.cmd}`);
|
|
119
|
+
console.log(chalk.gray(` [${s.id}] ${s.createdAt.slice(0, 16)}`));
|
|
120
|
+
}
|
|
121
|
+
console.log();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function showHelp() {
|
|
125
|
+
console.log(chalk.cyan('\n 🖥️ Terminal\n'));
|
|
126
|
+
console.log(chalk.gray(' Execute commands and manage terminal sessions.\n'));
|
|
127
|
+
console.log(chalk.gray(' Usage: natureco terminal <action> [params]'));
|
|
128
|
+
console.log(chalk.gray('\n Actions:'));
|
|
129
|
+
console.log(chalk.cyan(' exec <cmd>') + chalk.gray(' Run a shell command'));
|
|
130
|
+
console.log(chalk.cyan(' connect <target> [shell]') + chalk.gray(' Start a session'));
|
|
131
|
+
console.log(chalk.cyan(' disconnect <id>') + chalk.gray(' Close a session'));
|
|
132
|
+
console.log(chalk.cyan(' list') + chalk.gray(' List sessions'));
|
|
133
|
+
console.log(chalk.gray('\n Examples:'));
|
|
134
|
+
console.log(chalk.gray(' natureco terminal exec "dir"'));
|
|
135
|
+
console.log(chalk.gray(' natureco terminal connect local'));
|
|
136
|
+
console.log(chalk.gray(' natureco terminal list\n'));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = terminal;
|