natureco-cli 2.23.28 → 2.23.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -11
- package/bin/natureco.js +470 -10
- package/package.json +10 -6
- package/src/commands/admin-rpc.js +219 -0
- package/src/commands/agent.js +89 -0
- package/src/commands/approvals.js +53 -0
- package/src/commands/backup.js +124 -0
- package/src/commands/bonjour.js +167 -0
- package/src/commands/capability.js +64 -0
- package/src/commands/channels.js +94 -4
- package/src/commands/chat.js +11 -25
- package/src/commands/clickclack.js +130 -0
- package/src/commands/commitments.js +32 -0
- package/src/commands/completion.js +76 -0
- package/src/commands/config.js +111 -68
- package/src/commands/configure.js +93 -0
- package/src/commands/crestodian.js +92 -0
- package/src/commands/daemon.js +60 -0
- package/src/commands/device-pair.js +248 -0
- package/src/commands/devices.js +110 -0
- package/src/commands/directory.js +47 -0
- package/src/commands/dns.js +58 -0
- package/src/commands/docs.js +43 -0
- package/src/commands/doctor.js +121 -16
- package/src/commands/exec-policy.js +71 -0
- package/src/commands/gateway-server.js +1175 -30
- package/src/commands/gateway.js +11 -20
- package/src/commands/health.js +18 -0
- package/src/commands/help.js +6 -0
- package/src/commands/imessage.js +169 -0
- package/src/commands/infer.js +73 -0
- package/src/commands/irc.js +119 -0
- package/src/commands/mattermost.js +164 -0
- package/src/commands/memory-cmd.js +134 -1
- package/src/commands/message.js +30 -4
- package/src/commands/migrate.js +213 -2
- package/src/commands/models.js +584 -216
- package/src/commands/node.js +98 -0
- package/src/commands/nodes.js +106 -0
- package/src/commands/oc-path.js +200 -0
- package/src/commands/onboard.js +70 -0
- package/src/commands/open-prose.js +67 -0
- package/src/commands/plugins.js +415 -172
- package/src/commands/policy.js +176 -0
- package/src/commands/proxy.js +155 -0
- package/src/commands/qr.js +28 -0
- package/src/commands/sandbox.js +125 -0
- package/src/commands/secrets.js +118 -0
- package/src/commands/security.js +149 -1
- package/src/commands/setup.js +114 -10
- package/src/commands/signal.js +495 -0
- package/src/commands/skills.js +20 -29
- package/src/commands/sms.js +168 -0
- package/src/commands/system.js +53 -0
- package/src/commands/tasks.js +328 -79
- package/src/commands/terminal.js +21 -0
- package/src/commands/thread-ownership.js +157 -0
- package/src/commands/transcripts.js +72 -0
- package/src/commands/voice.js +82 -0
- package/src/commands/vydra.js +98 -0
- package/src/commands/webhooks.js +79 -0
- package/src/commands/whatsapp.js +7 -21
- package/src/commands/workboard.js +207 -0
- package/src/tools/audio_understanding.js +154 -0
- package/src/tools/bash.js +63 -29
- 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/api.js +3 -20
- package/src/utils/approvals.js +297 -0
- package/src/utils/background.js +223 -66
- package/src/utils/baileys.js +21 -0
- package/src/utils/config.js +141 -10
- package/src/utils/errors.js +148 -0
- package/src/utils/inquirer-wrapper.js +1 -2
- package/src/utils/memory.js +200 -0
- package/src/utils/path-utils.js +13 -13
- package/src/utils/plugin-registry.js +238 -0
- package/src/utils/secrets.js +177 -0
- package/src/utils/skills.js +10 -23
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const { getConfig } = require('../utils/config');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
name: 'text_to_speech',
|
|
5
|
+
description: 'Convert text to speech using ElevenLabs, OpenAI TTS, or local CLI TTS',
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
text: { type: 'string', description: 'Text to convert to speech' },
|
|
10
|
+
provider: { type: 'string', description: 'TTS provider: elevenlabs, openai, local (default: elevenlabs)', enum: ['elevenlabs', 'openai', 'local'] },
|
|
11
|
+
voice: { type: 'string', description: 'Voice ID or name (ElevenLabs: Rachel, Adam, etc; OpenAI: alloy, echo, fable, nova, shimmer)' },
|
|
12
|
+
outputPath: { type: 'string', description: 'Save audio to file path (optional)' }
|
|
13
|
+
},
|
|
14
|
+
required: ['text']
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
async execute(params) {
|
|
18
|
+
try {
|
|
19
|
+
const config = getConfig();
|
|
20
|
+
const provider = params.provider || config.ttsProvider || 'elevenlabs';
|
|
21
|
+
const outputPath = params.outputPath;
|
|
22
|
+
|
|
23
|
+
if (provider === 'elevenlabs') {
|
|
24
|
+
const apiKey = params.apiKey || config.elevenlabsApiKey || process.env.ELEVENLABS_API_KEY;
|
|
25
|
+
if (!apiKey) {
|
|
26
|
+
return { success: false, error: 'ElevenLabs API key gerekli.\nKur: natureco config set elevenlabsApiKey <key>' };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const voice = params.voice || config.elevenlabsVoice || '21m00Tcm4TlvDq8ikWAM';
|
|
30
|
+
const response = await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${voice}`, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
headers: { 'Content-Type': 'application/json', 'xi-api-key': apiKey },
|
|
33
|
+
body: JSON.stringify({
|
|
34
|
+
text: params.text,
|
|
35
|
+
model_id: 'eleven_monolingual_v1',
|
|
36
|
+
voice_settings: { stability: 0.5, similarity_boost: 0.5 }
|
|
37
|
+
})
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (!response.ok) throw new Error(`ElevenLabs error ${response.status}`);
|
|
41
|
+
|
|
42
|
+
const audioBuffer = await response.arrayBuffer();
|
|
43
|
+
if (outputPath) {
|
|
44
|
+
require('fs').writeFileSync(outputPath, Buffer.from(audioBuffer));
|
|
45
|
+
return { success: true, provider: 'elevenlabs', outputPath, size: audioBuffer.byteLength };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
success: true,
|
|
50
|
+
provider: 'elevenlabs',
|
|
51
|
+
audioData: Buffer.from(audioBuffer).toString('base64'),
|
|
52
|
+
format: 'mp3',
|
|
53
|
+
message: 'Audio generated. Use outputPath to save to file.'
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (provider === 'openai') {
|
|
58
|
+
const apiKey = params.apiKey || config.openaiApiKey || process.env.OPENAI_API_KEY;
|
|
59
|
+
if (!apiKey) {
|
|
60
|
+
return { success: false, error: 'OpenAI API key gerekli.' };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const voice = params.voice || 'alloy';
|
|
64
|
+
const response = await fetch('https://api.openai.com/v1/audio/speech', {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` },
|
|
67
|
+
body: JSON.stringify({ model: 'tts-1', input: params.text, voice })
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (!response.ok) throw new Error(`OpenAI TTS error ${response.status}`);
|
|
71
|
+
|
|
72
|
+
const audioBuffer = await response.arrayBuffer();
|
|
73
|
+
if (outputPath) {
|
|
74
|
+
require('fs').writeFileSync(outputPath, Buffer.from(audioBuffer));
|
|
75
|
+
return { success: true, provider: 'openai', outputPath, size: audioBuffer.byteLength };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
success: true, provider: 'openai',
|
|
80
|
+
audioData: Buffer.from(audioBuffer).toString('base64'), format: 'mp3'
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (provider === 'local') {
|
|
85
|
+
const { execSync } = require('child_process');
|
|
86
|
+
try {
|
|
87
|
+
execSync('which say || which espeak || which festival', { stdio: 'ignore' });
|
|
88
|
+
} catch {
|
|
89
|
+
return { success: false, error: 'Local TTS aracı bulunamadı. macOS: "say", Linux: "espeak"' };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const cmd = process.platform === 'darwin'
|
|
93
|
+
? `say "${params.text.replace(/"/g, '\\"')}"${outputPath ? ` -o "${outputPath}"` : ''}`
|
|
94
|
+
: `espeak "${params.text.replace(/"/g, '\\"')}"${outputPath ? ` -w "${outputPath}"` : ''}`;
|
|
95
|
+
|
|
96
|
+
execSync(cmd, { timeout: 30000 });
|
|
97
|
+
return { success: true, provider: 'local', outputPath: outputPath || 'played via speakers', message: 'Text spoken via local TTS' };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return { success: false, error: `Unknown provider: ${provider}` };
|
|
101
|
+
} catch (error) {
|
|
102
|
+
return { success: false, error: error.message };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
name: 'thread_ownership',
|
|
5
|
+
description: 'Manage message thread ownership — assign threads to specific agents/bots',
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
action: { type: 'string', description: 'Action: assign, release, status, list', enum: ['assign', 'release', 'status', 'list'] },
|
|
10
|
+
threadId: { type: 'string', description: 'Thread/channel/conversation ID' },
|
|
11
|
+
agentName: { type: 'string', description: 'Agent name to assign (for assign action)' },
|
|
12
|
+
channel: { type: 'string', description: 'Channel type: telegram, whatsapp, signal, irc, mattermost, discord, slack' }
|
|
13
|
+
},
|
|
14
|
+
required: ['action']
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
async execute(params) {
|
|
18
|
+
try {
|
|
19
|
+
const config = getConfig();
|
|
20
|
+
const ownership = config.threadOwnership || {};
|
|
21
|
+
|
|
22
|
+
if (params.action === 'list') {
|
|
23
|
+
const entries = Object.entries(ownership);
|
|
24
|
+
if (entries.length === 0) {
|
|
25
|
+
return { success: true, action: 'list', message: 'Atanmış thread yok.', threads: [] };
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
success: true,
|
|
29
|
+
action: 'list',
|
|
30
|
+
threads: entries.map(([id, agent]) => ({
|
|
31
|
+
threadId: id,
|
|
32
|
+
assignedAgent: agent
|
|
33
|
+
})),
|
|
34
|
+
count: entries.length
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (params.action === 'status') {
|
|
39
|
+
if (!params.threadId) {
|
|
40
|
+
return { success: false, error: 'threadId gerekli' };
|
|
41
|
+
}
|
|
42
|
+
const assigned = ownership[params.threadId];
|
|
43
|
+
return {
|
|
44
|
+
success: true,
|
|
45
|
+
action: 'status',
|
|
46
|
+
threadId: params.threadId,
|
|
47
|
+
assignedAgent: assigned || null,
|
|
48
|
+
isAssigned: !!assigned
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (params.action === 'assign') {
|
|
53
|
+
if (!params.threadId || !params.agentName) {
|
|
54
|
+
return { success: false, error: 'threadId ve agentName gerekli' };
|
|
55
|
+
}
|
|
56
|
+
ownership[params.threadId] = params.agentName;
|
|
57
|
+
config.threadOwnership = ownership;
|
|
58
|
+
saveConfig(config);
|
|
59
|
+
return {
|
|
60
|
+
success: true,
|
|
61
|
+
action: 'assign',
|
|
62
|
+
threadId: params.threadId,
|
|
63
|
+
agentName: params.agentName,
|
|
64
|
+
message: `Thread ${params.threadId} → ${params.agentName}`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (params.action === 'release') {
|
|
69
|
+
if (!params.threadId) {
|
|
70
|
+
return { success: false, error: 'threadId gerekli' };
|
|
71
|
+
}
|
|
72
|
+
delete ownership[params.threadId];
|
|
73
|
+
config.threadOwnership = ownership;
|
|
74
|
+
saveConfig(config);
|
|
75
|
+
return {
|
|
76
|
+
success: true,
|
|
77
|
+
action: 'release',
|
|
78
|
+
threadId: params.threadId,
|
|
79
|
+
message: `Thread ${params.threadId} serbest bırakıldı`
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return { success: false, error: `Bilinmeyen aksiyon: ${params.action}` };
|
|
84
|
+
} catch (error) {
|
|
85
|
+
return { success: false, error: error.message };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const { getConfig } = require('../utils/config');
|
|
2
|
+
|
|
3
|
+
const PROVIDERS = {
|
|
4
|
+
runway: {
|
|
5
|
+
name: 'RunwayML',
|
|
6
|
+
async generate({ prompt, apiKey, model }) {
|
|
7
|
+
const response = await fetch('https://api.runwayml.com/v1/text_to_video', {
|
|
8
|
+
method: 'POST',
|
|
9
|
+
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` },
|
|
10
|
+
body: JSON.stringify({
|
|
11
|
+
model: model || 'gen3a_turbo',
|
|
12
|
+
prompt_text: prompt,
|
|
13
|
+
prompt_image: null,
|
|
14
|
+
duration: 5
|
|
15
|
+
})
|
|
16
|
+
});
|
|
17
|
+
if (!response.ok) throw new Error(`Runway error ${response.status}: ${await response.text()}`);
|
|
18
|
+
const data = await response.json();
|
|
19
|
+
return [{ url: data.video?.url || data.url, id: data.id }];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
name: 'video_generation',
|
|
26
|
+
description: 'Generate videos using AI. Supports RunwayML provider.',
|
|
27
|
+
inputSchema: {
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: {
|
|
30
|
+
prompt: { type: 'string', description: 'Text description of the video to generate' },
|
|
31
|
+
provider: { type: 'string', description: 'Video provider: runway (default: runway)', enum: ['runway'] },
|
|
32
|
+
model: { type: 'string', description: 'Model override (default: gen3a_turbo)' }
|
|
33
|
+
},
|
|
34
|
+
required: ['prompt']
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
async execute(params) {
|
|
38
|
+
try {
|
|
39
|
+
const config = getConfig();
|
|
40
|
+
const provider = params.provider || 'runway';
|
|
41
|
+
|
|
42
|
+
const providerConfig = PROVIDERS[provider];
|
|
43
|
+
if (!providerConfig) {
|
|
44
|
+
return { success: false, error: `Desteklenmeyen provider: ${provider}` };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const apiKey = params.apiKey || config.runwayApiKey || process.env.RUNWAY_API_KEY;
|
|
48
|
+
if (!apiKey) {
|
|
49
|
+
return {
|
|
50
|
+
success: false,
|
|
51
|
+
error: `${providerConfig.name} API key gerekli.\nKur: natureco config set runwayApiKey <key>`
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const videos = await providerConfig.generate({
|
|
56
|
+
prompt: params.prompt,
|
|
57
|
+
apiKey,
|
|
58
|
+
model: params.model
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
success: true,
|
|
63
|
+
prompt: params.prompt,
|
|
64
|
+
provider,
|
|
65
|
+
videos,
|
|
66
|
+
count: videos.length
|
|
67
|
+
};
|
|
68
|
+
} catch (error) {
|
|
69
|
+
return { success: false, error: error.message };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const { getConfig } = require('../utils/config');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
name: 'web_readability',
|
|
5
|
+
description: 'Extract readable content from any web page (Mozilla Readability algorithm, no API key needed)',
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
url: { type: 'string', description: 'URL to extract readable content from' },
|
|
10
|
+
maxChars: { type: 'number', description: 'Maximum characters to return (default: 10000)', default: 10000 }
|
|
11
|
+
},
|
|
12
|
+
required: ['url']
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
async execute(params) {
|
|
16
|
+
try {
|
|
17
|
+
const maxChars = params.maxChars || 10000;
|
|
18
|
+
|
|
19
|
+
const response = await fetch(params.url, {
|
|
20
|
+
headers: { 'User-Agent': 'Mozilla/5.0 (compatible; NatureCo-CLI/2.0; +https://natureco.me)' },
|
|
21
|
+
signal: AbortSignal.timeout(15000)
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
return { success: false, error: `HTTP ${response.status}: ${response.statusText}` };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const html = await response.text();
|
|
29
|
+
const contentType = response.headers.get('content-type') || '';
|
|
30
|
+
const isHtml = contentType.includes('text/html') || contentType.includes('text/plain') || html.trim().startsWith('<');
|
|
31
|
+
|
|
32
|
+
if (!isHtml) {
|
|
33
|
+
return { success: false, error: 'URL does not contain HTML content' };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Extract title
|
|
37
|
+
const titleMatch = html.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
|
|
38
|
+
const title = titleMatch ? titleMatch[1].trim() : '';
|
|
39
|
+
|
|
40
|
+
// Extract meta description
|
|
41
|
+
const descMatch = html.match(/<meta[^>]+name=["']description["'][^>]+content=["']([^"']*)["']/i);
|
|
42
|
+
const description = descMatch ? descMatch[1] : '';
|
|
43
|
+
|
|
44
|
+
// Strip HTML tags for readable text
|
|
45
|
+
let text = html
|
|
46
|
+
// Remove scripts and styles
|
|
47
|
+
.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, ' ')
|
|
48
|
+
.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, ' ')
|
|
49
|
+
.replace(/<nav[^>]*>[\s\S]*?<\/nav>/gi, ' ')
|
|
50
|
+
.replace(/<footer[^>]*>[\s\S]*?<\/footer>/gi, ' ')
|
|
51
|
+
.replace(/<header[^>]*>[\s\S]*?<\/header>/gi, ' ')
|
|
52
|
+
// Remove all HTML tags
|
|
53
|
+
.replace(/<[^>]+>/g, ' ')
|
|
54
|
+
// Decode HTML entities
|
|
55
|
+
.replace(/&/g, '&')
|
|
56
|
+
.replace(/</g, '<')
|
|
57
|
+
.replace(/>/g, '>')
|
|
58
|
+
.replace(/"/g, '"')
|
|
59
|
+
.replace(/'/g, "'")
|
|
60
|
+
.replace(///g, '/')
|
|
61
|
+
.replace(/&#\d+;/g, ' ')
|
|
62
|
+
// Normalize whitespace
|
|
63
|
+
.replace(/ /g, ' ')
|
|
64
|
+
.replace(/\s+/g, ' ')
|
|
65
|
+
.trim();
|
|
66
|
+
|
|
67
|
+
// Extract meaningful paragraphs
|
|
68
|
+
const paragraphs = [];
|
|
69
|
+
const pRegex = /<p[^>]*>([\s\S]*?)<\/p>/gi;
|
|
70
|
+
let pMatch;
|
|
71
|
+
while ((pMatch = pRegex.exec(html)) !== null) {
|
|
72
|
+
const pText = pMatch[1]
|
|
73
|
+
.replace(/<[^>]+>/g, '')
|
|
74
|
+
.replace(/ /g, ' ')
|
|
75
|
+
.replace(/\s+/g, ' ')
|
|
76
|
+
.trim();
|
|
77
|
+
if (pText.length > 20) paragraphs.push(pText);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Prefer paragraph extraction, fall back to full text
|
|
81
|
+
const content = paragraphs.length > 0
|
|
82
|
+
? paragraphs.join('\n\n')
|
|
83
|
+
: text;
|
|
84
|
+
|
|
85
|
+
const truncated = content.length > maxChars
|
|
86
|
+
? content.slice(0, maxChars) + '...'
|
|
87
|
+
: content;
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
success: true,
|
|
91
|
+
url: params.url,
|
|
92
|
+
title,
|
|
93
|
+
description,
|
|
94
|
+
content: truncated,
|
|
95
|
+
wordCount: content.split(/\s+/).length,
|
|
96
|
+
totalChars: content.length,
|
|
97
|
+
truncated: content.length > maxChars,
|
|
98
|
+
source: 'readability'
|
|
99
|
+
};
|
|
100
|
+
} catch (error) {
|
|
101
|
+
return { success: false, error: error.message };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
package/src/utils/api.js
CHANGED
|
@@ -317,8 +317,6 @@ function encodeToolResult(toolResult) {
|
|
|
317
317
|
content = toolResult;
|
|
318
318
|
} else if (toolResult.output) {
|
|
319
319
|
content = toolResult.output;
|
|
320
|
-
/* DEAD CODE */ } else if (toolResult.data) {
|
|
321
|
-
content = JSON.stringify(toolResult.data); /* DEAD CODE */
|
|
322
320
|
} else if (toolResult.success !== undefined) {
|
|
323
321
|
// Handle { success: true/false, output/error: ... } format
|
|
324
322
|
content = toolResult.success ? (toolResult.output || JSON.stringify(toolResult)) : (toolResult.error || 'Unknown error');
|
|
@@ -429,9 +427,7 @@ function formatToolsForAnthropic() {
|
|
|
429
427
|
*/
|
|
430
428
|
async function sendMessageOpenAICompatible(providerConfig, messages, tools) {
|
|
431
429
|
const baseUrl = providerConfig.url.replace(/\/+$/, '');
|
|
432
|
-
const endpoint = baseUrl
|
|
433
|
-
? 'https://api.natureco.me/api/v1/chat/completions'
|
|
434
|
-
: `${baseUrl}/chat/completions`;
|
|
430
|
+
const endpoint = `${baseUrl}/chat/completions`;
|
|
435
431
|
const requestBody = {
|
|
436
432
|
model: providerConfig.model,
|
|
437
433
|
messages: messages,
|
|
@@ -859,16 +855,8 @@ async function getBots(apiKey) {
|
|
|
859
855
|
}
|
|
860
856
|
} catch (e) {
|
|
861
857
|
debugLog('[getBots] NatureCo API error:', e.message);
|
|
858
|
+
return { bots: [], error: e.message };
|
|
862
859
|
}
|
|
863
|
-
// Fallback — API'den bot gelmezse universal provider döndür
|
|
864
|
-
return {
|
|
865
|
-
bots: [{
|
|
866
|
-
id: 'universal-provider',
|
|
867
|
-
name: 'Universal Provider (NatureCo)',
|
|
868
|
-
ai_provider: 'natureco',
|
|
869
|
-
model: 'natureco-default',
|
|
870
|
-
}]
|
|
871
|
-
};
|
|
872
860
|
}
|
|
873
861
|
|
|
874
862
|
// Diğer provider'lar — universal provider döndür
|
|
@@ -889,9 +877,6 @@ async function getBots(apiKey) {
|
|
|
889
877
|
// ── Streaming Support ────────────────────────────────────────────────────────────
|
|
890
878
|
|
|
891
879
|
async function streamProviderCompletion(providerConfig, messages, tools) {
|
|
892
|
-
if (providerConfig.url.includes('api.natureco.me')) {
|
|
893
|
-
return sendMessageOpenAICompatible(providerConfig, messages, tools);
|
|
894
|
-
}
|
|
895
880
|
if (providerConfig.isAnthropic) {
|
|
896
881
|
return streamAnthropicCompletion(providerConfig, messages);
|
|
897
882
|
}
|
|
@@ -900,9 +885,7 @@ async function streamProviderCompletion(providerConfig, messages, tools) {
|
|
|
900
885
|
|
|
901
886
|
async function streamOpenAICompletion(providerConfig, messages, tools) {
|
|
902
887
|
const baseUrl = providerConfig.url.replace(/\/+$/, '');
|
|
903
|
-
const endpoint = baseUrl
|
|
904
|
-
? 'https://api.natureco.me/api/v1/chat/completions'
|
|
905
|
-
: `${baseUrl}/chat/completions`;
|
|
888
|
+
const endpoint = `${baseUrl}/chat/completions`;
|
|
906
889
|
|
|
907
890
|
const requestBody = {
|
|
908
891
|
model: providerConfig.model,
|