natureco-cli 1.0.1 → 1.0.5

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,109 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const os = require('os');
4
+
5
+ function getSessionsDir(botId) {
6
+ return path.join(os.homedir(), '.natureco', 'history', botId, 'sessions');
7
+ }
8
+
9
+ function ensureSessionsDir(botId) {
10
+ const dir = getSessionsDir(botId);
11
+ if (!fs.existsSync(dir)) {
12
+ fs.mkdirSync(dir, { recursive: true });
13
+ }
14
+ }
15
+
16
+ function createSession(botId, botName) {
17
+ ensureSessionsDir(botId);
18
+
19
+ const sessionId = Date.now().toString(36) + Math.random().toString(36).slice(2, 7);
20
+ const session = {
21
+ id: sessionId,
22
+ botId,
23
+ botName,
24
+ createdAt: new Date().toISOString(),
25
+ messages: [],
26
+ };
27
+
28
+ saveSession(botId, session);
29
+ return session;
30
+ }
31
+
32
+ function saveSession(botId, session) {
33
+ ensureSessionsDir(botId);
34
+ const sessionFile = path.join(getSessionsDir(botId), `${session.id}.json`);
35
+ fs.writeFileSync(sessionFile, JSON.stringify(session, null, 2), 'utf-8');
36
+ }
37
+
38
+ function loadSession(botId, sessionId) {
39
+ const sessionFile = path.join(getSessionsDir(botId), `${sessionId}.json`);
40
+ if (!fs.existsSync(sessionFile)) {
41
+ return null;
42
+ }
43
+ try {
44
+ const data = fs.readFileSync(sessionFile, 'utf-8');
45
+ return JSON.parse(data);
46
+ } catch {
47
+ return null;
48
+ }
49
+ }
50
+
51
+ function getLatestSession(botId) {
52
+ ensureSessionsDir(botId);
53
+ const sessionsDir = getSessionsDir(botId);
54
+ const files = fs.readdirSync(sessionsDir).filter(f => f.endsWith('.json'));
55
+
56
+ if (files.length === 0) return null;
57
+
58
+ // Sort by modification time
59
+ const sorted = files
60
+ .map(f => ({
61
+ file: f,
62
+ mtime: fs.statSync(path.join(sessionsDir, f)).mtime.getTime(),
63
+ }))
64
+ .sort((a, b) => b.mtime - a.mtime);
65
+
66
+ const latestFile = sorted[0].file;
67
+ const sessionId = path.basename(latestFile, '.json');
68
+ return loadSession(botId, sessionId);
69
+ }
70
+
71
+ function listSessions(botId) {
72
+ ensureSessionsDir(botId);
73
+ const sessionsDir = getSessionsDir(botId);
74
+ const files = fs.readdirSync(sessionsDir).filter(f => f.endsWith('.json'));
75
+
76
+ const sessions = files.map(f => {
77
+ const sessionId = path.basename(f, '.json');
78
+ const session = loadSession(botId, sessionId);
79
+ return session;
80
+ }).filter(Boolean);
81
+
82
+ // Sort by creation time
83
+ sessions.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
84
+
85
+ return sessions;
86
+ }
87
+
88
+ function addMessageToSession(botId, sessionId, userMessage, botReply) {
89
+ const session = loadSession(botId, sessionId);
90
+ if (!session) return false;
91
+
92
+ session.messages.push({
93
+ user: userMessage,
94
+ bot: botReply,
95
+ timestamp: new Date().toISOString(),
96
+ });
97
+
98
+ saveSession(botId, session);
99
+ return true;
100
+ }
101
+
102
+ module.exports = {
103
+ createSession,
104
+ saveSession,
105
+ loadSession,
106
+ getLatestSession,
107
+ listSessions,
108
+ addMessageToSession,
109
+ };
@@ -10,7 +10,7 @@ const PROJECT_SKILLS_DIR = path.join(process.cwd(), '.natureco', 'skills');
10
10
 
11
11
  // Skill metadata parser
12
12
  function parseSkillMetadata(content) {
13
- const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
13
+ const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
14
14
  if (!frontmatterMatch) return null;
15
15
 
16
16
  const frontmatter = frontmatterMatch[1];
@@ -144,14 +144,32 @@ function getSkills() {
144
144
  return skills;
145
145
  }
146
146
 
147
- // Install skill from NatureHub
147
+ // Install skill from NatureHub or ClawHub
148
148
  async function installSkill(slug) {
149
- const url = `https://natureco.me/hub/skills/${slug}/SKILL.md`;
149
+ let url;
150
+ let actualSlug = slug;
151
+
152
+ // ClawHub format: clawhub:github
153
+ if (slug.startsWith('clawhub:')) {
154
+ actualSlug = slug.replace('clawhub:', '');
155
+ url = `https://clawhub.ai/skills/${actualSlug}/SKILL.md`;
156
+ }
157
+ // Direct URL
158
+ else if (slug.startsWith('http://') || slug.startsWith('https://')) {
159
+ url = slug;
160
+ // Extract slug from URL
161
+ const urlParts = slug.split('/');
162
+ actualSlug = urlParts[urlParts.length - 2] || 'custom-skill';
163
+ }
164
+ // NatureHub (default)
165
+ else {
166
+ url = `https://natureco.me/hub/skills/${slug}/SKILL.md`;
167
+ }
150
168
 
151
169
  try {
152
170
  const response = await fetch(url);
153
171
  if (!response.ok) {
154
- throw new Error(`Skill bulunamadı: ${slug}`);
172
+ throw new Error(`Skill bulunamadı: ${actualSlug}`);
155
173
  }
156
174
 
157
175
  const content = await response.text();
@@ -172,7 +190,7 @@ async function installSkill(slug) {
172
190
  fs.mkdirSync(USER_SKILLS_DIR, { recursive: true });
173
191
  }
174
192
 
175
- const skillDir = path.join(USER_SKILLS_DIR, slug);
193
+ const skillDir = path.join(USER_SKILLS_DIR, actualSlug);
176
194
  if (!fs.existsSync(skillDir)) {
177
195
  fs.mkdirSync(skillDir, { recursive: true });
178
196
  }
@@ -256,6 +274,23 @@ Bu skill ${name} işlemlerini yapar.
256
274
  return path.join(skillDir, 'SKILL.md');
257
275
  }
258
276
 
277
+ // Popular skills list
278
+ const POPULAR_SKILLS = [
279
+ { slug: 'github', name: 'GitHub', description: 'GitHub repo işlemleri' },
280
+ { slug: 'filesystem', name: 'Filesystem', description: 'Dosya sistemi işlemleri' },
281
+ { slug: 'web-search', name: 'Web Search', description: 'Web arama' },
282
+ { slug: 'summarize', name: 'Summarize', description: 'Metin özetleme' },
283
+ { slug: 'code-review', name: 'Code Review', description: 'Kod inceleme' },
284
+ { slug: 'translate', name: 'Translate', description: 'Çeviri' },
285
+ { slug: 'weather', name: 'Weather', description: 'Hava durumu' },
286
+ { slug: 'calendar', name: 'Calendar', description: 'Takvim yönetimi' },
287
+ ];
288
+
289
+ // Get popular skills
290
+ function getPopularSkills() {
291
+ return POPULAR_SKILLS;
292
+ }
293
+
259
294
  // Get skill prompt injection content
260
295
  function getSkillPrompts() {
261
296
  const skills = getSkills();
@@ -282,4 +317,5 @@ module.exports = {
282
317
  createSkillTemplate,
283
318
  getSkillPrompts,
284
319
  checkSkillRequirements,
320
+ getPopularSkills,
285
321
  };