natureco-cli 5.20.3 → 5.21.0
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/CHANGELOG.md +779 -750
- package/README.md +608 -608
- package/bin/natureco.js +1099 -1095
- package/package.json +95 -94
- package/scripts/generate-qr.js +21 -0
- package/scripts/import-curated-skills-log.json +5 -0
- package/scripts/import-curated-skills.js +262 -0
- package/scripts/import-skills-log.json +167 -0
- package/scripts/import-skills.js +261 -0
- package/scripts/postinstall.js +125 -0
- package/src/commands/agent.js +280 -280
- package/src/commands/ask.js +4 -2
- package/src/commands/naturehub.js +206 -282
- package/src/commands/repl.js +1594 -1580
- package/src/providers/mem0-memory.js +121 -121
- package/src/providers/supermemory-memory.js +117 -117
- package/src/tools/llm_task.js +150 -150
- package/src/tools/mac_alarm.js +199 -199
- package/src/tools/workflow.js +424 -424
- package/src/utils/api.js +1211 -1188
- package/src/utils/cost-tracker.js +361 -360
- package/src/utils/inquirer-wrapper.js +43 -31
- package/src/utils/paste-safe-input.js +346 -334
- package/src/utils/process-errors.js +129 -115
- package/src/utils/provider-detect.js +76 -72
- package/src/utils/skills.js +1 -1
- package/src/utils/system-prompt.js +136 -136
- package/src/utils/tools.js +324 -324
- package/README.md.bak +0 -565
- package/src/tools/http.js +0 -78
package/src/commands/agent.js
CHANGED
|
@@ -1,280 +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;
|
|
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;
|
package/src/commands/ask.js
CHANGED
|
@@ -5,7 +5,7 @@ const { getSkillPrompts } = require('../utils/skills');
|
|
|
5
5
|
const { getMemoryPrompt } = require('../utils/memory');
|
|
6
6
|
const { getAgentsPrompt } = require('../utils/agents');
|
|
7
7
|
|
|
8
|
-
async function ask(question) {
|
|
8
|
+
async function ask(question, options = {}) {
|
|
9
9
|
const apiKey = getApiKey();
|
|
10
10
|
|
|
11
11
|
if (!apiKey) {
|
|
@@ -41,7 +41,9 @@ async function ask(question) {
|
|
|
41
41
|
}, 80);
|
|
42
42
|
|
|
43
43
|
try {
|
|
44
|
-
|
|
44
|
+
// Tek atımlık soru: 47 araç şeması göndermek ~15K token israfıydı.
|
|
45
|
+
// Varsayılan araçsız (~%90 tasarruf); --tools ile açılabilir.
|
|
46
|
+
const response = await sendMessage(apiKey, defaultBotId, question, null, systemPrompt, { stream: false, noTools: !options.tools });
|
|
45
47
|
|
|
46
48
|
clearInterval(loadingInterval);
|
|
47
49
|
process.stdout.write('\r');
|