natureco-cli 2.23.31 → 4.4.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/AUDIT.md +178 -0
- package/CHANGELOG.md +422 -0
- package/DEPLOY_v2.0.0.md +400 -0
- package/README.md +159 -1
- package/bin/natureco.js +182 -12
- package/package.json +43 -11
- package/skills/code-review/SKILL.md +0 -0
- package/skills/summarize/SKILL.md +0 -0
- package/skills/translate/SKILL.md +0 -0
- package/src/commands/acp.js +0 -0
- package/src/commands/admin-rpc.js +0 -0
- package/src/commands/agent.js +0 -0
- package/src/commands/agents.js +0 -0
- package/src/commands/approvals.js +0 -0
- package/src/commands/ask.js +1 -1
- package/src/commands/audit.js +209 -0
- package/src/commands/backup.js +0 -0
- package/src/commands/bonjour.js +0 -0
- package/src/commands/bots.js +0 -0
- package/src/commands/browser.js +0 -0
- package/src/commands/capability.js +0 -0
- package/src/commands/channels.js +0 -0
- package/src/commands/chat.js +0 -0
- package/src/commands/clawbot.js +0 -0
- package/src/commands/clickclack.js +0 -0
- package/src/commands/code.js +0 -0
- package/src/commands/commands.js +0 -0
- package/src/commands/commitments.js +0 -0
- package/src/commands/completion.js +0 -0
- package/src/commands/config.js +11 -2
- package/src/commands/configure.js +0 -0
- package/src/commands/cost.js +210 -0
- package/src/commands/crestodian.js +0 -0
- package/src/commands/cron.js +0 -0
- package/src/commands/daemon.js +0 -0
- package/src/commands/dashboard.js +126 -45
- package/src/commands/device-pair.js +0 -0
- package/src/commands/devices.js +0 -0
- package/src/commands/directory.js +0 -0
- package/src/commands/discord.js +0 -0
- package/src/commands/dns.js +0 -0
- package/src/commands/docs.js +0 -0
- package/src/commands/doctor.js +134 -15
- package/src/commands/exec-policy.js +0 -0
- package/src/commands/gateway-server.js +0 -0
- package/src/commands/gateway.js +0 -0
- package/src/commands/git.js +0 -0
- package/src/commands/health.js +0 -0
- package/src/commands/help.js +0 -0
- package/src/commands/hooks.js +0 -0
- package/src/commands/imessage.js +0 -0
- package/src/commands/infer.js +0 -0
- package/src/commands/init.js +0 -0
- package/src/commands/irc.js +0 -0
- package/src/commands/login.js +0 -0
- package/src/commands/logout.js +0 -0
- package/src/commands/logs.js +0 -0
- package/src/commands/mattermost.js +0 -0
- package/src/commands/mcp.js +0 -0
- package/src/commands/medium.js +206 -0
- package/src/commands/memory-cmd.js +0 -0
- package/src/commands/memory.js +0 -0
- package/src/commands/message.js +0 -0
- package/src/commands/migrate.js +0 -0
- package/src/commands/models.js +0 -0
- package/src/commands/naturehub.js +156 -0
- package/src/commands/node.js +0 -0
- package/src/commands/nodes.js +1 -1
- package/src/commands/oc-path.js +0 -0
- package/src/commands/onboard.js +0 -0
- package/src/commands/open-prose.js +0 -0
- package/src/commands/pairing.js +0 -0
- package/src/commands/path.js +0 -0
- package/src/commands/plugins.js +0 -0
- package/src/commands/policy.js +0 -0
- package/src/commands/proxy.js +0 -0
- package/src/commands/qr.js +0 -0
- package/src/commands/reset.js +0 -0
- package/src/commands/run.js +0 -0
- package/src/commands/sandbox.js +0 -0
- package/src/commands/secrets.js +0 -0
- package/src/commands/security.js +0 -0
- package/src/commands/seo.js +268 -0
- package/src/commands/sessions.js +0 -0
- package/src/commands/setup.js +131 -4
- package/src/commands/signal.js +0 -0
- package/src/commands/skills.js +82 -1
- package/src/commands/slack.js +0 -0
- package/src/commands/sms.js +0 -0
- package/src/commands/status.js +0 -0
- package/src/commands/system.js +0 -0
- package/src/commands/tasks.js +0 -0
- package/src/commands/team.js +171 -0
- package/src/commands/telegram.js +0 -0
- package/src/commands/terminal.js +0 -0
- package/src/commands/thread-ownership.js +0 -0
- package/src/commands/transcripts.js +0 -0
- package/src/commands/tui.js +0 -0
- package/src/commands/ultrareview.js +0 -0
- package/src/commands/uninstall.js +0 -0
- package/src/commands/update.js +0 -0
- package/src/commands/voice.js +0 -0
- package/src/commands/vydra.js +0 -0
- package/src/commands/web-fetch.js +34 -0
- package/src/commands/webhooks.js +0 -0
- package/src/commands/whatsapp.js +0 -0
- package/src/commands/wiki.js +0 -0
- package/src/commands/workboard.js +0 -0
- package/src/commands/xp.js +194 -0
- package/src/tools/audio_understanding.js +0 -0
- package/src/tools/bash.js +0 -0
- package/src/tools/browser.js +0 -0
- package/src/tools/canvas.js +0 -0
- package/src/tools/document_extract.js +0 -0
- package/src/tools/duckduckgo.js +0 -0
- package/src/tools/exa_search.js +0 -0
- package/src/tools/filesystem.js +0 -0
- package/src/tools/firecrawl.js +0 -0
- package/src/tools/git.js +0 -0
- package/src/tools/http.js +0 -0
- package/src/tools/image_generation.js +0 -0
- package/src/tools/list_dir.js +0 -0
- package/src/tools/llm_task.js +43 -11
- package/src/tools/media_understanding.js +0 -0
- package/src/tools/music_generation.js +0 -0
- package/src/tools/parallel_search.js +0 -0
- package/src/tools/phone_control.js +0 -0
- package/src/tools/phone_control_enhanced.js +0 -0
- package/src/tools/read_file.js +0 -0
- package/src/tools/searxng.js +0 -0
- package/src/tools/speech_to_text.js +0 -0
- package/src/tools/text_to_speech.js +0 -0
- package/src/tools/thread_ownership.js +0 -0
- package/src/tools/video_generation.js +0 -0
- package/src/tools/web_readability.js +0 -0
- package/src/tools/web_search.js +0 -0
- package/src/tools/write_file.js +0 -0
- package/src/utils/agents-md.js +0 -0
- package/src/utils/agents.js +0 -0
- package/src/utils/api.js +6 -2
- package/src/utils/approvals.js +0 -0
- package/src/utils/audit.js +199 -0
- package/src/utils/background.js +0 -0
- package/src/utils/baileys.js +0 -0
- package/src/utils/branding.js +136 -0
- package/src/utils/commands.js +0 -0
- package/src/utils/config.js +0 -0
- package/src/utils/cost-tracker.js +360 -0
- package/src/utils/cron.js +0 -0
- package/src/utils/dashboard-server.js +284 -0
- package/src/utils/errors.js +0 -0
- package/src/utils/format.js +7 -10
- package/src/utils/gateway-ws.js +0 -0
- package/src/utils/headless.js +0 -0
- package/src/utils/history.js +0 -0
- package/src/utils/hooks.js +0 -0
- package/src/utils/inquirer-wrapper.js +0 -0
- package/src/utils/mcp-client.js +0 -0
- package/src/utils/mcp.js +0 -0
- package/src/utils/memory.js +0 -0
- package/src/utils/parallel-tools.js +0 -0
- package/src/utils/path-utils.js +0 -0
- package/src/utils/pattern-detector.js +314 -0
- package/src/utils/plugin-registry.js +0 -0
- package/src/utils/secret-scanner.js +204 -0
- package/src/utils/secrets.js +0 -0
- package/src/utils/sessions.js +0 -0
- package/src/utils/skills.js +0 -0
- package/src/utils/sub-agent.js +6 -0
- package/src/utils/token-budget.js +0 -0
- package/src/utils/tool-adapter.js +0 -0
- package/src/utils/tool-runner.js +0 -0
- package/src/utils/tui.js +750 -0
- package/src/utils/web-fetch.js +0 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* natureco seo — SEO analiz aracı (Phase 6)
|
|
3
|
+
*
|
|
4
|
+
* Herhangi bir URL için hızlı SEO denetimi.
|
|
5
|
+
* Meta tags, başlık yapısı, performans ipuçları, schema.org kontrolü.
|
|
6
|
+
*
|
|
7
|
+
* Kullanım:
|
|
8
|
+
* natureco seo audit <url> Tam SEO denetimi
|
|
9
|
+
* natureco seo meta <url> Meta tag analizi
|
|
10
|
+
* natureco seo speed <url> Hız ipuçları
|
|
11
|
+
* natureco seo keywords <url> <k> Keyword density
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const chalk = require('chalk');
|
|
15
|
+
const tui = require('../utils/tui');
|
|
16
|
+
const https = require('https');
|
|
17
|
+
const http = require('http');
|
|
18
|
+
const { URL } = require('url');
|
|
19
|
+
const audit = require('../utils/audit');
|
|
20
|
+
|
|
21
|
+
function fetchUrl(targetUrl, options = {}) {
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
const url = new URL(targetUrl);
|
|
24
|
+
const client = url.protocol === 'https:' ? https : http;
|
|
25
|
+
const req = client.request({
|
|
26
|
+
hostname: url.hostname,
|
|
27
|
+
path: url.pathname + url.search,
|
|
28
|
+
method: 'GET',
|
|
29
|
+
headers: {
|
|
30
|
+
'User-Agent': 'NatureCo-SEO-Audit/3.5',
|
|
31
|
+
'Accept': 'text/html,application/xhtml+xml',
|
|
32
|
+
...options.headers,
|
|
33
|
+
},
|
|
34
|
+
timeout: 15000,
|
|
35
|
+
}, (res) => {
|
|
36
|
+
// Redirect takip (max 3)
|
|
37
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
38
|
+
const redirect = new URL(res.headers.location, url).toString();
|
|
39
|
+
return fetchUrl(redirect).then(resolve).catch(reject);
|
|
40
|
+
}
|
|
41
|
+
let data = '';
|
|
42
|
+
res.on('data', (c) => data += c);
|
|
43
|
+
res.on('end', () => resolve({
|
|
44
|
+
statusCode: res.statusCode,
|
|
45
|
+
headers: res.headers,
|
|
46
|
+
body: data,
|
|
47
|
+
url: targetUrl,
|
|
48
|
+
}));
|
|
49
|
+
});
|
|
50
|
+
req.on('error', reject);
|
|
51
|
+
req.on('timeout', () => { req.destroy(); reject(new Error('Timeout')); });
|
|
52
|
+
req.end();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function extractMeta(html) {
|
|
57
|
+
const result = {};
|
|
58
|
+
// Title
|
|
59
|
+
const titleMatch = html.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
|
|
60
|
+
result.title = titleMatch ? titleMatch[1].trim() : null;
|
|
61
|
+
// Meta description
|
|
62
|
+
const descMatch = html.match(/<meta\s+name=["']description["']\s+content=["']([\s\S]*?)["']/i);
|
|
63
|
+
result.description = descMatch ? descMatch[1].trim() : null;
|
|
64
|
+
// Canonical
|
|
65
|
+
const canonMatch = html.match(/<link\s+rel=["']canonical["']\s+href=["']([\s\S]*?)["']/i);
|
|
66
|
+
result.canonical = canonMatch ? canonMatch[1].trim() : null;
|
|
67
|
+
// Open Graph
|
|
68
|
+
result.og = {};
|
|
69
|
+
const ogRe = /<meta\s+property=["']og:(\w+)["']\s+content=["']([\s\S]*?)["']/gi;
|
|
70
|
+
let m;
|
|
71
|
+
while ((m = ogRe.exec(html)) !== null) {
|
|
72
|
+
result.og[m[1]] = m[2].trim();
|
|
73
|
+
}
|
|
74
|
+
// Twitter Card
|
|
75
|
+
result.twitter = {};
|
|
76
|
+
const twRe = /<meta\s+name=["']twitter:(\w+)["']\s+content=["']([\s\S]*?)["']/gi;
|
|
77
|
+
while ((m = twRe.exec(html)) !== null) {
|
|
78
|
+
result.twitter[m[1]] = m[2].trim();
|
|
79
|
+
}
|
|
80
|
+
// H1-H6
|
|
81
|
+
result.headings = { h1: [], h2: [], h3: [] };
|
|
82
|
+
for (const tag of ['h1', 'h2', 'h3']) {
|
|
83
|
+
const re = new RegExp(`<${tag}[^>]*>([\\s\\S]*?)<\\/${tag}>`, 'gi');
|
|
84
|
+
while ((m = re.exec(html)) !== null) {
|
|
85
|
+
const text = m[1].replace(/<[^>]+>/g, '').trim();
|
|
86
|
+
if (text) result.headings[tag].push(text);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Images without alt
|
|
90
|
+
const imgRe = /<img\s[^>]*>/gi;
|
|
91
|
+
result.imagesWithoutAlt = 0;
|
|
92
|
+
result.totalImages = 0;
|
|
93
|
+
while ((m = imgRe.exec(html)) !== null) {
|
|
94
|
+
result.totalImages++;
|
|
95
|
+
if (!/\salt=/.test(m[0]) || /\salt=["']\s*["']/.test(m[0])) {
|
|
96
|
+
result.imagesWithoutAlt++;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Schema.org
|
|
100
|
+
result.hasSchema = /<script\s+type=["']application\/ld\+json["']/.test(html) ||
|
|
101
|
+
/itemtype=["']https?:\/\/schema\.org/.test(html);
|
|
102
|
+
// Word count (basit)
|
|
103
|
+
const text = html.replace(/<script[\s\S]*?<\/script>/gi, '')
|
|
104
|
+
.replace(/<style[\s\S]*?<\/style>/gi, '')
|
|
105
|
+
.replace(/<[^>]+>/g, ' ')
|
|
106
|
+
.replace(/\s+/g, ' ').trim();
|
|
107
|
+
result.wordCount = text.split(/\s+/).filter(Boolean).length;
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function cmdAudit(args) {
|
|
112
|
+
const targetUrl = args[0];
|
|
113
|
+
if (!targetUrl) {
|
|
114
|
+
console.log(tui.C.red('\n Kullanım: natureco seo audit <url>\n'));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log('\n' + tui.styled(` 🔍 SEO Denetimi: ${targetUrl}`, { color: tui.PALETTE.primary, bold: true }));
|
|
119
|
+
console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
|
|
120
|
+
|
|
121
|
+
// Spinner göster
|
|
122
|
+
const spinner = new tui.Spinner('Sayfa yükleniyor', { style: 'dots' }).start();
|
|
123
|
+
let response;
|
|
124
|
+
try {
|
|
125
|
+
response = await fetchUrl(targetUrl);
|
|
126
|
+
} catch (e) {
|
|
127
|
+
spinner.stop(tui.C.red('✗ Hata: ' + e.message));
|
|
128
|
+
console.log('');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (response.statusCode !== 200) {
|
|
133
|
+
spinner.stop(tui.C.yellow(`⚠ HTTP ${response.statusCode} yanıtı alındı`));
|
|
134
|
+
} else {
|
|
135
|
+
spinner.stop(tui.C.green('✓ Sayfa yüklendi'));
|
|
136
|
+
}
|
|
137
|
+
console.log('');
|
|
138
|
+
|
|
139
|
+
const meta = extractMeta(response.body);
|
|
140
|
+
const issues = [];
|
|
141
|
+
const passes = [];
|
|
142
|
+
|
|
143
|
+
// Title
|
|
144
|
+
if (!meta.title) {
|
|
145
|
+
issues.push({ severity: 'high', msg: 'Title tag eksik' });
|
|
146
|
+
} else if (meta.title.length < 30) {
|
|
147
|
+
issues.push({ severity: 'medium', msg: `Title çok kısa (${meta.title.length} karakter, ideal: 50-60)` });
|
|
148
|
+
} else if (meta.title.length > 60) {
|
|
149
|
+
issues.push({ severity: 'medium', msg: `Title çok uzun (${meta.title.length} karakter, ideal: 50-60)` });
|
|
150
|
+
} else {
|
|
151
|
+
passes.push(`Title (${meta.title.length} karakter)`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Description
|
|
155
|
+
if (!meta.description) {
|
|
156
|
+
issues.push({ severity: 'high', msg: 'Meta description eksik' });
|
|
157
|
+
} else if (meta.description.length < 120) {
|
|
158
|
+
issues.push({ severity: 'low', msg: `Description kısa (${meta.description.length} karakter, ideal: 150-160)` });
|
|
159
|
+
} else if (meta.description.length > 160) {
|
|
160
|
+
issues.push({ severity: 'low', msg: `Description uzun (${meta.description.length} karakter, ideal: 150-160)` });
|
|
161
|
+
} else {
|
|
162
|
+
passes.push(`Description (${meta.description.length} karakter)`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Canonical
|
|
166
|
+
if (meta.canonical) passes.push('Canonical URL var');
|
|
167
|
+
else issues.push({ severity: 'medium', msg: 'Canonical URL tanımlı değil' });
|
|
168
|
+
|
|
169
|
+
// OG
|
|
170
|
+
if (Object.keys(meta.og).length > 0) passes.push(`Open Graph (${Object.keys(meta.og).length} tag)`);
|
|
171
|
+
else issues.push({ severity: 'low', msg: 'Open Graph tag yok (sosyal medya paylaşımı için)' });
|
|
172
|
+
|
|
173
|
+
// Twitter
|
|
174
|
+
if (Object.keys(meta.twitter).length > 0) passes.push(`Twitter Card (${Object.keys(meta.twitter).length} tag)`);
|
|
175
|
+
else issues.push({ severity: 'low', msg: 'Twitter Card tag yok' });
|
|
176
|
+
|
|
177
|
+
// H1
|
|
178
|
+
if (meta.headings.h1.length === 0) issues.push({ severity: 'high', msg: 'H1 tag eksik' });
|
|
179
|
+
else if (meta.headings.h1.length > 1) issues.push({ severity: 'medium', msg: `Birden fazla H1 var (${meta.headings.h1.length}, ideal: 1)` });
|
|
180
|
+
else passes.push(`H1 var: "${meta.headings.h1[0].slice(0, 50)}"`);
|
|
181
|
+
|
|
182
|
+
// Images
|
|
183
|
+
if (meta.totalImages > 0) {
|
|
184
|
+
if (meta.imagesWithoutAlt > 0) {
|
|
185
|
+
issues.push({ severity: 'medium', msg: `${meta.imagesWithoutAlt}/${meta.totalImages} image alt tag eksik` });
|
|
186
|
+
} else {
|
|
187
|
+
passes.push(`Tüm image'larda alt var (${meta.totalImages})`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Schema
|
|
192
|
+
if (meta.hasSchema) passes.push('Schema.org markup var');
|
|
193
|
+
else issues.push({ severity: 'low', msg: 'Schema.org markup yok (rich snippets için)' });
|
|
194
|
+
|
|
195
|
+
// Content
|
|
196
|
+
if (meta.wordCount < 300) issues.push({ severity: 'medium', msg: `İçerik kısa (${meta.wordCount} kelime, ideal: 600+)` });
|
|
197
|
+
else passes.push(`İçerik uzunluğu (${meta.wordCount} kelime)`);
|
|
198
|
+
|
|
199
|
+
// Sonuçları tablo halinde göster
|
|
200
|
+
console.log(tui.styled(' 📊 Sonuçlar', { color: tui.PALETTE.primary, bold: true }));
|
|
201
|
+
console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
|
|
202
|
+
|
|
203
|
+
// Geçenler
|
|
204
|
+
if (passes.length > 0) {
|
|
205
|
+
console.log('\n' + tui.styled(' ✅ Geçenler', { color: tui.PALETTE.success, bold: true }));
|
|
206
|
+
const passRows = passes.map((p, i) => ({
|
|
207
|
+
icon: tui.styled(' ✓ ', { bg: tui.PALETTE.success, color: '#000', bold: true }),
|
|
208
|
+
msg: p,
|
|
209
|
+
}));
|
|
210
|
+
console.log(tui.table(passRows, [
|
|
211
|
+
{ key: 'icon', label: ' ', minWidth: 5 },
|
|
212
|
+
{ key: 'msg', label: 'Kontrol', minWidth: 40, render: r => tui.C.text(r.msg) },
|
|
213
|
+
], { borderStyle: 'round', zebra: true }));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// İyileştirme alanları
|
|
217
|
+
if (issues.length > 0) {
|
|
218
|
+
console.log('\n' + tui.styled(' ⚠️ İyileştirme Alanları', { color: tui.PALETTE.warning, bold: true }));
|
|
219
|
+
const issueRows = issues.map(i => ({
|
|
220
|
+
icon: i.severity === 'high' ? tui.styled(' ✗ ', { bg: tui.PALETTE.danger, color: '#000', bold: true })
|
|
221
|
+
: i.severity === 'medium' ? tui.styled(' ⚠ ', { bg: tui.PALETTE.warning, color: '#000', bold: true })
|
|
222
|
+
: tui.styled(' ℹ ', { bg: tui.PALETTE.info, color: '#000', bold: true }),
|
|
223
|
+
msg: i.msg,
|
|
224
|
+
}));
|
|
225
|
+
console.log(tui.table(issueRows, [
|
|
226
|
+
{ key: 'icon', label: ' ', minWidth: 5 },
|
|
227
|
+
{ key: 'msg', label: 'Sorun', minWidth: 40, render: r => tui.C.text(r.msg) },
|
|
228
|
+
], { borderStyle: 'round', zebra: true }));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Skor (büyük, prominent)
|
|
232
|
+
const score = Math.max(0, Math.min(100, 100 - (issues.filter(i => i.severity === 'high').length * 15 + issues.filter(i => i.severity === 'medium').length * 7 + issues.filter(i => i.severity === 'low').length * 3)));
|
|
233
|
+
const scoreColor = score >= 80 ? tui.PALETTE.success : score >= 50 ? tui.PALETTE.warning : tui.PALETTE.danger;
|
|
234
|
+
const scoreGrade = score >= 80 ? '🟢 Mükemmel' : score >= 50 ? '🟡 İyi' : '🔴 Geliştirilmeli';
|
|
235
|
+
|
|
236
|
+
console.log('\n' + tui.styled(' ╭────────────────────────────────────────────────────╮', { color: tui.PALETTE.border }));
|
|
237
|
+
console.log(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted('SEO Skoru:') + ' ' +
|
|
238
|
+
tui.styled(String(score).padStart(3), { color: scoreColor, bold: true }) + tui.C.muted('/100 ') +
|
|
239
|
+
tui.styled(scoreGrade, { color: scoreColor }) + ' ' + tui.styled('│', { color: tui.PALETTE.border }));
|
|
240
|
+
console.log(tui.styled(' ╰────────────────────────────────────────────────────╯', { color: tui.PALETTE.border }));
|
|
241
|
+
console.log('');
|
|
242
|
+
|
|
243
|
+
audit.log(audit.ACTIONS.INFO, { source: 'seo', url: targetUrl, score, issues: issues.length });
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function seo(args) {
|
|
247
|
+
const [action, ...params] = args || [];
|
|
248
|
+
if (!action || action === 'help') {
|
|
249
|
+
console.log(chalk.yellow('\n Kullanım:'));
|
|
250
|
+
console.log(chalk.gray(' natureco seo audit <url> Tam SEO denetimi'));
|
|
251
|
+
console.log(chalk.gray(' natureco seo meta <url> Meta tag analizi'));
|
|
252
|
+
console.log(chalk.gray(' natureco seo speed <url> Hız ipuçları'));
|
|
253
|
+
console.log('');
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (action === 'audit') return cmdAudit(params);
|
|
257
|
+
if (action === 'meta') {
|
|
258
|
+
console.log(chalk.gray('\n Meta analizi audit\'in bir parçası olarak geliyor.\n'));
|
|
259
|
+
return cmdAudit(params);
|
|
260
|
+
}
|
|
261
|
+
if (action === 'speed') {
|
|
262
|
+
console.log(chalk.gray('\n Hız analizi: PageSpeed Insights API entegrasyonu eklenecek (Phase 7).\n'));
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
console.log(chalk.red(`\n Bilinmeyen: ${action}\n`));
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
module.exports = seo;
|
package/src/commands/sessions.js
CHANGED
|
File without changes
|
package/src/commands/setup.js
CHANGED
|
@@ -2,28 +2,147 @@ const chalk = require('chalk');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const os = require('os');
|
|
5
|
+
const readline = require('readline');
|
|
6
|
+
const inquirer = require('../utils/inquirer-wrapper');
|
|
7
|
+
const brand = require('../utils/branding');
|
|
8
|
+
const { COLORS, FULL_LOGO } = brand;
|
|
5
9
|
|
|
6
10
|
const BASE_DIR = path.join(os.homedir(), '.natureco');
|
|
7
11
|
const CONFIG_FILE = path.join(BASE_DIR, 'config.json');
|
|
8
12
|
|
|
9
13
|
const DIRS = ['sources', 'concepts', 'cache', 'skills', 'memory', 'sessions', 'backups'];
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
const PROVIDER_PRESETS = {
|
|
16
|
+
groq: { url: 'https://api.groq.com/openai/v1', model: 'llama-3.3-70b-versatile' },
|
|
17
|
+
openai: { url: 'https://api.openai.com/v1', model: 'gpt-4o' },
|
|
18
|
+
anthropic:{ url: 'https://api.anthropic.com', model: 'claude-sonnet-4-6' },
|
|
19
|
+
deepseek: { url: 'https://api.deepseek.com/v1', model: 'deepseek-chat' },
|
|
20
|
+
ollama: { url: 'http://localhost:11434/v1', model: 'llama3.3' },
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function rlQuestion(query) {
|
|
24
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
25
|
+
return new Promise(resolve => {
|
|
26
|
+
rl.question(query, answer => { rl.close(); resolve(answer.trim()); });
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getConfig() {
|
|
31
|
+
if (!fs.existsSync(CONFIG_FILE)) return {};
|
|
32
|
+
try { return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); }
|
|
33
|
+
catch { return {}; }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function saveConfig(data) {
|
|
37
|
+
if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
|
|
38
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), 'utf8');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function setup(params) {
|
|
12
42
|
try {
|
|
13
43
|
const [action] = params || [];
|
|
14
44
|
|
|
15
|
-
if (!action || action === '
|
|
45
|
+
if (!action || action === 'wizard') return await cmdWizard();
|
|
46
|
+
if (action === 'status') return cmdStatus();
|
|
16
47
|
if (action === 'config') return cmdConfig();
|
|
17
48
|
if (action === 'workspace') return cmdWorkspace();
|
|
18
49
|
if (action === 'dirs') return cmdDirs();
|
|
19
50
|
|
|
20
|
-
console.log(chalk.
|
|
21
|
-
console.log(chalk.gray('
|
|
51
|
+
console.log(chalk.yellow('\n Usage:'));
|
|
52
|
+
console.log(chalk.gray(' natureco setup Interactive setup wizard'));
|
|
53
|
+
console.log(chalk.gray(' natureco setup config Create default config'));
|
|
54
|
+
console.log(chalk.gray(' natureco setup workspace Create workspace directories'));
|
|
55
|
+
console.log(chalk.gray(' natureco setup dirs Create data directories'));
|
|
56
|
+
console.log(chalk.gray(' natureco setup status Show setup status\n'));
|
|
22
57
|
} catch (err) {
|
|
23
58
|
console.log(chalk.red(`\n Setup error: ${err.message}\n`));
|
|
24
59
|
}
|
|
25
60
|
}
|
|
26
61
|
|
|
62
|
+
async function cmdWizard() {
|
|
63
|
+
console.clear();
|
|
64
|
+
// Tam NatureCo logosu — brand kimliği
|
|
65
|
+
for (const line of FULL_LOGO) console.log(COLORS.primary(line));
|
|
66
|
+
console.log('');
|
|
67
|
+
console.log(COLORS.secondary.bold(' ⚡ Setup Wizard — 60 saniyede hazır'));
|
|
68
|
+
console.log(COLORS.muted(' Provider seç, API key gir, hemen başla.\n'));
|
|
69
|
+
|
|
70
|
+
// Ensure directories
|
|
71
|
+
if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
|
|
72
|
+
for (const dir of DIRS) {
|
|
73
|
+
const p = path.join(BASE_DIR, dir);
|
|
74
|
+
if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const cfg = getConfig();
|
|
78
|
+
|
|
79
|
+
// Step 1: Provider selection
|
|
80
|
+
console.log(chalk.white(' Step 1: Provider'));
|
|
81
|
+
console.log(chalk.gray(' ─────────────────────────────────────────────'));
|
|
82
|
+
const providerKeys = Object.keys(PROVIDER_PRESETS);
|
|
83
|
+
const { provider } = await inquirer.prompt([{
|
|
84
|
+
type: 'list',
|
|
85
|
+
name: 'provider',
|
|
86
|
+
message: ' AI Provider:',
|
|
87
|
+
choices: [
|
|
88
|
+
...providerKeys.map(k => ({
|
|
89
|
+
name: `${k.charAt(0).toUpperCase() + k.slice(1)} (${PROVIDER_PRESETS[k].model})`,
|
|
90
|
+
value: k,
|
|
91
|
+
})),
|
|
92
|
+
{ name: 'Custom URL', value: 'custom' },
|
|
93
|
+
],
|
|
94
|
+
}]);
|
|
95
|
+
|
|
96
|
+
let providerUrl, providerModel;
|
|
97
|
+
if (provider === 'custom') {
|
|
98
|
+
providerUrl = await rlQuestion(` Provider URL (${cfg.providerUrl || 'https://api.openai.com/v1'}): `);
|
|
99
|
+
providerModel = await rlQuestion(` Model (${cfg.providerModel || 'gpt-4o'}): `);
|
|
100
|
+
providerUrl = providerUrl || cfg.providerUrl || 'https://api.openai.com/v1';
|
|
101
|
+
providerModel = providerModel || cfg.providerModel || 'gpt-4o';
|
|
102
|
+
} else {
|
|
103
|
+
const preset = PROVIDER_PRESETS[provider];
|
|
104
|
+
providerUrl = preset.url;
|
|
105
|
+
providerModel = preset.model;
|
|
106
|
+
console.log(chalk.gray(` URL: ${providerUrl}`));
|
|
107
|
+
console.log(chalk.gray(` Model: ${providerModel}`));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Step 2: API Key
|
|
111
|
+
console.log('');
|
|
112
|
+
console.log(chalk.white(' Step 2: API Key'));
|
|
113
|
+
console.log(chalk.gray(' ─────────────────────────────────────────────'));
|
|
114
|
+
console.log(chalk.gray(' Get a key from: ') + chalk.cyan('developers.natureco.me'));
|
|
115
|
+
console.log(chalk.gray(' Or use your own provider API key.\n'));
|
|
116
|
+
|
|
117
|
+
const currentKey = cfg.providerApiKey || '';
|
|
118
|
+
const apiKey = await rlQuestion(` API Key ${currentKey ? '(leave blank to keep current)' : ''}: `);
|
|
119
|
+
if (apiKey) {
|
|
120
|
+
cfg.providerApiKey = apiKey;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Step 3: Save
|
|
124
|
+
cfg.providerUrl = providerUrl;
|
|
125
|
+
cfg.providerModel = providerModel;
|
|
126
|
+
cfg.setupCompleted = true;
|
|
127
|
+
cfg.updated = new Date().toISOString();
|
|
128
|
+
if (!cfg.created) cfg.created = new Date().toISOString();
|
|
129
|
+
if (!cfg.version) cfg.version = 1;
|
|
130
|
+
if (cfg.skills === undefined) cfg.skills = { enabled: true, list: [] };
|
|
131
|
+
if (cfg.mcpServers === undefined) cfg.mcpServers = {};
|
|
132
|
+
|
|
133
|
+
saveConfig(cfg);
|
|
134
|
+
|
|
135
|
+
console.log('');
|
|
136
|
+
console.log(chalk.green(' ✓ Setup complete!\n'));
|
|
137
|
+
console.log(chalk.white(' Config saved to: ') + chalk.gray(CONFIG_FILE));
|
|
138
|
+
console.log('');
|
|
139
|
+
console.log(chalk.white(' Next steps:'));
|
|
140
|
+
console.log(chalk.cyan(' natureco chat Start chatting'));
|
|
141
|
+
console.log(chalk.cyan(' natureco login Login with API key'));
|
|
142
|
+
console.log(chalk.cyan(' natureco help View all commands'));
|
|
143
|
+
console.log('');
|
|
144
|
+
}
|
|
145
|
+
|
|
27
146
|
function cmdStatus() {
|
|
28
147
|
console.log(chalk.cyan('\n Setup Status\n'));
|
|
29
148
|
|
|
@@ -33,6 +152,14 @@ function cmdStatus() {
|
|
|
33
152
|
console.log(chalk.white(' Config: ') + (configExists ? chalk.green('exists') : chalk.yellow('missing')));
|
|
34
153
|
console.log(chalk.white(' Directory: ') + (dirExists ? chalk.green('exists') : chalk.yellow('missing')));
|
|
35
154
|
|
|
155
|
+
if (configExists) {
|
|
156
|
+
const cfg = getConfig();
|
|
157
|
+
console.log(chalk.white(' Provider: ') + chalk.gray(cfg.providerUrl || 'not set'));
|
|
158
|
+
console.log(chalk.white(' Model: ') + chalk.gray(cfg.providerModel || 'not set'));
|
|
159
|
+
console.log(chalk.white(' API Key: ') + (cfg.providerApiKey ? chalk.green('set') : chalk.yellow('not set')));
|
|
160
|
+
console.log(chalk.white(' Setup: ') + (cfg.setupCompleted ? chalk.green('completed') : chalk.yellow('incomplete')));
|
|
161
|
+
}
|
|
162
|
+
|
|
36
163
|
if (dirExists) {
|
|
37
164
|
const existing = fs.readdirSync(BASE_DIR).filter(f => fs.statSync(path.join(BASE_DIR, f)).isDirectory());
|
|
38
165
|
const present = DIRS.filter(d => existing.includes(d));
|
package/src/commands/signal.js
CHANGED
|
File without changes
|
package/src/commands/skills.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const tui = require('../utils/tui');
|
|
2
3
|
const path = require('path');
|
|
3
4
|
const fs = require('fs');
|
|
4
5
|
const os = require('os');
|
|
5
6
|
const inquirer = require('../utils/inquirer-wrapper');
|
|
6
7
|
const { getSkills, installSkill, removeSkill, updateAllSkills, createSkillTemplate, getPopularSkills } = require('../utils/skills');
|
|
7
8
|
const { NatureCoError, SkillError, handleError } = require('../utils/errors');
|
|
9
|
+
const detector = require('../utils/pattern-detector');
|
|
10
|
+
const audit = require('../utils/audit');
|
|
8
11
|
|
|
9
12
|
async function skills(args) {
|
|
10
13
|
const [action, ...params] = args;
|
|
@@ -77,8 +80,40 @@ async function skills(args) {
|
|
|
77
80
|
return;
|
|
78
81
|
}
|
|
79
82
|
|
|
83
|
+
if (action === 'suggest' || action === 'proposals') {
|
|
84
|
+
await listProposals();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (action === 'accept') {
|
|
89
|
+
const proposalId = params[0];
|
|
90
|
+
if (!proposalId) {
|
|
91
|
+
console.log(chalk.red('\n❌ Kullanım: natureco skills accept <proposal-id>\n'));
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
await acceptProposalCommand(proposalId);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (action === 'reject') {
|
|
99
|
+
const proposalId = params[0];
|
|
100
|
+
if (!proposalId) {
|
|
101
|
+
console.log(chalk.red('\n❌ Kullanım: natureco skills reject <proposal-id>\n'));
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
detector.rejectProposal(proposalId);
|
|
105
|
+
console.log(chalk.green(`\n✅ Proposal reddedildi: ${proposalId}\n`));
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (action === 'forget') {
|
|
110
|
+
detector.reset();
|
|
111
|
+
console.log(chalk.yellow('\n🧹 Tüm pattern hafızası ve proposal\'lar silindi.\n'));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
80
115
|
console.log(chalk.red(`\n❌ Geçersiz action: ${action}\n`));
|
|
81
|
-
console.log(chalk.gray('Kullanım: natureco skills [list|install|remove|update|create|search|browse|info|check]\n'));
|
|
116
|
+
console.log(chalk.gray('Kullanım: natureco skills [list|install|remove|update|create|search|browse|info|check|suggest|accept|reject|forget]\n'));
|
|
82
117
|
process.exit(1);
|
|
83
118
|
}
|
|
84
119
|
|
|
@@ -330,4 +365,50 @@ async function checkSkills() {
|
|
|
330
365
|
}
|
|
331
366
|
}
|
|
332
367
|
|
|
368
|
+
async function listProposals() {
|
|
369
|
+
const proposals = detector.loadProposals();
|
|
370
|
+
const pending = proposals.filter(p => p.status === 'pending');
|
|
371
|
+
|
|
372
|
+
console.log('\n' + tui.styled(' 🧠 Self-Evolving Skill Proposals', { color: tui.PALETTE.primary, bold: true }));
|
|
373
|
+
console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
|
|
374
|
+
console.log(' ' + tui.C.muted('Kullanımın tekrar eden pattern\'lerinden otomatik skill önerileri.\n'));
|
|
375
|
+
|
|
376
|
+
if (pending.length === 0) {
|
|
377
|
+
console.log(' ' + tui.C.muted('Şu an öneri yok. Daha fazla tool çağrısı yap, sistem öğrensin.'));
|
|
378
|
+
console.log(' ' + tui.C.muted('Pattern\'leri sıfırla: ') + tui.C.brand('natureco skills forget\n'));
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const rows = pending.map(p => ({
|
|
383
|
+
name: p.suggestedName,
|
|
384
|
+
count: p.count + 'x',
|
|
385
|
+
pattern: p.pattern.length > 50 ? p.pattern.slice(0, 47) + '...' : p.pattern,
|
|
386
|
+
first: new Date(p.firstSeen).toLocaleString(),
|
|
387
|
+
id: p.id,
|
|
388
|
+
}));
|
|
389
|
+
|
|
390
|
+
console.log(tui.table(rows, [
|
|
391
|
+
{ key: 'name', label: 'Öneri', minWidth: 25, render: r => tui.styled(r.name, { color: tui.PALETTE.primary, bold: true }) },
|
|
392
|
+
{ key: 'count', label: 'Tekrar', minWidth: 7, render: r => tui.styled(r.count, { color: tui.PALETTE.accent, bold: true }) },
|
|
393
|
+
{ key: 'pattern', label: 'Pattern', minWidth: 30, render: r => tui.C.muted(r.pattern) },
|
|
394
|
+
{ key: 'first', label: 'İlk', minWidth: 18, render: r => tui.C.muted(r.first) },
|
|
395
|
+
], { borderStyle: 'round', zebra: true }));
|
|
396
|
+
|
|
397
|
+
console.log('\n ' + tui.C.muted('Kabul et: ') + tui.C.brand('natureco skills accept <id>'));
|
|
398
|
+
console.log(' ' + tui.C.muted('Reddet: ') + tui.C.brand('natureco skills reject <id>\n'));
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
async function acceptProposalCommand(proposalId) {
|
|
402
|
+
console.log(chalk.yellow('\n⏳ Skill oluşturuluyor...\n'));
|
|
403
|
+
const result = detector.acceptProposal(proposalId);
|
|
404
|
+
if (!result.success) {
|
|
405
|
+
console.log(chalk.red(`\n❌ ${result.reason}\n`));
|
|
406
|
+
process.exit(1);
|
|
407
|
+
}
|
|
408
|
+
console.log(chalk.green(`✅ Yeni skill oluşturuldu: ${result.skillName}\n`));
|
|
409
|
+
console.log(chalk.gray(` Yol: ${result.path}\n`));
|
|
410
|
+
console.log(chalk.gray(' SKILL.md dosyasını düzenleyerek özelleştirebilirsin.\n'));
|
|
411
|
+
audit.log(audit.ACTIONS.SKILL_AUTO, { proposalId, skillName: result.skillName });
|
|
412
|
+
}
|
|
413
|
+
|
|
333
414
|
module.exports = skills;
|
package/src/commands/slack.js
CHANGED
|
File without changes
|
package/src/commands/sms.js
CHANGED
|
File without changes
|
package/src/commands/status.js
CHANGED
|
File without changes
|
package/src/commands/system.js
CHANGED
|
File without changes
|
package/src/commands/tasks.js
CHANGED
|
File without changes
|