natureco-cli 5.0.1 → 5.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "5.0.1",
3
+ "version": "5.1.0",
4
4
  "description": "OpenClaw'dan daha güvenli, daha hızlı, daha ucuz AI agent CLI. Multi-agent, self-evolving skills, audit log, maliyet optimizasyonu ve NatureCo platform-native.",
5
5
  "bin": {
6
6
  "natureco": "bin/natureco.js"
@@ -0,0 +1,146 @@
1
+ /**
2
+ * skill_generate - Self-generating skill (v5.1.0)
3
+ *
4
+ * Parton'un vizyonu: "Ihtiyaca gore skill yoksa kendi uretsin"
5
+ *
6
+ * Akis:
7
+ * 1. Kullanici bir istek yapar (ornek: "tum pdf'leri birlestir")
8
+ * 2. Mevcut tool/skill'ler yoksa bu tool cagirilir
9
+ * 3. LLM'a skill taslagi uretmesi icin istek gonderilir
10
+ * 4. SKILL.md dosyasi yazilir, kaydedilir, hemen kullanilir
11
+ */
12
+
13
+ const fs = require("fs");
14
+ const path = require("path");
15
+ const os = require("os");
16
+ const https = require("https");
17
+
18
+ const SKILLS_DIR = path.join(os.homedir(), ".natureco", "skills");
19
+
20
+ function getConfig() {
21
+ try {
22
+ return JSON.parse(fs.readFileSync(path.join(os.homedir(), ".natureco", "config.json"), "utf8"));
23
+ } catch { return {}; }
24
+ }
25
+
26
+ function isMiniMax(url) {
27
+ return url && (url.includes("minimax.io") || url.includes("minimaxi.com"));
28
+ }
29
+
30
+ function apiRequest(url, key, body) {
31
+ return new Promise((resolve, reject) => {
32
+ const isMM = isMiniMax(url);
33
+ const endpoint = isMM
34
+ ? url.replace(/\/$/, "") + "/v1/text/chatcompletion_v2"
35
+ : url.replace(/\/$/, "") + "/chat/completions";
36
+ const req = https.request(endpoint, {
37
+ method: "POST",
38
+ headers: { "Authorization": "Bearer " + key, "Content-Type": "application/json" },
39
+ timeout: 30000,
40
+ }, res => {
41
+ let data = "";
42
+ res.on("data", c => data += c);
43
+ res.on("end", () => {
44
+ if (res.statusCode === 200) {
45
+ try { resolve(JSON.parse(data)); } catch (e) { reject(new Error("Parse hatasi")); }
46
+ } else reject(new Error("HTTP " + res.statusCode + ": " + data.slice(0, 200)));
47
+ });
48
+ });
49
+ req.on("error", reject);
50
+ req.on("timeout", () => req.destroy() && reject(new Error("Timeout")));
51
+ req.write(JSON.stringify(body));
52
+ req.end();
53
+ });
54
+ }
55
+
56
+ function slugify(text) {
57
+ return (text || "")
58
+ .toLowerCase()
59
+ .replace(/[^a-z0-9]+/g, "-")
60
+ .replace(/^-+|-+$/g, "")
61
+ .slice(0, 40) || "custom-skill";
62
+ }
63
+
64
+ async function generateSkillInstructions(taskDescription, skillName) {
65
+ const cfg = getConfig();
66
+ if (!cfg.providerUrl || !cfg.providerApiKey) {
67
+ throw new Error("Provider ayarli degil. Once: natureco setup");
68
+ }
69
+ const promptText = "Sen NatureCo CLI icin SKILL talimatlari yazarsin. Asagidaki gorev icin System Prompt'a eklenecek Turkce talimat yaz:\n\nGOREV: " + taskDescription + "\n\nKURALLAR:\n- Turkce, kisa, oz, madde madde yaz\n- 5-10 satir, dogrudan uygulanabilir\n- Hangi araclarin kullanilacagi (dosya/shell/web) acikca belirt\n- Ornek bir kucuk kullanim ornegi ekle\n- Yanlis ciktilari nasil onlenmesi gerektigini yaz\n\nDirekt SKILL.md icerigini yaz, baska aciklama yapma.";
70
+
71
+ const body = {
72
+ model: cfg.providerModel || "MiniMax-M2.5",
73
+ messages: [
74
+ { role: "system", content: "Sen bir CLI skill talimat yazarsin. Kisa ve net Turkce yaz. Markdown kullanma, duz metin yaz." },
75
+ { role: "user", content: promptText },
76
+ ],
77
+ temperature: 0.5,
78
+ max_tokens: 1500,
79
+ };
80
+ const res = await apiRequest(cfg.providerUrl, cfg.providerApiKey, body);
81
+ const content = res.choices && res.choices[0] && res.choices[0].message ? (res.choices[0].message.content || "") : "";
82
+ return content.trim();
83
+ }
84
+
85
+ async function generateSkill(params) {
86
+ const taskDescription = params.taskDescription;
87
+ const requestedName = params.skillName;
88
+ if (!taskDescription) return { success: false, error: "taskDescription gerekli" };
89
+
90
+ const skillName = requestedName || slugify(taskDescription);
91
+ const skillDir = path.join(SKILLS_DIR, skillName);
92
+
93
+ if (fs.existsSync(skillDir)) {
94
+ return { success: true, message: "Skill zaten mevcut", path: skillDir, skillName: skillName, alreadyExisted: true };
95
+ }
96
+
97
+ let skillContent;
98
+ try {
99
+ skillContent = await generateSkillInstructions(taskDescription, skillName);
100
+ } catch (e) {
101
+ return { success: false, error: "Skill talimati uretilemedi: " + e.message };
102
+ }
103
+
104
+ if (!skillContent || skillContent.length < 50) {
105
+ return { success: false, error: "LLM bos icerik uretti" };
106
+ }
107
+
108
+ fs.mkdirSync(skillDir, { recursive: true });
109
+ fs.writeFileSync(path.join(skillDir, "SKILL.md"), skillContent, "utf8");
110
+ const meta = {
111
+ name: skillName,
112
+ description: "Otomatik uretildi: " + taskDescription.slice(0, 100),
113
+ author: "skill_generate (auto)",
114
+ version: "1.0.0",
115
+ tags: ["auto-generated", "user-created"],
116
+ autoGenerated: true,
117
+ taskDescription: taskDescription,
118
+ createdAt: new Date().toISOString(),
119
+ };
120
+ fs.writeFileSync(path.join(skillDir, "metadata.json"), JSON.stringify(meta, null, 2), "utf8");
121
+
122
+ return {
123
+ success: true,
124
+ message: "Yeni skill olusturuldu ve hemen kullanilabilir!",
125
+ skillName: skillName,
126
+ path: skillDir,
127
+ content: skillContent.slice(0, 300),
128
+ note: "REPL'i yeniden acarsaniz yeni skill yuklenecek. /skills list ile test edebilirsiniz.",
129
+ };
130
+ }
131
+
132
+ module.exports = {
133
+ name: "skill_generate",
134
+ description: "Olmayan bir ozellik icin LLM ile yeni bir skill talimati uretir, kaydeder ve hemen kullanima sunar. 'PDF birlestir', 'JSON duzenle' gibi gorevler icin.",
135
+ inputSchema: {
136
+ type: "object",
137
+ properties: {
138
+ taskDescription: { type: "string", description: "Skill'in ne yapacagi (ornek: 'PDF dosyalarini tek dosyada birlestir')" },
139
+ skillName: { type: "string", description: "Ozel skill adi (opsiyonel, otomatik uretilir)" },
140
+ },
141
+ required: ["taskDescription"],
142
+ },
143
+ async execute(params) {
144
+ return await generateSkill(params);
145
+ },
146
+ };