natureco-cli 4.9.1 → 5.0.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.
@@ -0,0 +1,97 @@
1
+ /**
2
+ * skills_autoload - Otomatik skill yukleme (v5.0.0)
3
+ *
4
+ * Parton'un vizyonu: "Ihtiyaca gore skill'ler otomatik yuklensin"
5
+ *
6
+ * Mantik:
7
+ * 1. Kullanici bir istek yapar
8
+ * 2. REPL anahtar kelimeleri tarar (seo, telegram, git commit, vb.)
9
+ * 3. Ilgili skill varsa otomatik yuklenir
10
+ * 4. System prompt'a eklenir
11
+ */
12
+
13
+ const fs = require("fs");
14
+ const path = require("path");
15
+ const os = require("os");
16
+
17
+ const SKILLS_DIR = path.join(os.homedir(), ".natureco", "skills");
18
+
19
+ /**
20
+ * Anahtar kelime -> skill mapping
21
+ */
22
+ const KEYWORD_MAP = {
23
+ // SEO
24
+ "seo": ["seo", "audit", "site", "website", "ranking", "meta", "search engine", "url"],
25
+ "telegram": ["telegram", "bot", "botfather", "t.me"],
26
+ "git-commit": ["commit", "git commit", "conventional commit", "kaydet", "gönder"],
27
+ "code-review": ["review", "incele", "kod incele", "bug", "security check"],
28
+ "morning-briefing": ["briefing", "morning", "sabah brifingi", "günlük özet"],
29
+ };
30
+
31
+ function loadAllSkills() {
32
+ const loaded = [];
33
+ try {
34
+ if (!fs.existsSync(SKILLS_DIR)) return loaded;
35
+ const dirs = fs.readdirSync(SKILLS_DIR, { withFileTypes: true });
36
+ for (const dir of dirs) {
37
+ if (!dir.isDirectory()) continue;
38
+ const skillFile = path.join(SKILLS_DIR, dir.name, "SKILL.md");
39
+ if (fs.existsSync(skillFile)) {
40
+ loaded.push({ name: dir.name, content: fs.readFileSync(skillFile, "utf8") });
41
+ }
42
+ }
43
+ } catch {}
44
+ return loaded;
45
+ }
46
+
47
+ /**
48
+ * Mesaj icindeki anahtar kelimeleri tara, ilgili skill'leri bul
49
+ */
50
+ function detectRelevantSkills(message, availableSkills) {
51
+ const lower = message.toLowerCase();
52
+ const detected = new Set();
53
+
54
+ for (const [skill, keywords] of Object.entries(KEYWORD_MAP)) {
55
+ for (const kw of keywords) {
56
+ if (lower.includes(kw)) {
57
+ detected.add(skill);
58
+ break;
59
+ }
60
+ }
61
+ }
62
+
63
+ // Yuklu skill'lerle kesistir
64
+ return availableSkills.filter(s => detected.has(s.name));
65
+ }
66
+
67
+ function autoLoad(message) {
68
+ const available = loadAllSkills();
69
+ const relevant = detectRelevantSkills(message, available);
70
+ if (relevant.length === 0) return [];
71
+
72
+ return relevant.map(s => ({
73
+ name: s.name,
74
+ summary: s.content.slice(0, 500).split("\n").slice(0, 3).join("\n"),
75
+ }));
76
+ }
77
+
78
+ module.exports = {
79
+ name: "skills_autoload",
80
+ description: "Kullanici istegine gore otomatik skill yukle. Mesaj analiz edilir, ilgili skill sistem prompt'a eklenir.",
81
+ inputSchema: {
82
+ type: "object",
83
+ properties: {
84
+ message: { type: "string", description: "Kullanici mesaji / istegi" },
85
+ },
86
+ required: ["message"],
87
+ },
88
+ async execute(params) {
89
+ const loaded = autoLoad(params.message);
90
+ return {
91
+ success: true,
92
+ message: params.message,
93
+ detectedSkills: loaded.map(s => s.name),
94
+ skillContext: loaded.map(s => s.content).join("\n\n"),
95
+ };
96
+ },
97
+ };
@@ -0,0 +1,233 @@
1
+ /**
2
+ * skills_marketplace - Skill marketplace (v5.0.0)
3
+ *
4
+ * Parton'un vizyonu: "herkes kendi skill'ini paylassin, CLI otomatik yuklesin"
5
+ *
6
+ * Format: ~/.natureco/marketplace/<skill_name>.json
7
+ * Source: NatureCo GitHub repo (community-contributed) veya local
8
+ */
9
+
10
+ const fs = require("fs");
11
+ const path = require("path");
12
+ const os = require("os");
13
+ const https = require("https");
14
+
15
+ const MARKETPLACE_DIR = path.join(os.homedir(), ".natureco", "marketplace");
16
+ const SKILLS_DIR = path.join(os.homedir(), ".natureco", "skills");
17
+
18
+ /**
19
+ * Marketplace URL'leri — Parton kendi GitHub repo'sunu koyacak
20
+ */
21
+ const MARKETPLACE_SOURCES = [
22
+ {
23
+ name: "NatureCo Official",
24
+ url: "https://raw.githubusercontent.com/naturecoofficial/natureco-skills/main/index.json",
25
+ enabled: true,
26
+ },
27
+ {
28
+ name: "Community",
29
+ url: "https://raw.githubusercontent.com/natureco-community/skills/main/index.json",
30
+ enabled: true,
31
+ },
32
+ ];
33
+
34
+ /**
35
+ * Built-in skill paketleri — Parton'un NatureCo vizyonu icin onemli
36
+ */
37
+ const BUILTIN_SKILLS = {
38
+ "seo-audit": {
39
+ name: "SEO Audit",
40
+ description: "Web sitesi SEO denetimi - meta tags, headings, schema.org, performance",
41
+ author: "NatureCo Team",
42
+ version: "1.0.0",
43
+ tags: ["seo", "web", "audit"],
44
+ instructions: "Kullanici bir URL isteyince, bu skill devreye girer. http_request ile sayfayi cek, og:title, og:description, og:image, h1/h2 sayisi, schema.org/l* varligi, robots.txt, sitemap.xml kontrol et. Skor 0-100 dondur.",
45
+ },
46
+ "code-review": {
47
+ name: "Code Review",
48
+ description: "Kod inceleme - style, best practices, security, performance",
49
+ author: "NatureCo Team",
50
+ version: "1.0.0",
51
+ tags: ["code", "review", "security"],
52
+ instructions: "Kullanici kod gonderdiginde, grep_search ile TODO/FIXME/security issue bul, linting kontrolu yap, ozellikle XSS, SQL injection, hardcoded secret'lere bak. Olumlu/olumsuz yonleri listele.",
53
+ },
54
+ "git-commit": {
55
+ name: "Smart Git Commit",
56
+ description: "AI ile conventional commit mesaji uret",
57
+ author: "NatureCo Team",
58
+ version: "1.0.0",
59
+ tags: ["git", "workflow"],
60
+ instructions: "git diff ciktisini oku, degisiklik tipine gore (feat/fix/docs/style/refactor/test/chore) conventional commit formatinda mesaj uret. Turkce veya Ingilizce gore dili ayarla.",
61
+ },
62
+ "telegram-bot": {
63
+ name: "Telegram Bot Setup",
64
+ description: "Telegram bot kurulum wizard - BotFather adim adim",
65
+ author: "NatureCo Team",
66
+ version: "1.0.0",
67
+ tags: ["telegram", "integration", "tutorial"],
68
+ instructions: "Kullanici 'Telegram bot kur' dediginde, sirasiyla: 1) @BotFather'a git, 2) /newbot, 3) isim ve username, 4) token al, 5) natureco telegram connect ile gir, 6) @userinfobot'tan user ID al, 7) natureco gateway start. Adim adim Turkce yonlendir.",
69
+ },
70
+ "morning-briefing": {
71
+ name: "Morning Briefing",
72
+ description: "Her sabah 9'da ozet: hava, takvim, todo'lar, RSS",
73
+ author: "NatureCo Team",
74
+ version: "1.0.0",
75
+ tags: ["productivity", "cron", "daily"],
76
+ instructions: "cron_create ile her sabah 9'da calisan bir setup kur. natureco weather, natureco calendar today, natureco todo_write list, natureco memory_search - tum bunlari ozetleyen bir gunluk briefing ver.",
77
+ },
78
+ };
79
+
80
+ /**
81
+ * Local skill yukle (skill dosyasi -> ~/.natureco/skills/<name>/)
82
+ */
83
+ function installLocal(skillData) {
84
+ if (!skillData.name) return { success: false, error: "Skill name gerekli" };
85
+ const skillDir = path.join(SKILLS_DIR, skillData.name);
86
+ fs.mkdirSync(skillDir, { recursive: true });
87
+
88
+ const skillFile = path.join(skillDir, "SKILL.md");
89
+ const content = skillData.instructions || skillData.content || `# ${skillData.name}\n\n${skillData.description || ""}`;
90
+ fs.writeFileSync(skillFile, content, "utf8");
91
+
92
+ // Metadata
93
+ const meta = {
94
+ name: skillData.name,
95
+ description: skillData.description,
96
+ author: skillData.author || "Unknown",
97
+ version: skillData.version || "1.0.0",
98
+ tags: skillData.tags || [],
99
+ installedAt: new Date().toISOString(),
100
+ };
101
+ fs.writeFileSync(path.join(skillDir, "metadata.json"), JSON.stringify(meta, null, 2), "utf8");
102
+
103
+ return { success: true, path: skillDir, skill: meta };
104
+ }
105
+
106
+ /**
107
+ * URL'den skill yukle (GitHub raw content)
108
+ */
109
+ function installFromUrl(url) {
110
+ return new Promise((resolve) => {
111
+ https.get(url, (res) => {
112
+ let data = "";
113
+ res.on("data", d => data += d);
114
+ res.on("end", () => {
115
+ try {
116
+ const skill = JSON.parse(data);
117
+ resolve(installLocal(skill));
118
+ } catch (e) {
119
+ resolve({ success: false, error: "Skill JSON parse hatasi: " + e.message });
120
+ }
121
+ });
122
+ }).on("error", e => resolve({ success: false, error: e.message }));
123
+ });
124
+ }
125
+
126
+ /**
127
+ * Marketplace listele
128
+ */
129
+ async function listMarketplace() {
130
+ const skills = { ...BUILTIN_SKILLS };
131
+
132
+ // Remote sources'dan da cekmeyi dene
133
+ for (const source of MARKETPLACE_SOURCES.filter(s => s.enabled)) {
134
+ try {
135
+ const remote = await new Promise((resolve) => {
136
+ const req = https.get(source.url, { timeout: 5000 }, (res) => {
137
+ let data = "";
138
+ res.on("data", d => data += d);
139
+ res.on("end", () => {
140
+ try { resolve(JSON.parse(data)); } catch { resolve({}); }
141
+ });
142
+ });
143
+ req.on("error", () => resolve({}));
144
+ req.on("timeout", () => { req.destroy(); resolve({}); });
145
+ });
146
+ Object.assign(skills, remote);
147
+ } catch {}
148
+ }
149
+
150
+ return skills;
151
+ }
152
+
153
+ /**
154
+ * Tool definitions
155
+ */
156
+ module.exports = {
157
+ name: "skills_marketplace",
158
+ description: "Skill marketplace - topluluk tarafindan paylasilan NatureCo CLI skill'leri. action: list, install, uninstall, search.",
159
+ inputSchema: {
160
+ type: "object",
161
+ properties: {
162
+ action: { type: "string", description: "list/install/uninstall/search", enum: ["list", "install", "uninstall", "search"] },
163
+ skillName: { type: "string", description: "Skill adi (install/uninstall icin)" },
164
+ query: { type: "string", description: "Arama sorgusu (search icin)" },
165
+ source: { type: "string", description: "Marketplace URL (custom source icin)" },
166
+ },
167
+ required: ["action"],
168
+ },
169
+ async execute(params) {
170
+ const { action, skillName, query, source } = params;
171
+
172
+ if (action === "list") {
173
+ const all = await listMarketplace();
174
+ return {
175
+ success: true,
176
+ count: Object.keys(all).length,
177
+ skills: Object.entries(all).map(([name, s]) => ({
178
+ name,
179
+ description: s.description,
180
+ author: s.author,
181
+ version: s.version,
182
+ tags: s.tags,
183
+ })),
184
+ };
185
+ }
186
+
187
+ if (action === "search") {
188
+ if (!query) return { success: false, error: "query gerekli" };
189
+ const all = await listMarketplace();
190
+ const q = query.toLowerCase();
191
+ const matches = Object.entries(all).filter(([_, s]) =>
192
+ s.description?.toLowerCase().includes(q) ||
193
+ s.tags?.some(t => t.toLowerCase().includes(q)) ||
194
+ s.name.toLowerCase().includes(q)
195
+ );
196
+ return { success: true, query, count: matches.length, results: matches.map(([n, s]) => ({ name: n, ...s })) };
197
+ }
198
+
199
+ if (action === "install") {
200
+ if (!skillName) return { success: false, error: "skillName gerekli" };
201
+
202
+ // Once local BUILTIN'den dene
203
+ if (BUILTIN_SKILLS[skillName]) {
204
+ return installLocal(BUILTIN_SKILLS[skillName]);
205
+ }
206
+
207
+ // Sonra URL'den dene
208
+ if (source) {
209
+ return await installFromUrl(source);
210
+ }
211
+
212
+ // Marketplace'ten dene
213
+ const all = await listMarketplace();
214
+ if (all[skillName]) {
215
+ return installLocal(all[skillName]);
216
+ }
217
+
218
+ return { success: false, error: `Skill bulunamadi: ${skillName}. Once 'list' calistirin.` };
219
+ }
220
+
221
+ if (action === "uninstall") {
222
+ if (!skillName) return { success: false, error: "skillName gerekli" };
223
+ const skillDir = path.join(SKILLS_DIR, skillName);
224
+ if (!fs.existsSync(skillDir)) {
225
+ return { success: false, error: `Skill yuklu degil: ${skillName}` };
226
+ }
227
+ fs.rmSync(skillDir, { recursive: true });
228
+ return { success: true, message: `Skill kaldirildi: ${skillName}` };
229
+ }
230
+
231
+ return { success: false, error: `Bilinmeyen action: ${action}` };
232
+ },
233
+ };