apexbot 1.0.2 → 1.0.4
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/dist/agent/agentManager.js +52 -5
- package/dist/agent/toolExecutor.js +144 -0
- package/dist/channels/channelManager.js +3 -1
- package/dist/cli/index.js +114 -0
- package/dist/gateway/index.js +62 -8
- package/dist/skills/index.js +212 -0
- package/dist/skills/obsidian.js +440 -0
- package/dist/skills/reminder.js +430 -0
- package/dist/skills/system.js +360 -0
- package/dist/skills/weather.js +144 -0
- package/dist/tools/datetime.js +188 -0
- package/dist/tools/file.js +352 -0
- package/dist/tools/index.js +111 -0
- package/dist/tools/loader.js +66 -0
- package/dist/tools/math.js +248 -0
- package/dist/tools/shell.js +104 -0
- package/dist/tools/web.js +197 -0
- package/package.json +2 -2
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* System Info Skill
|
|
4
|
+
*
|
|
5
|
+
* Get system information, resource usage, and process management.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
const os = __importStar(require("os"));
|
|
42
|
+
const child_process_1 = require("child_process");
|
|
43
|
+
const util_1 = require("util");
|
|
44
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
45
|
+
const systemInfoTool = {
|
|
46
|
+
definition: {
|
|
47
|
+
name: 'system_info',
|
|
48
|
+
description: 'Get system information: OS, CPU, memory, disk, network.',
|
|
49
|
+
category: 'automation',
|
|
50
|
+
parameters: [
|
|
51
|
+
{
|
|
52
|
+
name: 'type',
|
|
53
|
+
type: 'string',
|
|
54
|
+
description: 'Info type: all, os, cpu, memory, disk, network',
|
|
55
|
+
required: false,
|
|
56
|
+
default: 'all',
|
|
57
|
+
enum: ['all', 'os', 'cpu', 'memory', 'disk', 'network'],
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
returns: 'System information',
|
|
61
|
+
},
|
|
62
|
+
async execute(params, context) {
|
|
63
|
+
const { type = 'all' } = params;
|
|
64
|
+
try {
|
|
65
|
+
const result = {};
|
|
66
|
+
if (type === 'all' || type === 'os') {
|
|
67
|
+
result.os = {
|
|
68
|
+
platform: os.platform(),
|
|
69
|
+
type: os.type(),
|
|
70
|
+
release: os.release(),
|
|
71
|
+
arch: os.arch(),
|
|
72
|
+
hostname: os.hostname(),
|
|
73
|
+
uptime: Math.floor(os.uptime() / 3600) + ' hours',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (type === 'all' || type === 'cpu') {
|
|
77
|
+
const cpus = os.cpus();
|
|
78
|
+
result.cpu = {
|
|
79
|
+
model: cpus[0]?.model || 'Unknown',
|
|
80
|
+
cores: cpus.length,
|
|
81
|
+
speed: cpus[0]?.speed + ' MHz',
|
|
82
|
+
loadAvg: os.loadavg().map(l => l.toFixed(2)),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (type === 'all' || type === 'memory') {
|
|
86
|
+
const totalMem = os.totalmem();
|
|
87
|
+
const freeMem = os.freemem();
|
|
88
|
+
const usedMem = totalMem - freeMem;
|
|
89
|
+
result.memory = {
|
|
90
|
+
total: (totalMem / 1024 / 1024 / 1024).toFixed(2) + ' GB',
|
|
91
|
+
used: (usedMem / 1024 / 1024 / 1024).toFixed(2) + ' GB',
|
|
92
|
+
free: (freeMem / 1024 / 1024 / 1024).toFixed(2) + ' GB',
|
|
93
|
+
usage: ((usedMem / totalMem) * 100).toFixed(1) + '%',
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (type === 'all' || type === 'disk') {
|
|
97
|
+
try {
|
|
98
|
+
if (os.platform() === 'win32') {
|
|
99
|
+
const { stdout } = await execAsync('wmic logicaldisk get size,freespace,caption');
|
|
100
|
+
const lines = stdout.trim().split('\n').slice(1);
|
|
101
|
+
result.disk = lines.map(line => {
|
|
102
|
+
const parts = line.trim().split(/\s+/);
|
|
103
|
+
if (parts.length >= 3) {
|
|
104
|
+
const free = parseInt(parts[1]) || 0;
|
|
105
|
+
const total = parseInt(parts[2]) || 1;
|
|
106
|
+
return {
|
|
107
|
+
drive: parts[0],
|
|
108
|
+
total: (total / 1024 / 1024 / 1024).toFixed(2) + ' GB',
|
|
109
|
+
free: (free / 1024 / 1024 / 1024).toFixed(2) + ' GB',
|
|
110
|
+
usage: (((total - free) / total) * 100).toFixed(1) + '%',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}).filter(Boolean);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
const { stdout } = await execAsync('df -h /');
|
|
118
|
+
const lines = stdout.trim().split('\n');
|
|
119
|
+
if (lines.length > 1) {
|
|
120
|
+
const parts = lines[1].split(/\s+/);
|
|
121
|
+
result.disk = [{
|
|
122
|
+
mount: parts[5],
|
|
123
|
+
total: parts[1],
|
|
124
|
+
used: parts[2],
|
|
125
|
+
free: parts[3],
|
|
126
|
+
usage: parts[4],
|
|
127
|
+
}];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
result.disk = { error: 'Could not get disk info' };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (type === 'all' || type === 'network') {
|
|
136
|
+
const interfaces = os.networkInterfaces();
|
|
137
|
+
result.network = Object.entries(interfaces)
|
|
138
|
+
.filter(([name]) => !name.includes('Loopback') && !name.startsWith('lo'))
|
|
139
|
+
.map(([name, addrs]) => ({
|
|
140
|
+
name,
|
|
141
|
+
addresses: addrs?.filter(a => a.family === 'IPv4').map(a => a.address) || [],
|
|
142
|
+
}))
|
|
143
|
+
.filter(n => n.addresses.length > 0);
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
success: true,
|
|
147
|
+
data: result,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
return { success: false, error: error.message };
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
const processListTool = {
|
|
156
|
+
definition: {
|
|
157
|
+
name: 'process_list',
|
|
158
|
+
description: 'List running processes.',
|
|
159
|
+
category: 'automation',
|
|
160
|
+
parameters: [
|
|
161
|
+
{
|
|
162
|
+
name: 'filter',
|
|
163
|
+
type: 'string',
|
|
164
|
+
description: 'Filter by process name',
|
|
165
|
+
required: false,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: 'limit',
|
|
169
|
+
type: 'number',
|
|
170
|
+
description: 'Max results (default: 20)',
|
|
171
|
+
required: false,
|
|
172
|
+
default: 20,
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
returns: 'List of processes',
|
|
176
|
+
},
|
|
177
|
+
async execute(params, context) {
|
|
178
|
+
const { filter, limit = 20 } = params;
|
|
179
|
+
try {
|
|
180
|
+
let processes = [];
|
|
181
|
+
if (os.platform() === 'win32') {
|
|
182
|
+
const { stdout } = await execAsync('tasklist /fo csv /nh');
|
|
183
|
+
const lines = stdout.trim().split('\n');
|
|
184
|
+
for (const line of lines) {
|
|
185
|
+
const match = line.match(/"([^"]+)","(\d+)","([^"]+)","(\d+)","([^"]+)"/);
|
|
186
|
+
if (match) {
|
|
187
|
+
processes.push({
|
|
188
|
+
name: match[1],
|
|
189
|
+
pid: match[2],
|
|
190
|
+
session: match[3],
|
|
191
|
+
memory: match[5],
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
const { stdout } = await execAsync('ps aux --no-headers');
|
|
198
|
+
const lines = stdout.trim().split('\n');
|
|
199
|
+
for (const line of lines) {
|
|
200
|
+
const parts = line.trim().split(/\s+/);
|
|
201
|
+
if (parts.length >= 11) {
|
|
202
|
+
processes.push({
|
|
203
|
+
user: parts[0],
|
|
204
|
+
pid: parts[1],
|
|
205
|
+
cpu: parts[2] + '%',
|
|
206
|
+
memory: parts[3] + '%',
|
|
207
|
+
name: parts.slice(10).join(' '),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// Filter
|
|
213
|
+
if (filter) {
|
|
214
|
+
processes = processes.filter(p => p.name.toLowerCase().includes(filter.toLowerCase()));
|
|
215
|
+
}
|
|
216
|
+
// Limit
|
|
217
|
+
processes = processes.slice(0, limit);
|
|
218
|
+
return {
|
|
219
|
+
success: true,
|
|
220
|
+
data: {
|
|
221
|
+
processes,
|
|
222
|
+
count: processes.length,
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
return { success: false, error: error.message };
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
const killProcessTool = {
|
|
232
|
+
definition: {
|
|
233
|
+
name: 'process_kill',
|
|
234
|
+
description: 'Kill a process by PID or name.',
|
|
235
|
+
category: 'automation',
|
|
236
|
+
parameters: [
|
|
237
|
+
{
|
|
238
|
+
name: 'target',
|
|
239
|
+
type: 'string',
|
|
240
|
+
description: 'Process PID or name',
|
|
241
|
+
required: true,
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
returns: 'Kill confirmation',
|
|
245
|
+
},
|
|
246
|
+
async execute(params, context) {
|
|
247
|
+
const { target } = params;
|
|
248
|
+
if (!target) {
|
|
249
|
+
return { success: false, error: 'Target is required' };
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
const isPid = /^\d+$/.test(target);
|
|
253
|
+
if (os.platform() === 'win32') {
|
|
254
|
+
const cmd = isPid
|
|
255
|
+
? `taskkill /PID ${target} /F`
|
|
256
|
+
: `taskkill /IM "${target}" /F`;
|
|
257
|
+
await execAsync(cmd);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
const cmd = isPid
|
|
261
|
+
? `kill -9 ${target}`
|
|
262
|
+
: `pkill -9 "${target}"`;
|
|
263
|
+
await execAsync(cmd);
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
success: true,
|
|
267
|
+
data: {
|
|
268
|
+
target,
|
|
269
|
+
killed: true,
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
return { success: false, error: error.message };
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
const clipboardTool = {
|
|
279
|
+
definition: {
|
|
280
|
+
name: 'clipboard',
|
|
281
|
+
description: 'Read or write system clipboard.',
|
|
282
|
+
category: 'automation',
|
|
283
|
+
parameters: [
|
|
284
|
+
{
|
|
285
|
+
name: 'action',
|
|
286
|
+
type: 'string',
|
|
287
|
+
description: 'Action: read, write',
|
|
288
|
+
required: true,
|
|
289
|
+
enum: ['read', 'write'],
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
name: 'content',
|
|
293
|
+
type: 'string',
|
|
294
|
+
description: 'Content to write (for write action)',
|
|
295
|
+
required: false,
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
returns: 'Clipboard content or confirmation',
|
|
299
|
+
},
|
|
300
|
+
async execute(params, context) {
|
|
301
|
+
const { action, content } = params;
|
|
302
|
+
try {
|
|
303
|
+
if (action === 'read') {
|
|
304
|
+
let text;
|
|
305
|
+
if (os.platform() === 'win32') {
|
|
306
|
+
const { stdout } = await execAsync('powershell -command "Get-Clipboard"');
|
|
307
|
+
text = stdout.trim();
|
|
308
|
+
}
|
|
309
|
+
else if (os.platform() === 'darwin') {
|
|
310
|
+
const { stdout } = await execAsync('pbpaste');
|
|
311
|
+
text = stdout;
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
const { stdout } = await execAsync('xclip -selection clipboard -o');
|
|
315
|
+
text = stdout;
|
|
316
|
+
}
|
|
317
|
+
return {
|
|
318
|
+
success: true,
|
|
319
|
+
data: { content: text },
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
else if (action === 'write') {
|
|
323
|
+
if (!content) {
|
|
324
|
+
return { success: false, error: 'Content is required for write action' };
|
|
325
|
+
}
|
|
326
|
+
if (os.platform() === 'win32') {
|
|
327
|
+
await execAsync(`powershell -command "Set-Clipboard -Value '${content.replace(/'/g, "''")}'"`);
|
|
328
|
+
}
|
|
329
|
+
else if (os.platform() === 'darwin') {
|
|
330
|
+
await execAsync(`echo "${content.replace(/"/g, '\\"')}" | pbcopy`);
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
await execAsync(`echo "${content.replace(/"/g, '\\"')}" | xclip -selection clipboard`);
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
success: true,
|
|
337
|
+
data: { written: true, length: content.length },
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
return { success: false, error: 'Invalid action' };
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
return { success: false, error: error.message };
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
};
|
|
347
|
+
const manifest = {
|
|
348
|
+
name: 'system',
|
|
349
|
+
version: '1.0.0',
|
|
350
|
+
description: 'System information and process management',
|
|
351
|
+
category: 'automation',
|
|
352
|
+
icon: 'computer',
|
|
353
|
+
tools: ['system_info', 'process_list', 'process_kill', 'clipboard'],
|
|
354
|
+
config: [],
|
|
355
|
+
};
|
|
356
|
+
const systemSkill = {
|
|
357
|
+
manifest,
|
|
358
|
+
tools: [systemInfoTool, processListTool, killProcessTool, clipboardTool],
|
|
359
|
+
};
|
|
360
|
+
exports.default = systemSkill;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Weather Skill
|
|
4
|
+
*
|
|
5
|
+
* Get current weather and forecasts using Open-Meteo API (free, no API key required).
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const weatherTool = {
|
|
9
|
+
definition: {
|
|
10
|
+
name: 'weather',
|
|
11
|
+
description: 'Get current weather and forecast for a location.',
|
|
12
|
+
category: 'productivity',
|
|
13
|
+
parameters: [
|
|
14
|
+
{
|
|
15
|
+
name: 'location',
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'City name or coordinates (lat,lon)',
|
|
18
|
+
required: true,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'days',
|
|
22
|
+
type: 'number',
|
|
23
|
+
description: 'Forecast days (1-7)',
|
|
24
|
+
required: false,
|
|
25
|
+
default: 1,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
returns: 'Weather data',
|
|
29
|
+
examples: [
|
|
30
|
+
'weather({ location: "London" })',
|
|
31
|
+
'weather({ location: "New York", days: 3 })',
|
|
32
|
+
'weather({ location: "48.8566,2.3522" })',
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
async execute(params, context) {
|
|
36
|
+
const { location, days = 1 } = params;
|
|
37
|
+
if (!location) {
|
|
38
|
+
return { success: false, error: 'Location is required' };
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
// Check if location is coordinates
|
|
42
|
+
let lat, lon, locationName;
|
|
43
|
+
if (location.includes(',')) {
|
|
44
|
+
const [latStr, lonStr] = location.split(',');
|
|
45
|
+
lat = parseFloat(latStr.trim());
|
|
46
|
+
lon = parseFloat(lonStr.trim());
|
|
47
|
+
locationName = `${lat}, ${lon}`;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// Geocode the location
|
|
51
|
+
const geoUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(location)}&count=1`;
|
|
52
|
+
const geoResponse = await fetch(geoUrl);
|
|
53
|
+
const geoData = await geoResponse.json();
|
|
54
|
+
if (!geoData.results || geoData.results.length === 0) {
|
|
55
|
+
return { success: false, error: `Location not found: ${location}` };
|
|
56
|
+
}
|
|
57
|
+
const result = geoData.results[0];
|
|
58
|
+
lat = result.latitude;
|
|
59
|
+
lon = result.longitude;
|
|
60
|
+
locationName = `${result.name}, ${result.country}`;
|
|
61
|
+
}
|
|
62
|
+
// Get weather data
|
|
63
|
+
const weatherUrl = `https://api.open-meteo.com/v1/forecast?` +
|
|
64
|
+
`latitude=${lat}&longitude=${lon}` +
|
|
65
|
+
`¤t=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m,wind_direction_10m` +
|
|
66
|
+
`&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum,wind_speed_10m_max` +
|
|
67
|
+
`&forecast_days=${Math.min(days, 7)}` +
|
|
68
|
+
`&timezone=auto`;
|
|
69
|
+
const weatherResponse = await fetch(weatherUrl);
|
|
70
|
+
const weatherData = await weatherResponse.json();
|
|
71
|
+
// Weather code descriptions
|
|
72
|
+
const weatherCodes = {
|
|
73
|
+
0: 'Clear sky',
|
|
74
|
+
1: 'Mainly clear',
|
|
75
|
+
2: 'Partly cloudy',
|
|
76
|
+
3: 'Overcast',
|
|
77
|
+
45: 'Foggy',
|
|
78
|
+
48: 'Depositing rime fog',
|
|
79
|
+
51: 'Light drizzle',
|
|
80
|
+
53: 'Moderate drizzle',
|
|
81
|
+
55: 'Dense drizzle',
|
|
82
|
+
61: 'Slight rain',
|
|
83
|
+
63: 'Moderate rain',
|
|
84
|
+
65: 'Heavy rain',
|
|
85
|
+
71: 'Slight snow',
|
|
86
|
+
73: 'Moderate snow',
|
|
87
|
+
75: 'Heavy snow',
|
|
88
|
+
80: 'Slight rain showers',
|
|
89
|
+
81: 'Moderate rain showers',
|
|
90
|
+
82: 'Violent rain showers',
|
|
91
|
+
95: 'Thunderstorm',
|
|
92
|
+
96: 'Thunderstorm with slight hail',
|
|
93
|
+
99: 'Thunderstorm with heavy hail',
|
|
94
|
+
};
|
|
95
|
+
const current = {
|
|
96
|
+
temperature: weatherData.current.temperature_2m,
|
|
97
|
+
feelsLike: weatherData.current.apparent_temperature,
|
|
98
|
+
humidity: weatherData.current.relative_humidity_2m,
|
|
99
|
+
windSpeed: weatherData.current.wind_speed_10m,
|
|
100
|
+
windDirection: weatherData.current.wind_direction_10m,
|
|
101
|
+
condition: weatherCodes[weatherData.current.weather_code] || 'Unknown',
|
|
102
|
+
};
|
|
103
|
+
const forecast = weatherData.daily.time.map((date, i) => ({
|
|
104
|
+
date,
|
|
105
|
+
tempMax: weatherData.daily.temperature_2m_max[i],
|
|
106
|
+
tempMin: weatherData.daily.temperature_2m_min[i],
|
|
107
|
+
precipitation: weatherData.daily.precipitation_sum[i],
|
|
108
|
+
windSpeed: weatherData.daily.wind_speed_10m_max[i],
|
|
109
|
+
condition: weatherCodes[weatherData.daily.weather_code[i]] || 'Unknown',
|
|
110
|
+
}));
|
|
111
|
+
return {
|
|
112
|
+
success: true,
|
|
113
|
+
data: {
|
|
114
|
+
location: locationName,
|
|
115
|
+
coordinates: { lat, lon },
|
|
116
|
+
current,
|
|
117
|
+
forecast,
|
|
118
|
+
units: {
|
|
119
|
+
temperature: 'C',
|
|
120
|
+
wind: 'km/h',
|
|
121
|
+
precipitation: 'mm',
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
return { success: false, error: error.message };
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
const manifest = {
|
|
132
|
+
name: 'weather',
|
|
133
|
+
version: '1.0.0',
|
|
134
|
+
description: 'Get current weather and forecasts',
|
|
135
|
+
category: 'productivity',
|
|
136
|
+
icon: 'cloud',
|
|
137
|
+
tools: ['weather'],
|
|
138
|
+
config: [],
|
|
139
|
+
};
|
|
140
|
+
const weatherSkill = {
|
|
141
|
+
manifest,
|
|
142
|
+
tools: [weatherTool],
|
|
143
|
+
};
|
|
144
|
+
exports.default = weatherSkill;
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* DateTime Tool
|
|
4
|
+
*
|
|
5
|
+
* Get current time, convert timezones, calculate dates.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.registerDateTimeTools = registerDateTimeTools;
|
|
9
|
+
const index_1 = require("./index");
|
|
10
|
+
const dateTimeTool = {
|
|
11
|
+
definition: {
|
|
12
|
+
name: 'datetime',
|
|
13
|
+
description: 'Get current date/time, convert timezones, or calculate dates.',
|
|
14
|
+
category: 'core',
|
|
15
|
+
parameters: [
|
|
16
|
+
{
|
|
17
|
+
name: 'action',
|
|
18
|
+
type: 'string',
|
|
19
|
+
description: 'Action: now, convert, add, diff',
|
|
20
|
+
required: false,
|
|
21
|
+
default: 'now',
|
|
22
|
+
enum: ['now', 'convert', 'add', 'diff'],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'timezone',
|
|
26
|
+
type: 'string',
|
|
27
|
+
description: 'Timezone (e.g., America/New_York, Europe/London)',
|
|
28
|
+
required: false,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'date',
|
|
32
|
+
type: 'string',
|
|
33
|
+
description: 'Input date (ISO format or natural)',
|
|
34
|
+
required: false,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'amount',
|
|
38
|
+
type: 'number',
|
|
39
|
+
description: 'Amount to add (for add action)',
|
|
40
|
+
required: false,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'unit',
|
|
44
|
+
type: 'string',
|
|
45
|
+
description: 'Unit for add action: days, hours, minutes, weeks, months',
|
|
46
|
+
required: false,
|
|
47
|
+
enum: ['days', 'hours', 'minutes', 'weeks', 'months', 'years'],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'date2',
|
|
51
|
+
type: 'string',
|
|
52
|
+
description: 'Second date for diff action',
|
|
53
|
+
required: false,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
returns: 'Date/time information',
|
|
57
|
+
examples: [
|
|
58
|
+
'datetime({ action: "now" })',
|
|
59
|
+
'datetime({ action: "now", timezone: "Asia/Tokyo" })',
|
|
60
|
+
'datetime({ action: "add", date: "2024-01-01", amount: 7, unit: "days" })',
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
async execute(params, context) {
|
|
64
|
+
const { action = 'now', timezone, date, amount, unit, date2 } = params;
|
|
65
|
+
try {
|
|
66
|
+
switch (action) {
|
|
67
|
+
case 'now': {
|
|
68
|
+
const now = new Date();
|
|
69
|
+
const options = {
|
|
70
|
+
year: 'numeric',
|
|
71
|
+
month: 'long',
|
|
72
|
+
day: 'numeric',
|
|
73
|
+
hour: '2-digit',
|
|
74
|
+
minute: '2-digit',
|
|
75
|
+
second: '2-digit',
|
|
76
|
+
weekday: 'long',
|
|
77
|
+
timeZoneName: 'short',
|
|
78
|
+
};
|
|
79
|
+
if (timezone) {
|
|
80
|
+
options.timeZone = timezone;
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
success: true,
|
|
84
|
+
data: {
|
|
85
|
+
iso: now.toISOString(),
|
|
86
|
+
unix: Math.floor(now.getTime() / 1000),
|
|
87
|
+
formatted: now.toLocaleString('en-US', options),
|
|
88
|
+
timezone: timezone || Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
89
|
+
date: now.toLocaleDateString('en-US', timezone ? { timeZone: timezone } : {}),
|
|
90
|
+
time: now.toLocaleTimeString('en-US', timezone ? { timeZone: timezone } : {}),
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
case 'convert': {
|
|
95
|
+
if (!date || !timezone) {
|
|
96
|
+
return { success: false, error: 'Date and timezone required for convert' };
|
|
97
|
+
}
|
|
98
|
+
const inputDate = new Date(date);
|
|
99
|
+
const options = {
|
|
100
|
+
year: 'numeric',
|
|
101
|
+
month: 'long',
|
|
102
|
+
day: 'numeric',
|
|
103
|
+
hour: '2-digit',
|
|
104
|
+
minute: '2-digit',
|
|
105
|
+
second: '2-digit',
|
|
106
|
+
timeZone: timezone,
|
|
107
|
+
timeZoneName: 'short',
|
|
108
|
+
};
|
|
109
|
+
return {
|
|
110
|
+
success: true,
|
|
111
|
+
data: {
|
|
112
|
+
original: date,
|
|
113
|
+
converted: inputDate.toLocaleString('en-US', options),
|
|
114
|
+
timezone,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
case 'add': {
|
|
119
|
+
if (!amount || !unit) {
|
|
120
|
+
return { success: false, error: 'Amount and unit required for add' };
|
|
121
|
+
}
|
|
122
|
+
const inputDate = date ? new Date(date) : new Date();
|
|
123
|
+
const result = new Date(inputDate);
|
|
124
|
+
switch (unit) {
|
|
125
|
+
case 'minutes':
|
|
126
|
+
result.setMinutes(result.getMinutes() + amount);
|
|
127
|
+
break;
|
|
128
|
+
case 'hours':
|
|
129
|
+
result.setHours(result.getHours() + amount);
|
|
130
|
+
break;
|
|
131
|
+
case 'days':
|
|
132
|
+
result.setDate(result.getDate() + amount);
|
|
133
|
+
break;
|
|
134
|
+
case 'weeks':
|
|
135
|
+
result.setDate(result.getDate() + amount * 7);
|
|
136
|
+
break;
|
|
137
|
+
case 'months':
|
|
138
|
+
result.setMonth(result.getMonth() + amount);
|
|
139
|
+
break;
|
|
140
|
+
case 'years':
|
|
141
|
+
result.setFullYear(result.getFullYear() + amount);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
success: true,
|
|
146
|
+
data: {
|
|
147
|
+
original: inputDate.toISOString(),
|
|
148
|
+
result: result.toISOString(),
|
|
149
|
+
added: `${amount} ${unit}`,
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
case 'diff': {
|
|
154
|
+
if (!date || !date2) {
|
|
155
|
+
return { success: false, error: 'Two dates required for diff' };
|
|
156
|
+
}
|
|
157
|
+
const d1 = new Date(date);
|
|
158
|
+
const d2 = new Date(date2);
|
|
159
|
+
const diffMs = Math.abs(d2.getTime() - d1.getTime());
|
|
160
|
+
return {
|
|
161
|
+
success: true,
|
|
162
|
+
data: {
|
|
163
|
+
date1: d1.toISOString(),
|
|
164
|
+
date2: d2.toISOString(),
|
|
165
|
+
difference: {
|
|
166
|
+
milliseconds: diffMs,
|
|
167
|
+
seconds: Math.floor(diffMs / 1000),
|
|
168
|
+
minutes: Math.floor(diffMs / (1000 * 60)),
|
|
169
|
+
hours: Math.floor(diffMs / (1000 * 60 * 60)),
|
|
170
|
+
days: Math.floor(diffMs / (1000 * 60 * 60 * 24)),
|
|
171
|
+
weeks: Math.floor(diffMs / (1000 * 60 * 60 * 24 * 7)),
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
default:
|
|
177
|
+
return { success: false, error: `Unknown action: ${action}` };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
return { success: false, error: error.message };
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
function registerDateTimeTools() {
|
|
186
|
+
index_1.toolRegistry.register(dateTimeTool);
|
|
187
|
+
}
|
|
188
|
+
exports.default = dateTimeTool;
|