natureco-cli 4.8.4 → 4.9.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 +1 -1
- package/src/tools/macos.js +324 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "natureco-cli",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.9.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,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NatureCo CLI — Calendar/Reminders/Notes Tools (v4.9.0)
|
|
3
|
+
*
|
|
4
|
+
* macOS için AppleScript entegrasyonu.
|
|
5
|
+
* Cross-platform için fallback'ler.
|
|
6
|
+
*
|
|
7
|
+
* Önemli: macOS'ta Calendar/Reminders/Notes'a erişim için
|
|
8
|
+
* "Automation" izni gerekli. Sistem Preferences → Security →
|
|
9
|
+
* Automation → natureco → Calendar/Reminders/Notes → ON
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const { spawn } = require('child_process');
|
|
13
|
+
const os = require('os');
|
|
14
|
+
|
|
15
|
+
const IS_MAC = os.platform() === 'darwin';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* AppleScript çalıştır (macOS only)
|
|
19
|
+
*/
|
|
20
|
+
function runAppleScript(script) {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const proc = spawn('osascript', ['-e', script]);
|
|
23
|
+
let stdout = '';
|
|
24
|
+
let stderr = '';
|
|
25
|
+
proc.stdout.on('data', d => stdout += d);
|
|
26
|
+
proc.stderr.on('data', d => stderr += d);
|
|
27
|
+
proc.on('close', code => {
|
|
28
|
+
if (code === 0) resolve(stdout.trim());
|
|
29
|
+
else reject(new Error(stderr.trim() || `osascript exit ${code}`));
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Takvime etkinlik ekle (macOS Calendar)
|
|
36
|
+
* @param title - Etkinlik başlığı
|
|
37
|
+
* @param startDate - Başlangıç tarihi (ISO string veya "tomorrow 14:00")
|
|
38
|
+
* @param duration - Dakika cinsinden süre (default 60)
|
|
39
|
+
* @param calendar - Takvim adı (default: ilk takvim)
|
|
40
|
+
*/
|
|
41
|
+
async function calendarAdd({ title, startDate, duration = 60, calendar = null, notes = '', location = '' }) {
|
|
42
|
+
if (!IS_MAC) return { success: false, error: 'Calendar sadece macOS\'ta desteklenir' };
|
|
43
|
+
if (!title) return { success: false, error: 'title gerekli' };
|
|
44
|
+
|
|
45
|
+
// startDate parse — basit ISO string veya "now", "+1 hour"
|
|
46
|
+
let startScript;
|
|
47
|
+
if (startDate === 'now') startScript = 'current date';
|
|
48
|
+
else if (startDate.startsWith('+')) {
|
|
49
|
+
// "+1 hour", "+2 days"
|
|
50
|
+
const match = startDate.match(/\+(\d+)\s*(hour|day|minute)/i);
|
|
51
|
+
if (match) {
|
|
52
|
+
const n = match[1];
|
|
53
|
+
const unit = match[2].toLowerCase() + 's';
|
|
54
|
+
startScript = `(current date) + ${n} * ${unit}`;
|
|
55
|
+
} else startScript = 'current date';
|
|
56
|
+
} else {
|
|
57
|
+
startScript = `date "${startDate}"`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Calendar adını bul
|
|
61
|
+
let calScript;
|
|
62
|
+
if (calendar) {
|
|
63
|
+
calScript = `calendar "${calendar}"`;
|
|
64
|
+
} else {
|
|
65
|
+
calScript = `first calendar whose writable is true`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const script = `
|
|
69
|
+
tell application "Calendar"
|
|
70
|
+
set targetCal to ${calScript}
|
|
71
|
+
set startDate to ${startScript}
|
|
72
|
+
set endDate to startDate + (${duration} * minutes)
|
|
73
|
+
set newEvent to make new event at end of events of targetCal with properties {summary:"${title.replace(/"/g, '\\"')}", start date:startDate, end date:endDate${location ? `, location:"${location.replace(/"/g, '\\"')}"` : ''}${notes ? `, description:"${notes.replace(/"/g, '\\"')}"` : ''}}
|
|
74
|
+
save
|
|
75
|
+
return id of newEvent
|
|
76
|
+
end tell
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const eventId = await runAppleScript(script);
|
|
81
|
+
return {
|
|
82
|
+
success: true,
|
|
83
|
+
eventId,
|
|
84
|
+
title,
|
|
85
|
+
startDate,
|
|
86
|
+
duration,
|
|
87
|
+
message: `Takvime eklendi: "${title}" (${startDate} + ${duration}dk)`,
|
|
88
|
+
};
|
|
89
|
+
} catch (e) {
|
|
90
|
+
if (e.message.includes('-1728') || e.message.includes('not authorized') || e.message.includes('-1743')) {
|
|
91
|
+
return {
|
|
92
|
+
success: false,
|
|
93
|
+
error: 'Calendar erişim izni yok.\n\nİzin vermek için:\n1. System Preferences → Security & Privacy → Privacy → Automation\n2. natureco (veya Terminal) → Calendar → ON\n3. Tekrar dene',
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return { success: false, error: e.message };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Reminders'a hatırlatıcı ekle (macOS Reminders)
|
|
102
|
+
*/
|
|
103
|
+
async function reminderAdd({ title, dueDate = null, list = null, notes = '' }) {
|
|
104
|
+
if (!IS_MAC) return { success: false, error: 'Reminders sadece macOS\'ta desteklenir' };
|
|
105
|
+
if (!title) return { success: false, error: 'title gerekli' };
|
|
106
|
+
|
|
107
|
+
let listScript;
|
|
108
|
+
if (list) listScript = `list "${list}"`;
|
|
109
|
+
else listScript = `default list`;
|
|
110
|
+
|
|
111
|
+
const dueScript = dueDate
|
|
112
|
+
? (dueDate === 'today' ? 'current date' : `date "${dueDate}"`)
|
|
113
|
+
: 'missing value';
|
|
114
|
+
|
|
115
|
+
const script = `
|
|
116
|
+
tell application "Reminders"
|
|
117
|
+
set targetList to ${listScript}
|
|
118
|
+
set newReminder to make new reminder at end of targetList with properties {name:"${title.replace(/"/g, '\\"')}"${notes ? `, body:"${notes.replace(/"/g, '\\"')}"` : ''}}
|
|
119
|
+
${dueDate ? `set due date of newReminder to ${dueScript}` : ''}
|
|
120
|
+
save
|
|
121
|
+
return id of newReminder
|
|
122
|
+
end tell
|
|
123
|
+
`;
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const reminderId = await runAppleScript(script);
|
|
127
|
+
return { success: true, reminderId, title, dueDate, message: `Hatırlatıcı eklendi: "${title}"` };
|
|
128
|
+
} catch (e) {
|
|
129
|
+
if (e.message.includes('-1743') || e.message.includes('not authorized')) {
|
|
130
|
+
return {
|
|
131
|
+
success: false,
|
|
132
|
+
error: 'Reminders erişim izni yok. System Preferences → Security → Automation → Reminders → ON',
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return { success: false, error: e.message };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Apple Notes'a not ekle
|
|
141
|
+
*/
|
|
142
|
+
async function notesAdd({ title, content, folder = null }) {
|
|
143
|
+
if (!IS_MAC) return { success: false, error: 'Notes sadece macOS\'ta desteklenir' };
|
|
144
|
+
if (!title || !content) return { success: false, error: 'title ve content gerekli' };
|
|
145
|
+
|
|
146
|
+
const folderScript = folder ? `folder "${folder}"` : 'default folder';
|
|
147
|
+
|
|
148
|
+
// AppleScript'te yeni note oluşturma
|
|
149
|
+
const script = `
|
|
150
|
+
tell application "Notes"
|
|
151
|
+
set targetFolder to ${folderScript}
|
|
152
|
+
set newNote to make new note at targetFolder with properties {name:"${title.replace(/"/g, '\\"')}", body:"${content.replace(/"/g, '\\"').replace(/\n/g, '\\n')}"}
|
|
153
|
+
save
|
|
154
|
+
return name of newNote
|
|
155
|
+
end tell
|
|
156
|
+
`;
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
const noteName = await runAppleScript(script);
|
|
160
|
+
return { success: true, noteName, title, message: `Not eklendi: "${title}"` };
|
|
161
|
+
} catch (e) {
|
|
162
|
+
if (e.message.includes('-1743') || e.message.includes('not authorized')) {
|
|
163
|
+
return {
|
|
164
|
+
success: false,
|
|
165
|
+
error: 'Notes erişim izni yok. System Preferences → Security → Automation → Notes → ON',
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return { success: false, error: e.message };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* macOS bildirimi göster (Notification Center)
|
|
174
|
+
*/
|
|
175
|
+
async function macNotify({ title, message, subtitle = '' }) {
|
|
176
|
+
if (!IS_MAC) return { success: false, error: 'Bildirim macOS\'a özel' };
|
|
177
|
+
if (!title || !message) return { success: false, error: 'title ve message gerekli' };
|
|
178
|
+
|
|
179
|
+
const script = `display notification "${message.replace(/"/g, '\\"')}" with title "${title.replace(/"/g, '\\"')}"${subtitle ? ` subtitle "${subtitle.replace(/"/g, '\\"')}"` : ''}`;
|
|
180
|
+
try {
|
|
181
|
+
await runAppleScript(script);
|
|
182
|
+
return { success: true, message: `Bildirim gönderildi: ${title}` };
|
|
183
|
+
} catch (e) {
|
|
184
|
+
return { success: false, error: e.message };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* macOS uygulaması aç
|
|
190
|
+
*/
|
|
191
|
+
async function macAppOpen({ appName }) {
|
|
192
|
+
if (!IS_MAC) return { success: false, error: 'Bu komut macOS\'a özel' };
|
|
193
|
+
if (!appName) return { success: false, error: 'appName gerekli' };
|
|
194
|
+
|
|
195
|
+
return new Promise((resolve) => {
|
|
196
|
+
const proc = spawn('open', ['-a', appName]);
|
|
197
|
+
proc.on('close', (code) => {
|
|
198
|
+
if (code === 0) resolve({ success: true, message: `"${appName}" açıldı` });
|
|
199
|
+
else resolve({ success: false, error: `Uygulama açılamadı: ${appName}` });
|
|
200
|
+
});
|
|
201
|
+
proc.on('error', (e) => resolve({ success: false, error: e.message }));
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* macOS uygulaması kapat
|
|
207
|
+
*/
|
|
208
|
+
async function macAppQuit({ appName }) {
|
|
209
|
+
if (!IS_MAC) return { success: false, error: 'Bu komut macOS\'a özel' };
|
|
210
|
+
if (!appName) return { success: false, error: 'appName gerekli' };
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
await runAppleScript(`tell application "${appName}" to quit`);
|
|
214
|
+
return { success: true, message: `"${appName}" kapatıldı` };
|
|
215
|
+
} catch (e) {
|
|
216
|
+
return { success: false, error: e.message };
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Tool definitions
|
|
221
|
+
module.exports = {
|
|
222
|
+
// Tek tek export (tools.js uyumlu)
|
|
223
|
+
calendar_add: {
|
|
224
|
+
name: 'calendar_add',
|
|
225
|
+
description: 'macOS Calendar\'a etkinlik ekle. "Yarın saat 14:00 toplantı ekle" gibi istekler için.',
|
|
226
|
+
inputSchema: {
|
|
227
|
+
type: 'object',
|
|
228
|
+
properties: {
|
|
229
|
+
title: { type: 'string', description: 'Etkinlik başlığı' },
|
|
230
|
+
startDate: { type: 'string', description: 'Başlangıç tarihi (ISO: 2026-06-23 14:00, veya "now", "+1 hour", "+1 day")' },
|
|
231
|
+
duration: { type: 'number', description: 'Dakika cinsinden süre (default 60)' },
|
|
232
|
+
calendar: { type: 'string', description: 'Takvim adı (default: ilk yazılabilir takvim)' },
|
|
233
|
+
notes: { type: 'string', description: 'Ek not' },
|
|
234
|
+
location: { type: 'string', description: 'Konum' },
|
|
235
|
+
},
|
|
236
|
+
required: ['title'],
|
|
237
|
+
},
|
|
238
|
+
async execute(params) {
|
|
239
|
+
return await calendarAdd(params);
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
reminder_add: {
|
|
244
|
+
name: 'reminder_add',
|
|
245
|
+
description: 'macOS Reminders\'a hatırlatıcı ekle. "Yarın süt al" gibi.',
|
|
246
|
+
inputSchema: {
|
|
247
|
+
type: 'object',
|
|
248
|
+
properties: {
|
|
249
|
+
title: { type: 'string', description: 'Hatırlatıcı başlığı' },
|
|
250
|
+
dueDate: { type: 'string', description: 'Son tarih (ISO string veya "today")' },
|
|
251
|
+
list: { type: 'string', description: 'Liste adı (default: default list)' },
|
|
252
|
+
notes: { type: 'string', description: 'Ek not' },
|
|
253
|
+
},
|
|
254
|
+
required: ['title'],
|
|
255
|
+
},
|
|
256
|
+
async execute(params) {
|
|
257
|
+
return await reminderAdd(params);
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
notes_add: {
|
|
262
|
+
name: 'notes_add',
|
|
263
|
+
description: 'Apple Notes\'a not ekle.',
|
|
264
|
+
inputSchema: {
|
|
265
|
+
type: 'object',
|
|
266
|
+
properties: {
|
|
267
|
+
title: { type: 'string', description: 'Not başlığı' },
|
|
268
|
+
content: { type: 'string', description: 'Not içeriği' },
|
|
269
|
+
folder: { type: 'string', description: 'Klasör adı (default: default folder)' },
|
|
270
|
+
},
|
|
271
|
+
required: ['title', 'content'],
|
|
272
|
+
},
|
|
273
|
+
async execute(params) {
|
|
274
|
+
return await notesAdd(params);
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
mac_notify: {
|
|
279
|
+
name: 'mac_notify',
|
|
280
|
+
description: 'macOS Notification Center\'da bildirim göster.',
|
|
281
|
+
inputSchema: {
|
|
282
|
+
type: 'object',
|
|
283
|
+
properties: {
|
|
284
|
+
title: { type: 'string', description: 'Bildirim başlığı' },
|
|
285
|
+
message: { type: 'string', description: 'Bildirim mesajı' },
|
|
286
|
+
subtitle: { type: 'string', description: 'Alt başlık' },
|
|
287
|
+
},
|
|
288
|
+
required: ['title', 'message'],
|
|
289
|
+
},
|
|
290
|
+
async execute(params) {
|
|
291
|
+
return await macNotify(params);
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
mac_app_open: {
|
|
296
|
+
name: 'mac_app_open',
|
|
297
|
+
description: 'macOS uygulaması aç (Finder, Safari, Slack, vs.).',
|
|
298
|
+
inputSchema: {
|
|
299
|
+
type: 'object',
|
|
300
|
+
properties: {
|
|
301
|
+
appName: { type: 'string', description: 'Uygulama adı (Finder, Safari, Slack, Spotify...)' },
|
|
302
|
+
},
|
|
303
|
+
required: ['appName'],
|
|
304
|
+
},
|
|
305
|
+
async execute(params) {
|
|
306
|
+
return await macAppOpen(params);
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
mac_app_quit: {
|
|
311
|
+
name: 'mac_app_quit',
|
|
312
|
+
description: 'macOS uygulamasını kapat.',
|
|
313
|
+
inputSchema: {
|
|
314
|
+
type: 'object',
|
|
315
|
+
properties: {
|
|
316
|
+
appName: { type: 'string', description: 'Uygulama adı' },
|
|
317
|
+
},
|
|
318
|
+
required: ['appName'],
|
|
319
|
+
},
|
|
320
|
+
async execute(params) {
|
|
321
|
+
return await macAppQuit(params);
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
};
|