natureco-cli 4.8.4 → 4.9.1
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/package.json +1 -1
- package/src/tools/calendar_add.js +94 -0
- package/src/tools/code_execution.js +86 -0
- package/src/tools/cron_create.js +105 -0
- package/src/tools/delegate_task.js +61 -0
- package/src/tools/file_search.js +85 -0
- package/src/tools/grep_search.js +127 -0
- package/src/tools/http_request.js +77 -0
- package/src/tools/kanban.js +108 -0
- package/src/tools/mac_app_open.js +38 -0
- package/src/tools/mac_app_quit.js +46 -0
- package/src/tools/mac_notify.js +50 -0
- package/src/tools/memory_search.js +112 -0
- package/src/tools/notebook_edit.js +93 -0
- package/src/tools/notes_add.js +62 -0
- package/src/tools/reminder_add.js +65 -0
- package/src/tools/shell_command.js +55 -0
- package/src/tools/text_to_speech.js +84 -98
- package/src/tools/todo_write.js +88 -0
|
@@ -1,105 +1,91 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* text_to_speech - TTS (v4.9.0)
|
|
3
|
+
*
|
|
4
|
+
* Hermes TTS'ine benzer. Edge TTS veya OpenAI TTS.
|
|
5
|
+
* macOS'ta 'say' komutu fallback.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { spawn } = require("child_process");
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const os = require("os");
|
|
12
|
+
|
|
13
|
+
async function speak({ text, provider = "auto", voice = "tr-TR", savePath = null }) {
|
|
14
|
+
if (!text) return { success: false, error: "text gerekli" };
|
|
15
|
+
|
|
16
|
+
// Once dosyaya kaydet, sonra caldir
|
|
17
|
+
if (provider === "auto" || provider === "edge") {
|
|
18
|
+
return await edgeTTS(text, voice, savePath);
|
|
19
|
+
}
|
|
20
|
+
if (provider === "say") {
|
|
21
|
+
return await macSay(text);
|
|
22
|
+
}
|
|
23
|
+
if (provider === "save") {
|
|
24
|
+
return await saveToFile(text, savePath);
|
|
25
|
+
}
|
|
26
|
+
return { success: false, error: `Desteklenmeyen provider: ${provider}` };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function edgeTTS(text, voice, savePath) {
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
const out = savePath || path.join(os.tmpdir(), `tts-${Date.now()}.mp3`);
|
|
32
|
+
const proc = spawn("python3", ["-c", `
|
|
33
|
+
import asyncio, sys
|
|
34
|
+
try:
|
|
35
|
+
import edge_tts
|
|
36
|
+
except ImportError:
|
|
37
|
+
print("ERROR: pip install edge-tts", file=sys.stderr)
|
|
38
|
+
sys.exit(1)
|
|
39
|
+
async def main():
|
|
40
|
+
tts = edge_tts.Communicate("""${text.replace(/"/g, "'")}""", "${voice}")
|
|
41
|
+
await tts.save("${out}")
|
|
42
|
+
asyncio.run(main())
|
|
43
|
+
`], { timeout: 30000 });
|
|
44
|
+
let stderr = "";
|
|
45
|
+
proc.stderr.on("data", d => stderr += d);
|
|
46
|
+
proc.on("close", code => {
|
|
47
|
+
if (code === 0) resolve({ success: true, provider: "edge", path: out, message: `Ses kaydedildi: ${out}` });
|
|
48
|
+
else resolve({ success: false, error: stderr || `edge-tts hata ${code}. Kur: pip install edge-tts` });
|
|
49
|
+
});
|
|
50
|
+
proc.on("error", e => resolve({ success: false, error: e.message + " (pip install edge-tts)" }));
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function macSay(text) {
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
|
+
const proc = spawn("say", ["-v", "Yelda", text]);
|
|
57
|
+
proc.on("close", code => {
|
|
58
|
+
if (code === 0) resolve({ success: true, provider: "mac-say", message: "Seslendirildi" });
|
|
59
|
+
else resolve({ success: false, error: `say hata ${code}` });
|
|
60
|
+
});
|
|
61
|
+
proc.on("error", e => resolve({ success: false, error: e.message }));
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function saveToFile(text, savePath) {
|
|
66
|
+
if (!savePath) return { success: false, error: "savePath gerekli" };
|
|
67
|
+
try {
|
|
68
|
+
fs.writeFileSync(savePath, text, "utf8");
|
|
69
|
+
return { success: true, provider: "save", path: savePath, message: `Metin kaydedildi: ${savePath}` };
|
|
70
|
+
} catch (e) {
|
|
71
|
+
return { success: false, error: e.message };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
2
74
|
|
|
3
75
|
module.exports = {
|
|
4
|
-
name:
|
|
5
|
-
description:
|
|
76
|
+
name: "text_to_speech",
|
|
77
|
+
description: "Metin seslendir. macOS say, edge-tts (pip install edge-tts), veya dosyaya kaydet.",
|
|
6
78
|
inputSchema: {
|
|
7
|
-
type:
|
|
79
|
+
type: "object",
|
|
8
80
|
properties: {
|
|
9
|
-
text: { type:
|
|
10
|
-
provider: { type:
|
|
11
|
-
voice: { type:
|
|
12
|
-
|
|
81
|
+
text: { type: "string", description: "Seslendirilecek metin" },
|
|
82
|
+
provider: { type: "string", description: "edge, say, save (default: auto)", enum: ["auto", "edge", "say", "save"] },
|
|
83
|
+
voice: { type: "string", description: "Ses (ornek: tr-TR-EmelNeural, en-US-AriaNeural)" },
|
|
84
|
+
savePath: { type: "string", description: "Kayıt yolu (edge/save provider için)" },
|
|
13
85
|
},
|
|
14
|
-
required: [
|
|
86
|
+
required: ["text"],
|
|
15
87
|
},
|
|
16
|
-
|
|
17
88
|
async execute(params) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
};
|
|
89
|
+
return await speak(params);
|
|
90
|
+
},
|
|
91
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* todo_write - Yapilacaklar listesi (v4.9.0)
|
|
3
|
+
*
|
|
4
|
+
* Hermes todo_write'una benzer.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
const path = require("path");
|
|
9
|
+
const os = require("os");
|
|
10
|
+
|
|
11
|
+
const TODO_FILE = path.join(os.homedir(), ".natureco", "todos.json");
|
|
12
|
+
|
|
13
|
+
function loadTodos() {
|
|
14
|
+
try {
|
|
15
|
+
if (!fs.existsSync(TODO_FILE)) return [];
|
|
16
|
+
return JSON.parse(fs.readFileSync(TODO_FILE, "utf8"));
|
|
17
|
+
} catch { return []; }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function saveTodos(todos) {
|
|
21
|
+
fs.mkdirSync(path.dirname(TODO_FILE), { recursive: true });
|
|
22
|
+
fs.writeFileSync(TODO_FILE, JSON.stringify(todos, null, 2), "utf8");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function genId() {
|
|
26
|
+
return Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function todoAction({ action = "list", content, id, priority = "medium", status }) {
|
|
30
|
+
let todos = loadTodos();
|
|
31
|
+
|
|
32
|
+
if (action === "list") {
|
|
33
|
+
const pending = todos.filter(t => t.status === "pending");
|
|
34
|
+
const done = todos.filter(t => t.status === "done");
|
|
35
|
+
return { success: true, total: todos.length, pending: pending.length, done: done.length, todos: pending };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (action === "add") {
|
|
39
|
+
if (!content) return { success: false, error: "content gerekli" };
|
|
40
|
+
const todo = { id: genId(), content, priority, status: "pending", createdAt: new Date().toISOString() };
|
|
41
|
+
todos.push(todo);
|
|
42
|
+
saveTodos(todos);
|
|
43
|
+
return { success: true, todo, message: `Todo eklendi: ${content}` };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (action === "done") {
|
|
47
|
+
if (!id) return { success: false, error: "id gerekli" };
|
|
48
|
+
const todo = todos.find(t => t.id === id);
|
|
49
|
+
if (!todo) return { success: false, error: `Todo bulunamadi: ${id}` };
|
|
50
|
+
todo.status = "done";
|
|
51
|
+
todo.completedAt = new Date().toISOString();
|
|
52
|
+
saveTodos(todos);
|
|
53
|
+
return { success: true, todo, message: `Tamamlandi: ${todo.content}` };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (action === "remove") {
|
|
57
|
+
if (!id) return { success: false, error: "id gerekli" };
|
|
58
|
+
const before = todos.length;
|
|
59
|
+
todos = todos.filter(t => t.id !== id);
|
|
60
|
+
saveTodos(todos);
|
|
61
|
+
return { success: true, removed: before - todos.length };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (action === "clear") {
|
|
65
|
+
saveTodos([]);
|
|
66
|
+
return { success: true, cleared: todos.length, message: "Tum todolar temizlendi" };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return { success: false, error: `Bilinmeyen action: ${action}` };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
name: "todo_write",
|
|
74
|
+
description: "Yapilacaklar listesi. action: list, add, done, remove, clear.",
|
|
75
|
+
inputSchema: {
|
|
76
|
+
type: "object",
|
|
77
|
+
properties: {
|
|
78
|
+
action: { type: "string", description: "list/add/done/remove/clear (default: list)", enum: ["list", "add", "done", "remove", "clear"] },
|
|
79
|
+
content: { type: "string", description: "Todo icerigi (add icin)" },
|
|
80
|
+
id: { type: "string", description: "Todo ID (done/remove icin)" },
|
|
81
|
+
priority: { type: "string", description: "Oncelik: low/medium/high (add icin)", enum: ["low", "medium", "high"] },
|
|
82
|
+
status: { type: "string", description: "Durum filtresi: pending/done" },
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
async execute(params) {
|
|
86
|
+
return await todoAction(params);
|
|
87
|
+
},
|
|
88
|
+
};
|