@crewx/cron 0.1.10-rc.24 → 0.1.10-rc.241

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/README.md CHANGED
@@ -3,5 +3,5 @@
3
3
  Cron scheduler for CrewX - schedule and execute crewx commands automatically.
4
4
 
5
5
  ```bash
6
- npx cron add "0 9 * * *" "@agent task" --name "Daily Task"
6
+ crewx cron add "0 9 * * *" "@agent task" --name "Daily Task"
7
7
  ```
package/dist/cli.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ export declare const CRON_RUNTIME_LIFECYCLE_MANAGED = "CRON_RUNTIME_LIFECYCLE_MANAGED";
3
+ export declare function formatDisplayTimestamp(date: Date): string;
2
4
  export declare function main(inputArgs?: string[]): Promise<void>;
3
- //# sourceMappingURL=cli.d.ts.map
5
+
package/dist/cli.js CHANGED
@@ -1,93 +1,6 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
8
- }
9
- Object.defineProperty(o, k2, desc);
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- o[k2] = m[k];
13
- }));
14
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
- Object.defineProperty(o, "default", { enumerable: true, value: v });
16
- }) : function(o, v) {
17
- o["default"] = v;
18
- });
19
- var __importStar = (this && this.__importStar) || (function () {
20
- var ownKeys = function(o) {
21
- ownKeys = Object.getOwnPropertyNames || function (o) {
22
- var ar = [];
23
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
- return ar;
25
- };
26
- return ownKeys(o);
27
- };
28
- return function (mod) {
29
- if (mod && mod.__esModule) return mod;
30
- var result = {};
31
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
- __setModuleDefault(result, mod);
33
- return result;
34
- };
35
- })();
36
- Object.defineProperty(exports, "__esModule", { value: true });
37
- exports.main = main;
38
- const fs = __importStar(require("fs"));
39
- const path = __importStar(require("path"));
40
- let PKG_VERSION = 'unknown';
41
- try {
42
- const _pkgPath = fs.existsSync(path.join(__dirname, 'package.json'))
43
- ? path.join(__dirname, 'package.json')
44
- : path.join(__dirname, '..', 'package.json');
45
- const _pkg = JSON.parse(fs.readFileSync(_pkgPath, 'utf-8'));
46
- if (_pkg?.version)
47
- PKG_VERSION = String(_pkg.version);
48
- }
49
- catch { }
50
- async function loadTracer() {
51
- try {
52
- return await Promise.resolve().then(() => __importStar(require('@crewx/shared/skill-tracer')));
53
- }
54
- catch {
55
- return null;
56
- }
57
- }
58
- const engine_1 = require("./src/engine");
59
- function getOpt(args, long, short) {
60
- for (let i = 0; i < args.length; i++) {
61
- const a = args[i];
62
- if (!a)
63
- continue;
64
- if (a === long || (short && a === short)) {
65
- return args[i + 1];
66
- }
67
- if (a.startsWith(long + '=')) {
68
- return a.slice(long.length + 1);
69
- }
70
- if (short && a.startsWith(short + '=')) {
71
- return a.slice(short.length + 1);
72
- }
73
- }
74
- return undefined;
75
- }
76
- function hasFlag(args, long, short) {
77
- return args.includes(long) || (short ? args.includes(short) : false);
78
- }
79
- function showDetailedUsage() {
80
- const skillMd = path.join(__dirname, '..', 'SKILL.md');
81
- if (fs.existsSync(skillMd)) {
82
- process.stdout.write(fs.readFileSync(skillMd, 'utf-8'));
83
- }
84
- else {
85
- console.log('No SKILL.md found. Use --help for usage.');
86
- }
87
- }
88
- function printUsage() {
89
- console.log(`
90
- @crewx/cron@${PKG_VERSION} - Cron-based task scheduler for AI agents
2
+ "use strict";var N=exports&&exports.__createBinding||(Object.create?(function(e,t,r,n){if(n===void 0)n=r;var o=Object.getOwnPropertyDescriptor(t,r);if(!o||("get"in o?!t.__esModule:o.writable||o.configurable)){o={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,o)}):(function(e,t,r,n){if(n===void 0)n=r;e[n]=t[r]}));var R=exports&&exports.__setModuleDefault||(Object.create?(function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}):function(e,t){e["default"]=t});var h=exports&&exports.__importStar||(function(){var e=function(t){e=Object.getOwnPropertyNames||function(r){var n=[];for(var o in r)if(Object.prototype.hasOwnProperty.call(r,o))n[n.length]=o;return n};return e(t)};return function(t){if(t&&t.__esModule)return t;var r={};if(t!=null){for(var n=e(t),o=0;o<n.length;o++)if(n[o]!=="default")N(r,t,n[o])}R(r,t);return r}})();Object.defineProperty(exports,"__esModule",{value:true});exports.CRON_RUNTIME_LIFECYCLE_MANAGED=void 0;exports.formatDisplayTimestamp=g;exports.main=S;const m=h(require("fs"));const f=h(require("path"));let $="unknown";try{const e=m.existsSync(f.join(__dirname,"package.json"))?f.join(__dirname,"package.json"):f.join(__dirname,"..","package.json");const t=JSON.parse(m.readFileSync(e,"utf-8"));if(t?.version)$=String(t.version)}catch{}async function I(){try{return await Promise.resolve().then(()=>h(require("@crewx/shared/skill-tracer")))}catch{return null}}const _=require("@crewx/sdk");const a=require("./src/engine");const k=require("./src/run-record");exports.CRON_RUNTIME_LIFECYCLE_MANAGED="CRON_RUNTIME_LIFECYCLE_MANAGED";function x(e,t){if(e==="APP_LAUNCHER_UNAVAILABLE"){return"This schedule belongs to an App and runs only inside the CrewX server; it cannot be started from the CLI."}if(e==="APP_ROW_INVALID")return"This App schedule is not in its managed form, so it was not run.";if(e==="MODE_UNSUPPORTED")return`Unsupported schedule mode: ${t.mode}`;return"A desktop update is draining active work; cannot start a new schedule run right now."}function v(e){return e.app!==void 0?(0,_.appScheduleCommandLabel)(e.app):e.command}function w(e){const t=new Error(`${exports.CRON_RUNTIME_LIFECYCLE_MANAGED}: cron ${e} is managed by the CrewX server runtime; start the server instead`);t.code=exports.CRON_RUNTIME_LIFECYCLE_MANAGED;return t}const b=20;function C(e){if(e===null)return"-";return`${(e/1e3).toFixed(1)}s`}function A(e,t){if(e.length===0){console.log(t===void 0?"No runs yet.":`No runs yet for ${t}.`);return}console.log(`Recent runs (newest first, ${b} max)`);console.log(`${"STARTED".padEnd(28)}${"STATUS".padEnd(10)}${"MODE".padEnd(9)}${"DURATION".padEnd(10)}${"RUN".padEnd(16)}${"SCHEDULE".padEnd(18)}DETAIL`);for(const r of e){const n=[r.errorCode,r.highFrequency?"high frequency":null].filter(Boolean).join(", ");console.log(`${g(new Date(r.startedAt)).padEnd(28)}${r.status.padEnd(10)}${r.mode.padEnd(9)}${C(r.durationMs).padEnd(10)}${r.id.padEnd(16)}${r.scheduleId.padEnd(18)}`+n)}}function O(e){console.log(`Run: ${e.id}`);console.log(`Schedule: ${e.scheduleId}${e.scheduleName?` (${e.scheduleName})`:""}`);console.log(`Mode: ${e.mode}`);console.log(`Status: ${e.status}`);if(e.errorCode)console.log(`Error: ${e.errorCode}`);if(e.exitCode!==null)console.log(`Exit code: ${e.exitCode}`);if(e.signal)console.log(`Signal: ${e.signal}`);console.log(`Trigger: ${e.trigger}`);console.log(`Started: ${g(new Date(e.startedAt))}`);if(e.finishedAt)console.log(`Finished: ${g(new Date(e.finishedAt))}`);console.log(`Duration: ${C(e.durationMs)}`);if(e.appId)console.log(`App: ${e.appId}`);if(e.command)console.log(`Command: ${e.command}`);if(e.taskId)console.log(`Task: ${e.taskId}`);if(e.outputBytes!==null)console.log(`Output: ${e.outputBytes} bytes${e.outputTruncated?" (truncated during the run)":""}`);console.log("\u2500".repeat(40));if(e.outputTail===null){console.log(e.mode==="app"?"(App runs keep no output tail)":"(no output captured)")}else if(e.outputTail===""){console.log("(no output)")}else{console.log(e.outputTail)}}function U(e){try{return new _.ScheduleRunRepository().get(e)}catch(t){console.warn(`Run ${e} record could not be read; the exit code follows the run's own result: ${t.message}`);return void 0}}function i(e,t,r){for(let n=0;n<e.length;n++){const o=e[n];if(!o)continue;if(o===t||r&&o===r){return e[n+1]}if(o.startsWith(t+"=")){return o.slice(t.length+1)}if(r&&o.startsWith(r+"=")){return o.slice(r.length+1)}}return void 0}function u(e,t,r){return e.includes(t)||(r?e.includes(r):false)}function T(){const e=f.join(__dirname,"..","SKILL.md");if(m.existsSync(e)){process.stdout.write(m.readFileSync(e,"utf-8"))}else{console.log("No SKILL.md found. Use --help for usage.")}}function g(e){const t=e.toISOString();return`${t.slice(0,10)} ${t.slice(11,19)} UTC`}function y(){console.log(`
3
+ @crewx/cron@${$} - Cron-based task scheduler for AI agents
91
4
 
92
5
  Usage:
93
6
  cron <command> [options]
@@ -101,6 +14,7 @@ Commands:
101
14
  cron update <id> [options] Update a schedule
102
15
  cron info <id> Show schedule details
103
16
  cron run <id> Run a schedule immediately
17
+ cron runs [cron_\u2026 | crun_\u2026] List recent runs, or show one run with its output
104
18
  cron start Start the cron daemon
105
19
  cron stop Stop the cron daemon
106
20
  cron status Check daemon status
@@ -117,323 +31,7 @@ Examples:
117
31
  cron start
118
32
 
119
33
  For detailed usage guide: cron usage
120
- `);
121
- }
122
- async function main(inputArgs) {
123
- const args = inputArgs ?? process.argv.slice(2);
124
- const command = args[0];
125
- if (args.length > 0 && command !== 'daemon') {
126
- (0, engine_1.logUsage)(args.join(' '));
127
- }
128
- if (hasFlag(args, '--version')) {
129
- console.log(PKG_VERSION);
130
- return;
131
- }
132
- if (!command || command === 'help' || hasFlag(args, '--help', '-h')) {
133
- printUsage();
134
- return;
135
- }
136
- switch (command) {
137
- case 'usage': {
138
- showDetailedUsage();
139
- break;
140
- }
141
- case 'add': {
142
- const positional = [];
143
- for (let i = 1; i < args.length; i++) {
144
- const arg = args[i];
145
- if (!arg)
146
- continue;
147
- if (arg.startsWith('-')) {
148
- if (['--name', '-n', '--mode', '-m', '--timezone', '-t', '--dir', '-d', '--timeout'].includes(arg)) {
149
- i++;
150
- }
151
- continue;
152
- }
153
- positional.push(arg);
154
- }
155
- if (positional.length < 2) {
156
- console.error('Usage: cron add <schedule> <command> [--name <name>] [--mode <mode>]');
157
- process.exit(1);
158
- }
159
- const cronExpr = positional[0];
160
- const cmd = positional.slice(1).join(' ');
161
- const subArgs = args.slice(1);
162
- (0, engine_1.ensureDaemonRunning)();
163
- const schedule = (0, engine_1.addSchedule)(cronExpr, cmd, {
164
- name: getOpt(subArgs, '--name', '-n'),
165
- mode: getOpt(subArgs, '--mode', '-m'),
166
- timezone: getOpt(subArgs, '--timezone', '-t'),
167
- dir: getOpt(subArgs, '--dir', '-d'),
168
- timeout: getOpt(subArgs, '--timeout'),
169
- allowConcurrent: hasFlag(subArgs, '--allow-concurrent'),
170
- });
171
- console.log(`Schedule created: ${schedule.id}`);
172
- console.log(`Cron: ${cronExpr} (${(0, engine_1.describeCron)(cronExpr)})`);
173
- console.log(`Command: ${cmd}`);
174
- console.log(`Mode: ${schedule.mode}`);
175
- if (schedule.timezone)
176
- console.log(`Timezone: ${schedule.timezone}`);
177
- if (schedule.next_run)
178
- console.log(`Next run: ${new Date(schedule.next_run).toLocaleString()}`);
179
- break;
180
- }
181
- case 'list':
182
- case 'ls': {
183
- const jsonOutput = hasFlag(args, '--json');
184
- (0, engine_1.ensureDaemonRunning)();
185
- const schedules = (0, engine_1.loadSchedules)();
186
- if (jsonOutput) {
187
- console.log(JSON.stringify(schedules, null, 2));
188
- return;
189
- }
190
- if (schedules.length === 0) {
191
- console.log('No schedules found.');
192
- return;
193
- }
194
- console.log(`\nSchedules (${schedules.length}):\n`);
195
- console.log('| ID | Name | Cron | Status | Command |');
196
- console.log('|--------|----------------|-------------|--------|----------------------------|');
197
- for (const s of schedules) {
198
- const status = s.enabled ? 'ON ' : 'OFF';
199
- const name = (s.name ?? '-').substring(0, 14).padEnd(14);
200
- const cron = s.cron.substring(0, 11).padEnd(11);
201
- const cmd = s.command.substring(0, 26).padEnd(26);
202
- console.log(`| ${s.id} | ${name} | ${cron} | ${status} | ${cmd} |`);
203
- }
204
- console.log('');
205
- break;
206
- }
207
- case 'remove':
208
- case 'rm': {
209
- const id = args[1];
210
- if (!id) {
211
- console.error('Usage: cron remove <id>');
212
- process.exit(1);
213
- }
214
- (0, engine_1.ensureDaemonRunning)();
215
- try {
216
- const removed = (0, engine_1.removeSchedule)(id);
217
- console.log(`Removed schedule: ${id}`);
218
- console.log(`Cron: ${removed.cron}`);
219
- console.log(`Command: ${removed.command}`);
220
- }
221
- catch (e) {
222
- const err = e;
223
- console.error(err.message);
224
- process.exit(1);
225
- }
226
- break;
227
- }
228
- case 'enable': {
229
- const id = args[1];
230
- if (!id) {
231
- console.error('Usage: cron enable <id>');
232
- process.exit(1);
233
- }
234
- (0, engine_1.ensureDaemonRunning)();
235
- try {
236
- (0, engine_1.enableSchedule)(id);
237
- console.log(`Enabled schedule: ${id}`);
238
- }
239
- catch (e) {
240
- const err = e;
241
- console.error(err.message);
242
- process.exit(1);
243
- }
244
- break;
245
- }
246
- case 'disable': {
247
- const id = args[1];
248
- if (!id) {
249
- console.error('Usage: cron disable <id>');
250
- process.exit(1);
251
- }
252
- (0, engine_1.ensureDaemonRunning)();
253
- try {
254
- (0, engine_1.disableSchedule)(id);
255
- console.log(`Disabled schedule: ${id}`);
256
- }
257
- catch (e) {
258
- const err = e;
259
- console.error(err.message);
260
- process.exit(1);
261
- }
262
- break;
263
- }
264
- case 'update': {
265
- const id = args[1];
266
- if (!id) {
267
- console.error('Usage: cron update <id> [--cron <expr>] [--command <cmd>] [--name <name>]');
268
- process.exit(1);
269
- }
270
- const subArgs = args.slice(1);
271
- (0, engine_1.ensureDaemonRunning)();
272
- try {
273
- const updateOpts = {
274
- cron: getOpt(subArgs, '--cron', '-c'),
275
- command: getOpt(subArgs, '--command', '-C'),
276
- name: getOpt(subArgs, '--name', '-n'),
277
- mode: getOpt(subArgs, '--mode', '-m'),
278
- timezone: getOpt(subArgs, '--timezone', '-t'),
279
- working_directory: getOpt(subArgs, '--dir', '-d'),
280
- timeout_ms: getOpt(subArgs, '--timeout') ? parseInt(getOpt(subArgs, '--timeout'), 10) : undefined,
281
- allow_concurrent: hasFlag(subArgs, '--allow-concurrent') ? true : hasFlag(subArgs, '--no-allow-concurrent') ? false : undefined,
282
- };
283
- const { schedule, changes } = (0, engine_1.updateSchedule)(id, updateOpts);
284
- if (changes.length === 0) {
285
- console.log('No changes specified. Use --cron, --command, --name, etc.');
286
- process.exit(1);
287
- }
288
- console.log(`Updated schedule: ${id}`);
289
- changes.forEach(c => console.log(` ${c}`));
290
- if (schedule.next_run) {
291
- console.log(`Next run: ${new Date(schedule.next_run).toLocaleString()}`);
292
- }
293
- }
294
- catch (e) {
295
- const err = e;
296
- console.error(err.message);
297
- process.exit(1);
298
- }
299
- break;
300
- }
301
- case 'info': {
302
- const id = args[1];
303
- if (!id) {
304
- console.error('Usage: cron info <id>');
305
- process.exit(1);
306
- }
307
- const jsonOutput = hasFlag(args, '--json');
308
- (0, engine_1.ensureDaemonRunning)();
309
- const schedules = (0, engine_1.loadSchedules)();
310
- const schedule = schedules.find(s => s.id === id);
311
- if (!schedule) {
312
- console.error(`Schedule not found: ${id}`);
313
- process.exit(1);
314
- }
315
- if (jsonOutput) {
316
- console.log(JSON.stringify(schedule, null, 2));
317
- return;
318
- }
319
- console.log(`\nSchedule: ${schedule.id}`);
320
- console.log('─'.repeat(40));
321
- console.log(`Name: ${schedule.name ?? '-'}`);
322
- console.log(`Cron: ${schedule.cron} (${(0, engine_1.describeCron)(schedule.cron)})`);
323
- console.log(`Command: ${schedule.command}`);
324
- console.log(`Mode: ${schedule.mode}`);
325
- console.log(`Status: ${schedule.enabled ? 'Enabled' : 'Disabled'}`);
326
- console.log(`Timezone: ${schedule.timezone ?? 'Local'}`);
327
- console.log(`Working Dir: ${schedule.working_directory ?? 'Project root'}`);
328
- console.log(`Timeout: ${schedule.timeout_ms / 1000}s`);
329
- console.log(`Allow Concurrent: ${schedule.allow_concurrent ? 'Yes' : 'No'}`);
330
- console.log('─'.repeat(40));
331
- console.log(`Created: ${new Date(schedule.created_at).toLocaleString()}`);
332
- console.log(`Updated: ${new Date(schedule.updated_at).toLocaleString()}`);
333
- console.log(`Last Run: ${schedule.last_run ? new Date(schedule.last_run).toLocaleString() : 'Never'}`);
334
- console.log(`Next Run: ${schedule.next_run ? new Date(schedule.next_run).toLocaleString() : 'Unknown'}`);
335
- console.log(`Run Count: ${schedule.run_count ?? 0}`);
336
- console.log('');
337
- break;
338
- }
339
- case 'run': {
340
- const id = args[1];
341
- if (!id) {
342
- console.error('Usage: cron run <id>');
343
- process.exit(1);
344
- }
345
- (0, engine_1.ensureDaemonRunning)();
346
- const schedules = (0, engine_1.loadSchedules)();
347
- const schedule = schedules.find(s => s.id === id);
348
- if (!schedule) {
349
- console.error(`Schedule not found: ${id}`);
350
- process.exit(1);
351
- }
352
- console.log(`Running schedule: ${id}`);
353
- const result = await (0, engine_1.executeSchedule)(schedule);
354
- console.log(`Result: ${result.success ? 'Success' : 'Failed'}`);
355
- if (result.error)
356
- console.log(`Error: ${result.error}`);
357
- break;
358
- }
359
- case 'start': {
360
- if ((0, engine_1.isDaemonRunning)()) {
361
- const status = (0, engine_1.getDaemonStatus)();
362
- console.error(`Daemon already running (PID: ${status.pid ?? 'unknown'})`);
363
- process.exit(1);
364
- }
365
- try {
366
- const pid = (0, engine_1.startDaemon)();
367
- console.log(`Cron daemon started (PID: ${pid})`);
368
- console.log(`PID file: ${engine_1.DATA_PATHS.PID_FILE}`);
369
- }
370
- catch (e) {
371
- const err = e;
372
- console.error('Failed to start daemon:', err.message);
373
- process.exit(1);
374
- }
375
- break;
376
- }
377
- case 'stop': {
378
- try {
379
- const stopped = (0, engine_1.stopDaemon)();
380
- if (!stopped) {
381
- console.error('Daemon not running');
382
- process.exit(1);
383
- }
384
- console.log('Cron daemon stopped');
385
- }
386
- catch (e) {
387
- const err = e;
388
- console.error('Failed to stop daemon:', err.message);
389
- process.exit(1);
390
- }
391
- break;
392
- }
393
- case 'status': {
394
- const jsonOutput = hasFlag(args, '--json');
395
- const status = (0, engine_1.getDaemonStatus)();
396
- if (jsonOutput) {
397
- console.log(JSON.stringify(status, null, 2));
398
- return;
399
- }
400
- if (status.running && status.pid) {
401
- console.log(`Daemon is running (PID: ${status.pid})`);
402
- if (status.started_at) {
403
- console.log(`Started: ${new Date(status.started_at).toLocaleString()}`);
404
- }
405
- }
406
- else {
407
- console.log('Daemon is not running');
408
- }
409
- console.log(`Schedules: ${status.schedules.enabled}/${status.schedules.total} enabled`);
410
- break;
411
- }
412
- case 'daemon': {
413
- if (hasFlag(args, '--foreground')) {
414
- (0, engine_1.runDaemonForeground)();
415
- }
416
- else {
417
- console.log('Use "cron start" to start the daemon');
418
- }
419
- break;
420
- }
421
- default: {
422
- console.error(`Unknown command: ${command}`);
423
- printUsage();
424
- process.exit(1);
425
- }
426
- }
427
- }
428
- if (require.main === module) {
429
- const _args = process.argv.slice(2);
430
- const _isDaemonForeground = _args[0] === 'daemon' && _args.includes('--foreground');
431
- (_isDaemonForeground ? Promise.resolve(null) : loadTracer()).then(tracer => {
432
- const opts = tracer ? { skillVersion: tracer.getOwnSkillVersion(__dirname) } : {};
433
- return tracer ? tracer.run('crewx/cron', () => main(), opts) : main();
434
- }).catch((e) => {
435
- console.error(e.message);
436
- process.exit(1);
437
- });
438
- }
439
- //# sourceMappingURL=cli.js.map
34
+ `)}async function S(e){const t=e??process.argv.slice(2);const r=t[0];if(u(t,"--version")){console.log($);return}if(!r||r==="help"||u(t,"--help","-h")){y();return}switch(r){case"usage":{T();break}case"add":{const n=[];for(let d=1;d<t.length;d++){const p=t[d];if(!p)continue;if(p.startsWith("-")){if(["--name","-n","--mode","-m","--timezone","-t","--dir","-d","--timeout","--model","--provider"].includes(p)){d++}continue}n.push(p)}if(n.length<2){console.error("Usage: cron add <schedule> <command> [--name <name>] [--mode <mode>] [--model <model>] [--provider <provider>]");process.exit(1)}const o=n[0];const c=n.slice(1).join(" ");const s=t.slice(1);const l=(0,a.addSchedule)(o,c,{name:i(s,"--name","-n"),mode:i(s,"--mode","-m"),timezone:i(s,"--timezone","-t"),dir:i(s,"--dir","-d"),timeout:i(s,"--timeout"),allowConcurrent:u(s,"--allow-concurrent"),model:i(s,"--model"),provider:i(s,"--provider")});console.log(`Schedule created: ${l.id}`);console.log(`Cron: ${o} (${(0,a.describeCron)(o)})`);console.log(`Command: ${c}`);console.log(`Mode: ${l.mode}`);if(l.model)console.log(`Model: ${l.model}`);if(l.provider)console.log(`Provider: ${l.provider}`);if(l.timezone)console.log(`Timezone: ${l.timezone}`);if(l.next_run)console.log(`Next run: ${g(new Date(l.next_run))}`);break}case"list":case"ls":{const n=u(t,"--json");const o=(0,a.loadSchedules)();if(n){console.log(JSON.stringify(o,null,2));return}if(o.length===0){console.log("No schedules found.");return}console.log(`
35
+ Schedules (${o.length}):
36
+ `);console.log("| ID | Name | Cron | Status | Command |");console.log("|--------|----------------|-------------|--------|----------------------------|");for(const c of o){const s=(0,a.effectiveEnabled)(c)?"ON ":"OFF";const l=(c.name??"-").substring(0,14).padEnd(14);const d=c.cron.substring(0,11).padEnd(11);const p=v(c).substring(0,26).padEnd(26);console.log(`| ${c.id} | ${l} | ${d} | ${s} | ${p} |`)}console.log("");break}case"remove":case"rm":{const n=t[1];if(!n){console.error("Usage: cron remove <id>");process.exit(1)}try{const o=(0,a.removeSchedule)(n);console.log(`Removed schedule: ${n}`);console.log(`Cron: ${o.cron}`);console.log(`Command: ${o.command}`)}catch(o){const c=o;console.error(c.message);process.exit(1)}break}case"enable":{const n=t[1];if(!n){console.error("Usage: cron enable <id>");process.exit(1)}try{(0,a.enableSchedule)(n);console.log(`Enabled schedule: ${n}`)}catch(o){const c=o;console.error(c.message);process.exit(1)}break}case"disable":{const n=t[1];if(!n){console.error("Usage: cron disable <id>");process.exit(1)}try{(0,a.disableSchedule)(n);console.log(`Disabled schedule: ${n}`)}catch(o){const c=o;console.error(c.message);process.exit(1)}break}case"update":{const n=t[1];if(!n){console.error("Usage: cron update <id> [--cron <expr>] [--command <cmd>] [--name <name>] [--model <model>] [--clear-model] [--provider <provider>] [--clear-provider]");process.exit(1)}const o=t.slice(1);try{const c={cron:i(o,"--cron","-c"),command:i(o,"--command","-C"),name:i(o,"--name","-n"),mode:i(o,"--mode","-m"),timezone:i(o,"--timezone","-t"),working_directory:i(o,"--dir","-d"),timeout_ms:i(o,"--timeout")?parseInt(i(o,"--timeout"),10):void 0,allow_concurrent:u(o,"--allow-concurrent")?true:u(o,"--no-allow-concurrent")?false:void 0,model:u(o,"--clear-model")?null:i(o,"--model"),provider:u(o,"--clear-provider")?null:i(o,"--provider")};const{schedule:s,changes:l}=(0,a.updateSchedule)(n,c);if(l.length===0){console.log("No changes specified. Use --cron, --command, --name, etc.");process.exit(1)}console.log(`Updated schedule: ${n}`);l.forEach(d=>console.log(` ${d}`));if(s.next_run){console.log(`Next run: ${g(new Date(s.next_run))}`)}}catch(c){const s=c;console.error(s.message);process.exit(1)}break}case"info":{const n=t[1];if(!n){console.error("Usage: cron info <id>");process.exit(1)}const o=u(t,"--json");const c=(0,a.loadSchedules)();const s=c.find(l=>l.id===n);if(!s){console.error(`Schedule not found: ${n}`);process.exit(1)}if(o){console.log(JSON.stringify(s,null,2));return}console.log(`
37
+ Schedule: ${s.id}`);console.log("\u2500".repeat(40));console.log(`Name: ${s.name??"-"}`);console.log(`Cron: ${s.cron} (${(0,a.describeCron)(s.cron)})`);console.log(`Command: ${v(s)}`);console.log(`Mode: ${s.mode}`);console.log(`Model: ${s.model??"(agent default)"}`);console.log(`Provider: ${s.provider??"(agent default)"}`);console.log(`Status: ${(0,a.effectiveEnabled)(s)?"Enabled":"Disabled"}`);if(s.app!==void 0)console.log(`App: ${s.app.appId} (${s.app.actionId}); change it from the App`);console.log(`Timezone: ${s.timezone??"Local"}`);console.log(`Working Dir: ${s.working_directory??"Project root"}`);console.log(`Timeout: ${s.timeout_ms/1e3}s`);console.log(`Allow Concurrent: ${s.allow_concurrent?"Yes":"No"}`);console.log("\u2500".repeat(40));console.log(`Created: ${g(new Date(s.created_at))}`);console.log(`Updated: ${g(new Date(s.updated_at))}`);console.log(`Last Run: ${s.last_run?g(new Date(s.last_run)):"Never"}`);console.log(`Next Run: ${s.next_run?g(new Date(s.next_run)):"Unknown"}`);console.log(`Run Count: ${s.run_count??0}`);console.log("");break}case"run":{const n=t[1];if(!n){console.error("Usage: cron run <id>");process.exit(1)}const o=(0,a.loadSchedules)();const c=o.find(D=>D.id===n);if(!c){console.error(`Schedule not found: ${n}`);process.exit(1)}console.log(`Running schedule: ${n}`);const s=await(0,a.executeSchedule)(c,{trigger:"cron_manual"});if(s.status==="blocked"){console.error(x(s.reason,c));process.exit(1)}if(s.status==="conflict"){console.error(`Schedule already running (run: ${s.runningRunId??"unknown"})`);process.exit(1)}if(s.status==="skipped"){console.error(`Schedule not run: ${s.reason}`);break}console.log(`Run started: ${s.runId}`);if(s.taskId!==void 0)console.log(`Task: ${s.taskId}`);const l=await s.done;const d=U(s.runId);const p=!l.success||d?.status==="failed"||d?.status==="lost";console.log(`Result: ${p?"Failed":"Success"}`);const E=l.error??d?.errorCode;if(E)console.log(`Error: ${E}`);if(p)process.exit(1);break}case"runs":{const n=t[1];const o=new _.ScheduleRunRepository;const c=(0,k.runWorkspaceId)(process.cwd());if(n!==void 0&&n.startsWith("crun_")){const l=o.get(n);if(l===void 0||l.workspaceId!==c){console.error(`Run not found in this workspace: ${n}`);process.exit(1)}O(l);break}const s=n===void 0?o.listByWorkspace(c,{limit:b}):o.listBySchedule(c,n,b);A(s,n);break}case"start":{throw w(r)}case"stop":{throw w(r)}case"status":{const n=u(t,"--json");const o=(0,a.getDaemonStatus)();if(n){console.log(JSON.stringify(o,null,2));return}if(o.running&&o.pid){console.log(`Daemon is running (PID: ${o.pid})`);if(o.started_at){console.log(`Started: ${g(new Date(o.started_at))}`)}}else{console.log("Daemon is not running")}console.log(`Schedules: ${o.schedules.enabled}/${o.schedules.total} enabled`);break}case"daemon":{if(u(t,"--foreground")){(0,a.runDaemonForeground)()}else{throw w(r)}break}default:{console.error(`Unknown command: ${r}`);y();process.exit(1)}}}if(require.main===module){const e=process.argv.slice(2);const t=e[0]==="daemon"&&e.includes("--foreground");(t?Promise.resolve(null):I()).then(r=>{const n=r?{skillVersion:r.getOwnSkillVersion(__dirname)}:{};return r?r.run("crewx/cron",()=>S(),n):S()}).catch(r=>{console.error(r.message);process.exit(1)})}
@@ -0,0 +1,17 @@
1
+ import type { ExecutionMode } from './types';
2
+ export interface BuiltinScheduleDef {
3
+ builtin_id: string;
4
+ name: string;
5
+ cron: string;
6
+ mode: ExecutionMode;
7
+ buildCommand: () => string;
8
+ cliArgs: readonly string[];
9
+ isLegacyCommand: (command: string) => boolean;
10
+ isFrozenPathCommand: (command: string) => boolean;
11
+ }
12
+ export declare function normalizeBuiltinCommand(command: string): string;
13
+ export declare function getProjectRoot(): string;
14
+ export declare const BUILTIN_SCHEDULES: BuiltinScheduleDef[];
15
+ export declare function findBuiltinByName(name: string | null | undefined): BuiltinScheduleDef | undefined;
16
+ export declare function findBuiltinById(builtinId: string): BuiltinScheduleDef | undefined;
17
+
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.BUILTIN_SCHEDULES=void 0;exports.normalizeBuiltinCommand=t;exports.getProjectRoot=m;exports.findBuiltinByName=d;exports.findBuiltinById=u;const r=require("child_process");function t(e){return e.trim().replace(/\s+/g," ")}function m(){try{return(0,r.execSync)("git rev-parse --show-toplevel",{encoding:"utf8"}).trim()}catch{return process.cwd()}}const n=/^node .+[\\/]packages[\\/]built-in[\\/]memory[\\/]dist[\\/]cli\.js summarize-dirty$/;const o=[n,/^npx memory summarize-dirty$/,/^npx @crewx\/memory summarize-dirty$/];exports.BUILTIN_SCHEDULES=[{builtin_id:"memory-debounce",name:"memory-debounce",cron:"*/1 * * * *",mode:"command",buildCommand:()=>"crewx memory summarize-dirty",cliArgs:["memory","summarize-dirty"],isLegacyCommand:e=>o.some(i=>i.test(e)),isFrozenPathCommand:e=>n.test(e)}];function d(e){if(!e)return void 0;return exports.BUILTIN_SCHEDULES.find(i=>i.name===e)}function u(e){return exports.BUILTIN_SCHEDULES.find(i=>i.builtin_id===e)}
@@ -1,23 +1,60 @@
1
- import type { Schedule, ExecutionMode, ExecuteResult, DaemonStatus, UpdateOptions } from './types';
2
- export type { Schedule, ExecutionMode, ExecuteResult, DaemonStatus, UpdateOptions };
1
+ import { spawn } from 'child_process';
2
+ import { CronStoreError } from './types';
3
+ import type { Schedule, ExecutionMode, ExecuteResult, ExecuteScheduleOptions, ExecuteScheduleOutcome, DaemonStatus, UpdateOptions, StartDaemonResult, CronStoreErrorCode, ScheduleStore, ScheduleStoreLock, ScheduleStoreUpdate, ClaimOccurrenceOptions, ClaimOccurrenceResult, RecordFinishedOptions, RecordStartedOptions, AppScheduleBinding, AppScheduleChildExit, AppScheduleLaunchDecision, AppScheduleLauncher, AppScheduleOwner, AppScheduleSettle, AppScheduleSkipRecord, AppScheduleTemplate, AppScheduleWrite, ExecuteScheduleSkipped, ScheduleTrigger } from './types';
4
+ import { BUILTIN_SCHEDULES, getProjectRoot } from './builtins';
5
+ import type { BuiltinScheduleDef } from './builtins';
6
+ export type { Schedule, ExecutionMode, ExecuteResult, ExecuteScheduleOptions, ExecuteScheduleOutcome, ExecuteScheduleSkipped, AppScheduleBinding, AppScheduleLaunchDecision, AppScheduleLauncher, AppScheduleOwner, AppScheduleSettle, AppScheduleChildExit, AppScheduleSkipRecord, AppScheduleTemplate, AppScheduleWrite, ScheduleTrigger, DaemonStatus, UpdateOptions, StartDaemonResult, CronStoreErrorCode, ScheduleStore, ScheduleStoreLock, ScheduleStoreUpdate, ClaimOccurrenceOptions, ClaimOccurrenceResult, RecordFinishedOptions, RecordStartedOptions, };
7
+ export { CronStoreError };
8
+ export type { BuiltinScheduleDef };
9
+ export { BUILTIN_SCHEDULES, getProjectRoot, recognizeBuiltinRow };
3
10
  export declare function getLocalTimestamp(): string;
4
- export declare function logUsage(...args: string[]): void;
5
- export declare function getProjectRoot(): string;
11
+ export declare function logUsage(dirOrMessage?: string, ...args: string[]): void;
12
+ export declare function acquireWorkspaceLock(workspacePath: string, timeout?: number): ScheduleStoreLock;
13
+ export declare function releaseWorkspaceLock(owner: ScheduleStoreLock): boolean;
14
+ export declare function migrateLegacyMemoryDebounceSchedule(workspacePath?: string): void;
6
15
  export declare function normalizeMode(mode: string): ExecutionMode;
16
+ export declare function effectiveEnabled(schedule: Pick<Schedule, 'enabled' | 'app'>): boolean;
17
+ export declare function createScheduleStore(workspacePath?: string): ScheduleStore;
7
18
  export declare function loadSchedules(dir?: string): Schedule[];
8
19
  export declare function saveSchedules(schedules: Schedule[], dir?: string): void;
9
- export declare function acquireLock(timeout?: number): Promise<boolean>;
10
- export declare function releaseLock(): void;
20
+ export declare function getRemovedBuiltins(dir?: string): string[];
21
+ export declare function seedBuiltinSchedules(dir?: string): string[];
22
+ declare function recognizeBuiltinRow(schedule: Schedule): BuiltinScheduleDef | undefined;
23
+ export declare function acquireLock(timeout?: number, dir?: string): Promise<boolean>;
24
+ export declare function releaseLock(dir?: string): void;
25
+ export declare function releaseRunLock(scheduleId: string, leaseId: string, dir?: string): boolean;
11
26
  export declare function shouldRunNow(cronExpr: string, now: Date, timezone?: string | null): boolean;
12
27
  export declare function describeCron(cronExpr: string): string;
13
28
  export declare function calculateNextRun(cronExpr: string, timezone?: string | null): string | null;
14
- export declare function isDaemonRunning(dir?: string): boolean;
15
- export declare function startDaemon(dir?: string): number;
16
- export declare function stopDaemon(dir?: string): boolean;
17
- export declare function ensureDaemonRunning(dir?: string): void;
29
+ type DaemonProcessProbe = {
30
+ isAlive: (pid: number) => boolean | 'unknown';
31
+ getCommandLine: (pid: number) => string | null;
32
+ spawnImpl?: typeof spawn;
33
+ };
34
+ export declare function isDaemonRunning(dir?: string, probe?: DaemonProcessProbe): boolean;
35
+ export declare function startDaemon(dir?: string, probe?: DaemonProcessProbe): number;
36
+ export declare function stopDaemon(dir?: string, probe?: DaemonProcessProbe): boolean;
37
+ export declare function startDaemonSafe(dir?: string, probe?: DaemonProcessProbe): StartDaemonResult;
38
+ export declare function ensureDaemonRunning(dir?: string, probe?: DaemonProcessProbe): void;
18
39
  export declare function getDaemonStatus(dir?: string): DaemonStatus;
19
- export declare function executeSchedule(schedule: Schedule, dir?: string): Promise<ExecuteResult>;
40
+ export declare function executeSchedule(schedule: Schedule, options?: ExecuteScheduleOptions): Promise<ExecuteScheduleOutcome>;
41
+ export declare function isHighFrequencyCron(cronExpr: string, now: Date, timezone?: string | null): boolean;
42
+ export declare const SCHEDULE_RUN_SWEEP_INTERVAL_MS: number;
43
+ export interface ScheduleRunSweepResult {
44
+ lost: number;
45
+ logsRemoved: number;
46
+ deleted: number;
47
+ tailsCleared: number;
48
+ }
49
+ export declare function sweepScheduleRuns(options?: {
50
+ dir?: string;
51
+ now?: Date;
52
+ }): ScheduleRunSweepResult;
53
+ export declare function getLocalMinuteKey(now: Date, timezone?: string | null): string;
54
+ export declare function buildOccurrenceKey(cronExpression: string, scheduledMinute: string): string;
20
55
  export declare function daemonTick(dir?: string): Promise<void>;
56
+ export { createCronRuntime, CRON_RUNTIME_PROCESS_LEASE_FILENAME, scheduledPeriodicAvailability, } from './runtime';
57
+ export type { CronRuntimeAdmissionContext, CronRuntimeBeforeExecutorAdmission, CronRuntime, CronRuntimeExecutor, CronRuntimeFenceResult, CronRuntimeFenceToken, CronRuntimeOptions, CronRuntimeProcessLeaseProvider, CronRuntimeScheduleResult, CronRuntimeScheduleResultStatus, CronRuntimeRole, CronRuntimeShouldRunNow, CronRuntimeSnapshot, CronRuntimeStatus, CronRuntimeStopResult, CronRuntimeTickResult, CronRuntimeTickSkipReason, CronRuntimeTestHooks, CronRuntimeWorkspace, CronRuntimeWorkspaceState, CronRuntimeWorkspaceStatus, CronRuntimeWorkspaceTickResult, CronRuntimeStoreFactory, } from './runtime';
21
58
  export declare function runDaemonForeground(dir?: string): void;
22
59
  export declare function addSchedule(cron: string, command: string, options: {
23
60
  name?: string;
@@ -26,6 +63,8 @@ export declare function addSchedule(cron: string, command: string, options: {
26
63
  dir?: string;
27
64
  timeout?: string;
28
65
  allowConcurrent?: boolean;
66
+ model?: string;
67
+ provider?: string;
29
68
  }, dataDir?: string): Schedule;
30
69
  export declare function removeSchedule(id: string, dir?: string): Schedule;
31
70
  export declare function enableSchedule(id: string, dir?: string): Schedule;
@@ -38,7 +77,9 @@ export declare const DATA_PATHS: {
38
77
  DATA_DIR: string;
39
78
  SCHEDULES_FILE: string;
40
79
  LOG_FILE: string;
80
+ LOCK_FILE: string;
41
81
  USAGE_LOG_FILE: string;
42
82
  PID_FILE: string;
83
+ BUILTINS_META_FILE: string;
43
84
  };
44
- //# sourceMappingURL=engine.d.ts.map
85
+