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
|
@@ -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;
|
|
@@ -126,6 +126,75 @@ async function callMethod(method, jsonParams) {
|
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
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
|
+
|
|
129
198
|
console.log(chalk.yellow(` ⚠️ Method "${method}" henüz implemente edilmedi\n`));
|
|
130
199
|
}
|
|
131
200
|
|
|
@@ -174,6 +243,20 @@ function startAdmin(portStr) {
|
|
|
174
243
|
} else if (rpc.method === 'plugins.list') {
|
|
175
244
|
const { loadTools } = require('../utils/tool-runner');
|
|
176
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 || [] };
|
|
177
260
|
} else {
|
|
178
261
|
payload = { message: `Method "${rpc.method}" called`, params: rpc.params };
|
|
179
262
|
}
|
package/src/commands/agent.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
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');
|
|
2
8
|
|
|
3
9
|
async function agent(args) {
|
|
4
10
|
const opts = {};
|
|
@@ -10,10 +16,18 @@ async function agent(args) {
|
|
|
10
16
|
else if (args[i] === '--model') opts.model = args[++i];
|
|
11
17
|
else if (args[i] === '--provider') opts.provider = args[++i];
|
|
12
18
|
else if (!opts.action) opts.action = args[i];
|
|
19
|
+
else (opts._positional = opts._positional || []).push(args[i]);
|
|
13
20
|
}
|
|
14
21
|
|
|
15
22
|
if (!opts.action || opts.action === 'help') return showHelp();
|
|
16
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);
|
|
17
31
|
|
|
18
32
|
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${opts.action}\n`));
|
|
19
33
|
process.exit(1);
|
|
@@ -21,13 +35,28 @@ async function agent(args) {
|
|
|
21
35
|
|
|
22
36
|
async function runAgent(opts) {
|
|
23
37
|
const { getConfig } = require('../utils/config');
|
|
38
|
+
const { createTask } = require('../utils/background');
|
|
39
|
+
const { getProviderConfig } = require('../utils/api');
|
|
24
40
|
const config = getConfig();
|
|
41
|
+
const pc = getProviderConfig();
|
|
25
42
|
|
|
26
|
-
const provider = opts.provider || config.provider || 'openai';
|
|
27
|
-
const model = opts.model || config.model || '
|
|
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';
|
|
28
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
|
+
}
|
|
29
52
|
|
|
30
|
-
|
|
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`));
|
|
31
60
|
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
32
61
|
console.log(` ${chalk.white('Message:')} ${message}`);
|
|
33
62
|
if (opts.to) console.log(` ${chalk.white('To:')} ${opts.to}`);
|
|
@@ -37,24 +66,26 @@ async function runAgent(opts) {
|
|
|
37
66
|
console.log(chalk.gray('\n Running...\n'));
|
|
38
67
|
|
|
39
68
|
try {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
console.log(chalk.red(` ❌ ${provider} API key gerekli\n`));
|
|
43
|
-
process.exit(1);
|
|
44
|
-
}
|
|
69
|
+
const { updateTask } = require('../utils/background');
|
|
70
|
+
updateTask(task.id, { status: 'running' });
|
|
45
71
|
|
|
46
|
-
const
|
|
47
|
-
const response = await fetch(`${
|
|
72
|
+
const apiUrl = pc?.url || `https://api.${provider}.com/v1`;
|
|
73
|
+
const response = await fetch(`${apiUrl}/chat/completions`, {
|
|
48
74
|
method: 'POST',
|
|
49
75
|
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` },
|
|
50
76
|
body: JSON.stringify({ model, messages: [{ role: 'user', content: message }], max_tokens: 2048 })
|
|
51
77
|
});
|
|
52
78
|
|
|
53
|
-
if (!response.ok)
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
updateTask(task.id, { status: 'failed', error: `API error ${response.status}` });
|
|
81
|
+
throw new Error(`API error ${response.status}`);
|
|
82
|
+
}
|
|
54
83
|
|
|
55
84
|
const data = await response.json();
|
|
56
85
|
const reply = data.choices?.[0]?.message?.content || 'No response';
|
|
57
86
|
|
|
87
|
+
updateTask(task.id, { status: 'succeeded', result: reply.substring(0, 500) });
|
|
88
|
+
|
|
58
89
|
console.log(chalk.white(' Response:'));
|
|
59
90
|
console.log(chalk.gray(` ${reply.substring(0, 500)}`));
|
|
60
91
|
|
|
@@ -69,21 +100,181 @@ async function runAgent(opts) {
|
|
|
69
100
|
}
|
|
70
101
|
}
|
|
71
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
|
+
|
|
72
253
|
function showHelp() {
|
|
73
254
|
console.log(chalk.cyan('\n 🤖 Agent\n'));
|
|
74
|
-
console.log(chalk.gray(' Run
|
|
75
|
-
console.log(chalk.gray('
|
|
76
|
-
console.log(chalk.gray('\n
|
|
77
|
-
console.log(chalk.cyan(' run') + chalk.gray('
|
|
78
|
-
console.log(chalk.cyan('
|
|
79
|
-
console.log(chalk.cyan('
|
|
80
|
-
console.log(chalk.cyan('
|
|
81
|
-
console.log(chalk.cyan('
|
|
82
|
-
console.log(chalk.cyan('
|
|
83
|
-
console.log(chalk.cyan('
|
|
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'));
|
|
84
273
|
console.log(chalk.gray('\n Examples:'));
|
|
85
|
-
console.log(chalk.gray(' natureco agent run --message "
|
|
86
|
-
console.log(chalk.gray(' natureco agent
|
|
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'));
|
|
87
278
|
}
|
|
88
279
|
|
|
89
280
|
module.exports = agent;
|
package/src/commands/agents.js
CHANGED
|
@@ -1,8 +1,39 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const F = require('../utils/format');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
2
6
|
const inquirer = require('../utils/inquirer-wrapper');
|
|
3
7
|
const { getConfig, saveConfig } = require('../utils/config');
|
|
4
8
|
const { getBots } = require('../utils/api');
|
|
5
9
|
|
|
10
|
+
const BINDINGS_FILE = path.join(os.homedir(), '.natureco', 'agent-bindings.json');
|
|
11
|
+
const IDENTITIES_FILE = path.join(os.homedir(), '.natureco', 'agent-identities.json');
|
|
12
|
+
|
|
13
|
+
function loadBindings() {
|
|
14
|
+
try {
|
|
15
|
+
if (fs.existsSync(BINDINGS_FILE)) return JSON.parse(fs.readFileSync(BINDINGS_FILE, 'utf8'));
|
|
16
|
+
} catch {}
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function saveBindings(data) {
|
|
21
|
+
fs.mkdirSync(path.dirname(BINDINGS_FILE), { recursive: true });
|
|
22
|
+
fs.writeFileSync(BINDINGS_FILE, JSON.stringify(data, null, 2));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function loadIdentities() {
|
|
26
|
+
try {
|
|
27
|
+
if (fs.existsSync(IDENTITIES_FILE)) return JSON.parse(fs.readFileSync(IDENTITIES_FILE, 'utf8'));
|
|
28
|
+
} catch {}
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function saveIdentities(data) {
|
|
33
|
+
fs.mkdirSync(path.dirname(IDENTITIES_FILE), { recursive: true });
|
|
34
|
+
fs.writeFileSync(IDENTITIES_FILE, JSON.stringify(data, null, 2));
|
|
35
|
+
}
|
|
36
|
+
|
|
6
37
|
async function agents(args) {
|
|
7
38
|
const [action, ...params] = (args || []);
|
|
8
39
|
|
|
@@ -10,9 +41,13 @@ async function agents(args) {
|
|
|
10
41
|
if (action === 'set') return setActiveAgent(params[0]);
|
|
11
42
|
if (action === 'info') return agentInfo(params[0]);
|
|
12
43
|
if (action === 'add') return addAgent();
|
|
44
|
+
if (action === 'bindings') return listBindings();
|
|
45
|
+
if (action === 'bind') return bindAgent(params[0], params[1]);
|
|
46
|
+
if (action === 'unbind') return unbindAgent(params[0], params[1]);
|
|
47
|
+
if (action === 'set-identity') return setIdentity(params[0], params.slice(1).join(' '));
|
|
13
48
|
|
|
14
49
|
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
15
|
-
console.log(chalk.gray(' Kullanım: natureco agents [list|set|info|add]\n'));
|
|
50
|
+
console.log(chalk.gray(' Kullanım: natureco agents [list|set|info|add|bindings|bind|unbind|set-identity]\n'));
|
|
16
51
|
process.exit(1);
|
|
17
52
|
}
|
|
18
53
|
|
|
@@ -20,32 +55,28 @@ async function listAgents() {
|
|
|
20
55
|
const config = getConfig();
|
|
21
56
|
const apiKey = config.providerApiKey || config.apiKey || '';
|
|
22
57
|
|
|
23
|
-
|
|
58
|
+
F.info('Agentlar yükleniyor...');
|
|
24
59
|
|
|
25
60
|
let botList = { bots: [] };
|
|
26
61
|
try {
|
|
27
62
|
botList = await getBots(apiKey);
|
|
28
63
|
} catch {}
|
|
29
64
|
|
|
30
|
-
|
|
31
|
-
console.log(chalk.cyan.bold('\n Agentlar (Botlar)\n'));
|
|
65
|
+
F.header('Agents');
|
|
32
66
|
|
|
33
67
|
if (!botList.bots?.length) {
|
|
34
|
-
|
|
35
|
-
console.log(chalk.gray(' Oluşturmak için: ') + chalk.cyan('developers.natureco.me\n'));
|
|
68
|
+
F.list(['Agent bulunamadı.', 'Oluşturmak için: developers.natureco.me']);
|
|
36
69
|
return;
|
|
37
70
|
}
|
|
38
71
|
|
|
39
|
-
botList.bots.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
});
|
|
72
|
+
const rows = botList.bots.map(bot => [
|
|
73
|
+
bot.name + (config.botName === bot.name ? ' ← aktif' : ''),
|
|
74
|
+
bot.id,
|
|
75
|
+
bot.ai_provider || 'groq',
|
|
76
|
+
bot.model || '—'
|
|
77
|
+
]);
|
|
78
|
+
F.table(['Name', 'ID', 'Provider', 'Model'], rows);
|
|
47
79
|
|
|
48
|
-
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
49
80
|
console.log(chalk.gray(' Değiştirmek için: ') + chalk.cyan('natureco agents set <bot-adı>\n'));
|
|
50
81
|
}
|
|
51
82
|
|
|
@@ -91,7 +122,7 @@ async function agentInfo(botName) {
|
|
|
91
122
|
const name = botName || config.botName;
|
|
92
123
|
|
|
93
124
|
if (!name) {
|
|
94
|
-
|
|
125
|
+
F.error('Agent adı belirtin: natureco agents info <bot-adı>');
|
|
95
126
|
return;
|
|
96
127
|
}
|
|
97
128
|
|
|
@@ -102,33 +133,27 @@ async function agentInfo(botName) {
|
|
|
102
133
|
|
|
103
134
|
const bot = botList.bots?.find(b => b.name === name || b.id === name);
|
|
104
135
|
|
|
105
|
-
|
|
106
|
-
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
107
|
-
console.log(chalk.cyan.bold(`\n Agent: ${name}\n`));
|
|
136
|
+
F.header('Agent: ' + name);
|
|
108
137
|
|
|
109
138
|
if (bot) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (bot.model)
|
|
139
|
+
F.kv('ID', bot.id);
|
|
140
|
+
F.kv('Provider', bot.ai_provider || 'groq');
|
|
141
|
+
if (bot.model) F.kv('Model', bot.model);
|
|
113
142
|
if (bot.system_prompt) {
|
|
114
|
-
|
|
143
|
+
F.kv('Prompt', bot.system_prompt.slice(0, 80) + (bot.system_prompt.length > 80 ? '...' : ''));
|
|
115
144
|
}
|
|
116
145
|
} else {
|
|
117
|
-
|
|
146
|
+
F.meta('(Detay alınamadı)');
|
|
118
147
|
}
|
|
119
148
|
|
|
120
|
-
// Hafıza bilgisi
|
|
121
149
|
try {
|
|
122
150
|
const { loadMemory } = require('../utils/memory');
|
|
123
151
|
const mem = loadMemory(bot?.id || 'universal-provider');
|
|
124
152
|
if (mem.name || mem.facts?.length) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
console.log(chalk.gray(' Hafıza : ') + chalk.white(`${(mem.facts || []).length} bilgi`));
|
|
153
|
+
if (mem.name) F.kv('Kullanıcı', mem.name);
|
|
154
|
+
F.kv('Hafıza', (mem.facts || []).length + ' bilgi');
|
|
128
155
|
}
|
|
129
156
|
} catch {}
|
|
130
|
-
|
|
131
|
-
console.log('');
|
|
132
157
|
}
|
|
133
158
|
|
|
134
159
|
async function addAgent() {
|
|
@@ -138,4 +163,63 @@ async function addAgent() {
|
|
|
138
163
|
console.log(chalk.gray(' Oluşturduktan sonra: ') + chalk.cyan('natureco agents list\n'));
|
|
139
164
|
}
|
|
140
165
|
|
|
166
|
+
// ── Bindings ──────────────────────────────────────────────────────────────────
|
|
167
|
+
|
|
168
|
+
function listBindings() {
|
|
169
|
+
const bindings = loadBindings();
|
|
170
|
+
const keys = Object.keys(bindings);
|
|
171
|
+
|
|
172
|
+
F.section('Bindings (' + keys.length + ')');
|
|
173
|
+
|
|
174
|
+
if (keys.length === 0) {
|
|
175
|
+
F.meta('Henüz binding yok.');
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const items = [];
|
|
180
|
+
keys.forEach(agentId => {
|
|
181
|
+
bindings[agentId].forEach(ch => items.push(agentId + ' → ' + ch));
|
|
182
|
+
});
|
|
183
|
+
F.list(items);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function bindAgent(agentId, channel) {
|
|
187
|
+
if (!agentId || !channel) {
|
|
188
|
+
F.error('Kullanım: natureco agents bind <agentId> <channel>');
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const bindings = loadBindings();
|
|
192
|
+
if (!bindings[agentId]) bindings[agentId] = [];
|
|
193
|
+
if (!bindings[agentId].includes(channel)) bindings[agentId].push(channel);
|
|
194
|
+
saveBindings(bindings);
|
|
195
|
+
F.success('Agent ' + agentId + ' → ' + channel + ' bağlandı');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function unbindAgent(agentId, channel) {
|
|
199
|
+
if (!agentId || !channel) {
|
|
200
|
+
F.error('Kullanım: natureco agents unbind <agentId> <channel>');
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const bindings = loadBindings();
|
|
204
|
+
if (!bindings[agentId]) {
|
|
205
|
+
F.warning('Agent ' + agentId + ' için binding bulunamadı');
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
bindings[agentId] = bindings[agentId].filter(ch => ch !== channel);
|
|
209
|
+
if (bindings[agentId].length === 0) delete bindings[agentId];
|
|
210
|
+
saveBindings(bindings);
|
|
211
|
+
F.success('Agent ' + agentId + ' → ' + channel + ' bağlantısı kaldırıldı');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function setIdentity(agentId, identity) {
|
|
215
|
+
if (!agentId) {
|
|
216
|
+
F.error('Kullanım: natureco agents set-identity <agentId> <identity>');
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const identities = loadIdentities();
|
|
220
|
+
identities[agentId] = identity || 'default';
|
|
221
|
+
saveIdentities(identities);
|
|
222
|
+
F.success('Agent ' + agentId + ' identity: ' + (identity || 'default'));
|
|
223
|
+
}
|
|
224
|
+
|
|
141
225
|
module.exports = agents;
|