@patrick-rodgers/cron-claude 0.1.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/LICENSE +21 -0
- package/README.md +401 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +296 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +61 -0
- package/dist/config.js.map +1 -0
- package/dist/executor.d.ts +19 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +234 -0
- package/dist/executor.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +42 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +178 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-server.d.ts +7 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +580 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/notifier.d.ts +17 -0
- package/dist/notifier.d.ts.map +1 -0
- package/dist/notifier.js +48 -0
- package/dist/notifier.js.map +1 -0
- package/dist/scheduler.d.ts +46 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +230 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/install.ps1 +93 -0
- package/package.json +52 -0
- package/uninstall.ps1 +59 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* CLI interface for cron-claude
|
|
5
|
+
* Manage scheduled Claude tasks
|
|
6
|
+
*/
|
|
7
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
const commander_1 = require("commander");
|
|
12
|
+
const fs_1 = require("fs");
|
|
13
|
+
const path_1 = require("path");
|
|
14
|
+
const gray_matter_1 = __importDefault(require("gray-matter"));
|
|
15
|
+
const scheduler_js_1 = require("./scheduler.js");
|
|
16
|
+
const executor_js_1 = require("./executor.js");
|
|
17
|
+
const logger_js_1 = require("./logger.js");
|
|
18
|
+
const config_js_1 = require("./config.js");
|
|
19
|
+
const child_process_1 = require("child_process");
|
|
20
|
+
const program = new commander_1.Command();
|
|
21
|
+
// Get project root (assuming CLI is in dist/)
|
|
22
|
+
const PROJECT_ROOT = (0, path_1.resolve)(__dirname, '..');
|
|
23
|
+
const TASKS_DIR = (0, path_1.join)(PROJECT_ROOT, 'tasks');
|
|
24
|
+
// Ensure tasks directory exists
|
|
25
|
+
if (!(0, fs_1.existsSync)(TASKS_DIR)) {
|
|
26
|
+
(0, fs_1.mkdirSync)(TASKS_DIR, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get all task files
|
|
30
|
+
*/
|
|
31
|
+
function getTaskFiles() {
|
|
32
|
+
try {
|
|
33
|
+
return (0, fs_1.readdirSync)(TASKS_DIR).filter((f) => f.endsWith('.md'));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parse task file
|
|
41
|
+
*/
|
|
42
|
+
function parseTask(filename) {
|
|
43
|
+
const filePath = (0, path_1.join)(TASKS_DIR, filename);
|
|
44
|
+
const content = (0, fs_1.readFileSync)(filePath, 'utf-8');
|
|
45
|
+
const parsed = (0, gray_matter_1.default)(content);
|
|
46
|
+
return { filePath, ...parsed.data, instructions: parsed.content };
|
|
47
|
+
}
|
|
48
|
+
program
|
|
49
|
+
.name('cron-claude')
|
|
50
|
+
.description('Manage scheduled Claude tasks (cron jobs for Claude)')
|
|
51
|
+
.version('0.1.0');
|
|
52
|
+
/**
|
|
53
|
+
* Create a new task
|
|
54
|
+
*/
|
|
55
|
+
program
|
|
56
|
+
.command('create')
|
|
57
|
+
.description('Create a new scheduled task')
|
|
58
|
+
.option('-i, --interactive', 'Interactive mode (default)', true)
|
|
59
|
+
.action(async (options) => {
|
|
60
|
+
console.log('Creating new scheduled task...\n');
|
|
61
|
+
// TODO: Add interactive prompts
|
|
62
|
+
// For now, create a template
|
|
63
|
+
const taskId = `task-${Date.now()}`;
|
|
64
|
+
const template = `---
|
|
65
|
+
id: ${taskId}
|
|
66
|
+
schedule: "0 9 * * *" # Every day at 9 AM
|
|
67
|
+
invocation: cli # or 'api'
|
|
68
|
+
notifications:
|
|
69
|
+
toast: true
|
|
70
|
+
enabled: true
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
# Task Instructions
|
|
74
|
+
|
|
75
|
+
Write your instructions for Claude here.
|
|
76
|
+
|
|
77
|
+
## Example
|
|
78
|
+
- Check email
|
|
79
|
+
- Summarize important messages
|
|
80
|
+
- Create a daily report
|
|
81
|
+
`;
|
|
82
|
+
const filename = `${taskId}.md`;
|
|
83
|
+
const filePath = (0, path_1.join)(TASKS_DIR, filename);
|
|
84
|
+
(0, fs_1.writeFileSync)(filePath, template, 'utf-8');
|
|
85
|
+
console.log(`✓ Task template created: ${filename}`);
|
|
86
|
+
console.log(` Location: ${filePath}`);
|
|
87
|
+
console.log('\nNext steps:');
|
|
88
|
+
console.log('1. Edit the task file to add your instructions');
|
|
89
|
+
console.log('2. Run: cron-claude register ' + taskId);
|
|
90
|
+
});
|
|
91
|
+
/**
|
|
92
|
+
* Register a task with Task Scheduler
|
|
93
|
+
*/
|
|
94
|
+
program
|
|
95
|
+
.command('register <task-id>')
|
|
96
|
+
.description('Register a task with Windows Task Scheduler')
|
|
97
|
+
.action((taskId) => {
|
|
98
|
+
try {
|
|
99
|
+
const filename = `${taskId}.md`;
|
|
100
|
+
const filePath = (0, path_1.join)(TASKS_DIR, filename);
|
|
101
|
+
if (!(0, fs_1.existsSync)(filePath)) {
|
|
102
|
+
console.error(`Error: Task file not found: ${filename}`);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
const task = parseTask(filename);
|
|
106
|
+
if (!task.schedule) {
|
|
107
|
+
console.error('Error: Task must have a schedule defined');
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
(0, scheduler_js_1.registerTask)(taskId, filePath, task.schedule, PROJECT_ROOT);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error('Error registering task:', error);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
/**
|
|
118
|
+
* Unregister a task
|
|
119
|
+
*/
|
|
120
|
+
program
|
|
121
|
+
.command('unregister <task-id>')
|
|
122
|
+
.alias('delete')
|
|
123
|
+
.description('Unregister a task from Windows Task Scheduler')
|
|
124
|
+
.action((taskId) => {
|
|
125
|
+
try {
|
|
126
|
+
(0, scheduler_js_1.unregisterTask)(taskId);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
console.error('Error unregistering task:', error);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
/**
|
|
134
|
+
* List all tasks
|
|
135
|
+
*/
|
|
136
|
+
program
|
|
137
|
+
.command('list')
|
|
138
|
+
.description('List all scheduled tasks')
|
|
139
|
+
.action(() => {
|
|
140
|
+
const files = getTaskFiles();
|
|
141
|
+
if (files.length === 0) {
|
|
142
|
+
console.log('No tasks found. Create one with: cron-claude create');
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
console.log('Scheduled Tasks:\n');
|
|
146
|
+
files.forEach((file) => {
|
|
147
|
+
try {
|
|
148
|
+
const task = parseTask(file);
|
|
149
|
+
const status = (0, scheduler_js_1.getTaskStatus)(task.id);
|
|
150
|
+
console.log(`📋 ${task.id}`);
|
|
151
|
+
console.log(` Schedule: ${task.schedule}`);
|
|
152
|
+
console.log(` Method: ${task.invocation}`);
|
|
153
|
+
console.log(` Enabled: ${task.enabled ? '✓' : '✗'} (file)`);
|
|
154
|
+
if (status.exists) {
|
|
155
|
+
console.log(` Registered: ✓`);
|
|
156
|
+
console.log(` Status: ${status.enabled ? 'Enabled' : 'Disabled'}`);
|
|
157
|
+
if (status.lastRunTime) {
|
|
158
|
+
console.log(` Last run: ${status.lastRunTime}`);
|
|
159
|
+
}
|
|
160
|
+
if (status.nextRunTime) {
|
|
161
|
+
console.log(` Next run: ${status.nextRunTime}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
console.log(` Registered: ✗ (run 'cron-claude register ${task.id}')`);
|
|
166
|
+
}
|
|
167
|
+
console.log('');
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
console.error(`Error parsing ${file}:`, error);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
/**
|
|
175
|
+
* Enable a task
|
|
176
|
+
*/
|
|
177
|
+
program
|
|
178
|
+
.command('enable <task-id>')
|
|
179
|
+
.description('Enable a task in Windows Task Scheduler')
|
|
180
|
+
.action((taskId) => {
|
|
181
|
+
try {
|
|
182
|
+
(0, scheduler_js_1.enableTask)(taskId);
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
console.error('Error enabling task:', error);
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
/**
|
|
190
|
+
* Disable a task
|
|
191
|
+
*/
|
|
192
|
+
program
|
|
193
|
+
.command('disable <task-id>')
|
|
194
|
+
.description('Disable a task in Windows Task Scheduler')
|
|
195
|
+
.action((taskId) => {
|
|
196
|
+
try {
|
|
197
|
+
(0, scheduler_js_1.disableTask)(taskId);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
console.error('Error disabling task:', error);
|
|
201
|
+
process.exit(1);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
/**
|
|
205
|
+
* Manually run a task
|
|
206
|
+
*/
|
|
207
|
+
program
|
|
208
|
+
.command('run <task-id>')
|
|
209
|
+
.description('Manually execute a task now')
|
|
210
|
+
.action(async (taskId) => {
|
|
211
|
+
try {
|
|
212
|
+
const filename = `${taskId}.md`;
|
|
213
|
+
const filePath = (0, path_1.join)(TASKS_DIR, filename);
|
|
214
|
+
if (!(0, fs_1.existsSync)(filePath)) {
|
|
215
|
+
console.error(`Error: Task file not found: ${filename}`);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
console.log(`Executing task: ${taskId}...\n`);
|
|
219
|
+
await (0, executor_js_1.executeTask)(filePath);
|
|
220
|
+
console.log('\n✓ Task execution completed');
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
console.error('Error executing task:', error);
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
/**
|
|
228
|
+
* View task logs
|
|
229
|
+
*/
|
|
230
|
+
program
|
|
231
|
+
.command('logs <task-id>')
|
|
232
|
+
.description('View execution logs for a task')
|
|
233
|
+
.action((taskId) => {
|
|
234
|
+
try {
|
|
235
|
+
// Query memory skill for logs
|
|
236
|
+
const result = (0, child_process_1.execSync)(`odsp-memory recall --category=cron-task "${taskId}"`, {
|
|
237
|
+
encoding: 'utf-8',
|
|
238
|
+
});
|
|
239
|
+
console.log(result);
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
console.error('Error fetching logs:', error);
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
/**
|
|
247
|
+
* Verify a log signature
|
|
248
|
+
*/
|
|
249
|
+
program
|
|
250
|
+
.command('verify <log-file>')
|
|
251
|
+
.description('Verify the signature of a log file')
|
|
252
|
+
.action((logFile) => {
|
|
253
|
+
try {
|
|
254
|
+
const content = (0, fs_1.readFileSync)(logFile, 'utf-8');
|
|
255
|
+
const result = (0, logger_js_1.verifyLogFile)(content);
|
|
256
|
+
if (result.valid) {
|
|
257
|
+
console.log('✓ Signature is valid - log has not been tampered with');
|
|
258
|
+
if (result.log) {
|
|
259
|
+
console.log(`\nTask: ${result.log.taskId}`);
|
|
260
|
+
console.log(`Execution: ${result.log.executionId}`);
|
|
261
|
+
console.log(`Status: ${result.log.status}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
console.error('✗ Signature verification failed!');
|
|
266
|
+
console.error(` ${result.error}`);
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
console.error('Error verifying log:', error);
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
/**
|
|
276
|
+
* Show system status
|
|
277
|
+
*/
|
|
278
|
+
program
|
|
279
|
+
.command('status')
|
|
280
|
+
.description('Show cron-claude system status')
|
|
281
|
+
.action(() => {
|
|
282
|
+
const config = (0, config_js_1.loadConfig)();
|
|
283
|
+
const taskCount = getTaskFiles().length;
|
|
284
|
+
const { getConfigDir } = require('./config.js');
|
|
285
|
+
console.log('Cron-Claude System Status\n');
|
|
286
|
+
console.log(`Version: 0.1.0`);
|
|
287
|
+
console.log(`Config directory: ${getConfigDir()}`);
|
|
288
|
+
console.log(`Tasks directory: ${TASKS_DIR}`);
|
|
289
|
+
console.log(`Total tasks: ${taskCount}`);
|
|
290
|
+
console.log(`Secret key: ${config.secretKey ? '✓ Configured' : '✗ Not configured'}`);
|
|
291
|
+
console.log(`\nNode version: ${process.version}`);
|
|
292
|
+
console.log(`Platform: ${process.platform}`);
|
|
293
|
+
});
|
|
294
|
+
// Parse arguments and execute
|
|
295
|
+
program.parse();
|
|
296
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for cron-claude
|
|
3
|
+
* Handles secret key generation and storage
|
|
4
|
+
*/
|
|
5
|
+
interface Config {
|
|
6
|
+
secretKey: string;
|
|
7
|
+
version: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Load or create configuration
|
|
11
|
+
*/
|
|
12
|
+
export declare function loadConfig(): Config;
|
|
13
|
+
/**
|
|
14
|
+
* Get the secret key for HMAC signing
|
|
15
|
+
*/
|
|
16
|
+
export declare function getSecretKey(): string;
|
|
17
|
+
/**
|
|
18
|
+
* Get config directory path
|
|
19
|
+
*/
|
|
20
|
+
export declare function getConfigDir(): string;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,UAAU,MAAM;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAkBD;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAkBnC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAGrC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration management for cron-claude
|
|
4
|
+
* Handles secret key generation and storage
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.loadConfig = loadConfig;
|
|
8
|
+
exports.getSecretKey = getSecretKey;
|
|
9
|
+
exports.getConfigDir = getConfigDir;
|
|
10
|
+
const crypto_1 = require("crypto");
|
|
11
|
+
const fs_1 = require("fs");
|
|
12
|
+
const path_1 = require("path");
|
|
13
|
+
const os_1 = require("os");
|
|
14
|
+
const CONFIG_DIR = (0, path_1.join)((0, os_1.homedir)(), '.cron-claude');
|
|
15
|
+
const CONFIG_FILE = (0, path_1.join)(CONFIG_DIR, 'config.json');
|
|
16
|
+
/**
|
|
17
|
+
* Ensure config directory exists
|
|
18
|
+
*/
|
|
19
|
+
function ensureConfigDir() {
|
|
20
|
+
if (!(0, fs_1.existsSync)(CONFIG_DIR)) {
|
|
21
|
+
(0, fs_1.mkdirSync)(CONFIG_DIR, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Generate a new secret key for HMAC signing
|
|
26
|
+
*/
|
|
27
|
+
function generateSecretKey() {
|
|
28
|
+
return (0, crypto_1.randomBytes)(32).toString('hex');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Load or create configuration
|
|
32
|
+
*/
|
|
33
|
+
function loadConfig() {
|
|
34
|
+
ensureConfigDir();
|
|
35
|
+
if ((0, fs_1.existsSync)(CONFIG_FILE)) {
|
|
36
|
+
const data = (0, fs_1.readFileSync)(CONFIG_FILE, 'utf-8');
|
|
37
|
+
return JSON.parse(data);
|
|
38
|
+
}
|
|
39
|
+
// Create new config with generated secret key
|
|
40
|
+
const config = {
|
|
41
|
+
secretKey: generateSecretKey(),
|
|
42
|
+
version: '0.1.0',
|
|
43
|
+
};
|
|
44
|
+
(0, fs_1.writeFileSync)(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
|
|
45
|
+
console.log('Generated new secret key for log signing');
|
|
46
|
+
return config;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get the secret key for HMAC signing
|
|
50
|
+
*/
|
|
51
|
+
function getSecretKey() {
|
|
52
|
+
const config = loadConfig();
|
|
53
|
+
return config.secretKey;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get config directory path
|
|
57
|
+
*/
|
|
58
|
+
function getConfigDir() {
|
|
59
|
+
return CONFIG_DIR;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAkCH,gCAkBC;AAKD,oCAGC;AAKD,oCAEC;AAjED,mCAAqC;AACrC,2BAAwE;AACxE,+BAA4B;AAC5B,2BAA6B;AAE7B,MAAM,UAAU,GAAG,IAAA,WAAI,EAAC,IAAA,YAAO,GAAE,EAAE,cAAc,CAAC,CAAC;AACnD,MAAM,WAAW,GAAG,IAAA,WAAI,EAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAOpD;;GAEG;AACH,SAAS,eAAe;IACtB,IAAI,CAAC,IAAA,eAAU,EAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,IAAA,cAAS,EAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB;IACxB,OAAO,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,SAAgB,UAAU;IACxB,eAAe,EAAE,CAAC;IAElB,IAAI,IAAA,eAAU,EAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAA,iBAAY,EAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,8CAA8C;IAC9C,MAAM,MAAM,GAAW;QACrB,SAAS,EAAE,iBAAiB,EAAE;QAC9B,OAAO,EAAE,OAAO;KACjB,CAAC;IAEF,IAAA,kBAAa,EAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;IAExD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY;IAC1B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,OAAO,MAAM,CAAC,SAAS,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY;IAC1B,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task execution engine
|
|
3
|
+
* Executes tasks via CLI or API based on task configuration
|
|
4
|
+
*/
|
|
5
|
+
import { TaskDefinition } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Parse task definition from markdown file
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseTaskDefinition(filePath: string): TaskDefinition;
|
|
10
|
+
/**
|
|
11
|
+
* Execute a task
|
|
12
|
+
*/
|
|
13
|
+
export declare function executeTask(taskFilePath: string): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Entry point for scheduled task execution
|
|
16
|
+
* Called by Windows Task Scheduler
|
|
17
|
+
*/
|
|
18
|
+
export declare function main(): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,cAAc,EAA4B,MAAM,YAAY,CAAC;AAItE;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAcpE;AA8JD;;GAEG;AACH,wBAAsB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4CrE;AAED;;;GAGG;AACH,wBAAsB,IAAI,kBAgBzB"}
|
package/dist/executor.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Task execution engine
|
|
4
|
+
* Executes tasks via CLI or API based on task configuration
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.parseTaskDefinition = parseTaskDefinition;
|
|
11
|
+
exports.executeTask = executeTask;
|
|
12
|
+
exports.main = main;
|
|
13
|
+
const child_process_1 = require("child_process");
|
|
14
|
+
const fs_1 = require("fs");
|
|
15
|
+
const gray_matter_1 = __importDefault(require("gray-matter"));
|
|
16
|
+
const logger_js_1 = require("./logger.js");
|
|
17
|
+
const notifier_js_1 = require("./notifier.js");
|
|
18
|
+
/**
|
|
19
|
+
* Parse task definition from markdown file
|
|
20
|
+
*/
|
|
21
|
+
function parseTaskDefinition(filePath) {
|
|
22
|
+
const content = (0, fs_1.readFileSync)(filePath, 'utf-8');
|
|
23
|
+
const parsed = (0, gray_matter_1.default)(content);
|
|
24
|
+
const taskDef = {
|
|
25
|
+
id: parsed.data.id || 'unknown',
|
|
26
|
+
schedule: parsed.data.schedule || '0 0 * * *',
|
|
27
|
+
invocation: parsed.data.invocation || 'cli',
|
|
28
|
+
notifications: parsed.data.notifications || { toast: false },
|
|
29
|
+
enabled: parsed.data.enabled !== false, // Default to true
|
|
30
|
+
instructions: parsed.content,
|
|
31
|
+
};
|
|
32
|
+
return taskDef;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Execute task via Claude CLI
|
|
36
|
+
*/
|
|
37
|
+
async function executeViaCLI(task, log) {
|
|
38
|
+
(0, logger_js_1.addLogStep)(log, 'Starting CLI execution');
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
try {
|
|
41
|
+
// Create a temporary file with the instructions
|
|
42
|
+
const tempFile = `${process.env.TEMP || '/tmp'}/cron-claude-task-${task.id}-${Date.now()}.md`;
|
|
43
|
+
const fs = require('fs');
|
|
44
|
+
fs.writeFileSync(tempFile, task.instructions, 'utf-8');
|
|
45
|
+
(0, logger_js_1.addLogStep)(log, 'Created temporary task file', tempFile);
|
|
46
|
+
// Spawn claude-code process
|
|
47
|
+
(0, logger_js_1.addLogStep)(log, 'Spawning claude-code process');
|
|
48
|
+
const claude = (0, child_process_1.spawn)('claude-code', [tempFile], {
|
|
49
|
+
stdio: 'pipe',
|
|
50
|
+
shell: true,
|
|
51
|
+
});
|
|
52
|
+
let output = '';
|
|
53
|
+
let errorOutput = '';
|
|
54
|
+
claude.stdout?.on('data', (data) => {
|
|
55
|
+
const text = data.toString();
|
|
56
|
+
output += text;
|
|
57
|
+
(0, logger_js_1.addLogStep)(log, 'CLI output', text);
|
|
58
|
+
});
|
|
59
|
+
claude.stderr?.on('data', (data) => {
|
|
60
|
+
const text = data.toString();
|
|
61
|
+
errorOutput += text;
|
|
62
|
+
(0, logger_js_1.addLogStep)(log, 'CLI error output', text);
|
|
63
|
+
});
|
|
64
|
+
claude.on('close', (code) => {
|
|
65
|
+
// Clean up temp file
|
|
66
|
+
try {
|
|
67
|
+
fs.unlinkSync(tempFile);
|
|
68
|
+
(0, logger_js_1.addLogStep)(log, 'Cleaned up temporary file');
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
(0, logger_js_1.addLogStep)(log, 'Warning: Could not clean up temp file', undefined, String(e));
|
|
72
|
+
}
|
|
73
|
+
if (code === 0) {
|
|
74
|
+
(0, logger_js_1.addLogStep)(log, 'CLI execution completed successfully');
|
|
75
|
+
resolve({
|
|
76
|
+
success: true,
|
|
77
|
+
output,
|
|
78
|
+
steps: log.steps,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
(0, logger_js_1.addLogStep)(log, 'CLI execution failed', undefined, `Exit code: ${code}`);
|
|
83
|
+
resolve({
|
|
84
|
+
success: false,
|
|
85
|
+
output,
|
|
86
|
+
error: errorOutput || `Process exited with code ${code}`,
|
|
87
|
+
steps: log.steps,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
claude.on('error', (err) => {
|
|
92
|
+
(0, logger_js_1.addLogStep)(log, 'CLI execution error', undefined, err.message);
|
|
93
|
+
resolve({
|
|
94
|
+
success: false,
|
|
95
|
+
output,
|
|
96
|
+
error: err.message,
|
|
97
|
+
steps: log.steps,
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
103
|
+
(0, logger_js_1.addLogStep)(log, 'Execution setup failed', undefined, errorMsg);
|
|
104
|
+
resolve({
|
|
105
|
+
success: false,
|
|
106
|
+
output: '',
|
|
107
|
+
error: errorMsg,
|
|
108
|
+
steps: log.steps,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Execute task via Claude API
|
|
115
|
+
*/
|
|
116
|
+
async function executeViaAPI(task, log) {
|
|
117
|
+
(0, logger_js_1.addLogStep)(log, 'Starting API execution');
|
|
118
|
+
try {
|
|
119
|
+
// Check for API key
|
|
120
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
121
|
+
if (!apiKey) {
|
|
122
|
+
throw new Error('ANTHROPIC_API_KEY environment variable not set');
|
|
123
|
+
}
|
|
124
|
+
(0, logger_js_1.addLogStep)(log, 'API key found, making request');
|
|
125
|
+
// Make API call using fetch
|
|
126
|
+
const response = await fetch('https://api.anthropic.com/v1/messages', {
|
|
127
|
+
method: 'POST',
|
|
128
|
+
headers: {
|
|
129
|
+
'Content-Type': 'application/json',
|
|
130
|
+
'x-api-key': apiKey,
|
|
131
|
+
'anthropic-version': '2023-06-01',
|
|
132
|
+
},
|
|
133
|
+
body: JSON.stringify({
|
|
134
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
135
|
+
max_tokens: 4096,
|
|
136
|
+
messages: [
|
|
137
|
+
{
|
|
138
|
+
role: 'user',
|
|
139
|
+
content: task.instructions,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
}),
|
|
143
|
+
});
|
|
144
|
+
if (!response.ok) {
|
|
145
|
+
const errorText = await response.text();
|
|
146
|
+
throw new Error(`API request failed: ${response.status} ${errorText}`);
|
|
147
|
+
}
|
|
148
|
+
const data = await response.json();
|
|
149
|
+
const output = data.content?.[0]?.text || JSON.stringify(data);
|
|
150
|
+
(0, logger_js_1.addLogStep)(log, 'API request completed', output);
|
|
151
|
+
return {
|
|
152
|
+
success: true,
|
|
153
|
+
output,
|
|
154
|
+
steps: log.steps,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
159
|
+
(0, logger_js_1.addLogStep)(log, 'API execution failed', undefined, errorMsg);
|
|
160
|
+
return {
|
|
161
|
+
success: false,
|
|
162
|
+
output: '',
|
|
163
|
+
error: errorMsg,
|
|
164
|
+
steps: log.steps,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Execute a task
|
|
170
|
+
*/
|
|
171
|
+
async function executeTask(taskFilePath) {
|
|
172
|
+
// Parse task definition
|
|
173
|
+
const task = parseTaskDefinition(taskFilePath);
|
|
174
|
+
// Create log
|
|
175
|
+
const log = (0, logger_js_1.createLog)(task.id);
|
|
176
|
+
(0, logger_js_1.addLogStep)(log, 'Task execution started', `Task: ${task.id}, Method: ${task.invocation}`);
|
|
177
|
+
// Check if task is enabled
|
|
178
|
+
if (!task.enabled) {
|
|
179
|
+
(0, logger_js_1.addLogStep)(log, 'Task skipped - disabled');
|
|
180
|
+
(0, logger_js_1.finalizeLog)(log, false);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
// Execute based on invocation method
|
|
184
|
+
let result;
|
|
185
|
+
if (task.invocation === 'cli') {
|
|
186
|
+
result = await executeViaCLI(task, log);
|
|
187
|
+
}
|
|
188
|
+
else if (task.invocation === 'api') {
|
|
189
|
+
result = await executeViaAPI(task, log);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
(0, logger_js_1.addLogStep)(log, 'Invalid invocation method', undefined, `Unknown method: ${task.invocation}`);
|
|
193
|
+
(0, logger_js_1.finalizeLog)(log, false);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
// Finalize log
|
|
197
|
+
(0, logger_js_1.finalizeLog)(log, result.success);
|
|
198
|
+
// Send notification if enabled
|
|
199
|
+
if (task.notifications.toast) {
|
|
200
|
+
try {
|
|
201
|
+
await (0, notifier_js_1.sendNotification)(`Task ${task.id} ${result.success ? 'completed' : 'failed'}`, result.success
|
|
202
|
+
? `Task executed successfully`
|
|
203
|
+
: `Task failed: ${result.error || 'Unknown error'}`);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
console.error('Failed to send notification:', error);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Entry point for scheduled task execution
|
|
212
|
+
* Called by Windows Task Scheduler
|
|
213
|
+
*/
|
|
214
|
+
async function main() {
|
|
215
|
+
// Get task file path from command line arguments
|
|
216
|
+
const taskFile = process.argv[2];
|
|
217
|
+
if (!taskFile) {
|
|
218
|
+
console.error('Usage: node executor.js <task-file-path>');
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
await executeTask(taskFile);
|
|
223
|
+
process.exit(0);
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
console.error('Fatal error:', error);
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// Run if called directly
|
|
231
|
+
if (require.main === module) {
|
|
232
|
+
main();
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
|