@crewx/cron 0.1.10-rc.195 → 0.1.10-rc.196

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/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var w=exports&&exports.__createBinding||(Object.create?(function(t,n,s,o){if(o===void 0)o=s;var e=Object.getOwnPropertyDescriptor(n,s);if(!e||("get"in e?!n.__esModule:e.writable||e.configurable)){e={enumerable:true,get:function(){return n[s]}}}Object.defineProperty(t,o,e)}):(function(t,n,s,o){if(o===void 0)o=s;t[o]=n[s]}));var S=exports&&exports.__setModuleDefault||(Object.create?(function(t,n){Object.defineProperty(t,"default",{enumerable:true,value:n})}):function(t,n){t["default"]=n});var p=exports&&exports.__importStar||(function(){var t=function(n){t=Object.getOwnPropertyNames||function(s){var o=[];for(var e in s)if(Object.prototype.hasOwnProperty.call(s,e))o[o.length]=e;return o};return t(n)};return function(n){if(n&&n.__esModule)return n;var s={};if(n!=null){for(var o=t(n),e=0;e<o.length;e++)if(o[e]!=="default")w(s,n,o[e])}S(s,n);return s}})();Object.defineProperty(exports,"__esModule",{value:true});exports.CRON_RUNTIME_LIFECYCLE_MANAGED=void 0;exports.formatDisplayTimestamp=m;exports.main=b;const f=p(require("fs"));const h=p(require("path"));let _="unknown";try{const t=f.existsSync(h.join(__dirname,"package.json"))?h.join(__dirname,"package.json"):h.join(__dirname,"..","package.json");const n=JSON.parse(f.readFileSync(t,"utf-8"));if(n?.version)_=String(n.version)}catch{}async function C(){try{return await Promise.resolve().then(()=>p(require("@crewx/shared/skill-tracer")))}catch{return null}}const a=require("./src/engine");exports.CRON_RUNTIME_LIFECYCLE_MANAGED="CRON_RUNTIME_LIFECYCLE_MANAGED";function $(t){const n=new Error(`${exports.CRON_RUNTIME_LIFECYCLE_MANAGED}: cron ${t} is managed by the CrewX server runtime; start the server instead`);n.code=exports.CRON_RUNTIME_LIFECYCLE_MANAGED;return n}function i(t,n,s){for(let o=0;o<t.length;o++){const e=t[o];if(!e)continue;if(e===n||s&&e===s){return t[o+1]}if(e.startsWith(n+"=")){return e.slice(n.length+1)}if(s&&e.startsWith(s+"=")){return e.slice(s.length+1)}}return void 0}function d(t,n,s){return t.includes(n)||(s?t.includes(s):false)}function E(){const t=h.join(__dirname,"..","SKILL.md");if(f.existsSync(t)){process.stdout.write(f.readFileSync(t,"utf-8"))}else{console.log("No SKILL.md found. Use --help for usage.")}}function m(t){const n=t.toISOString();return`${n.slice(0,10)} ${n.slice(11,19)} UTC`}function v(){console.log(`
2
+ "use strict";var S=exports&&exports.__createBinding||(Object.create?(function(s,o,t,n){if(n===void 0)n=t;var e=Object.getOwnPropertyDescriptor(o,t);if(!e||("get"in e?!o.__esModule:e.writable||e.configurable)){e={enumerable:true,get:function(){return o[t]}}}Object.defineProperty(s,n,e)}):(function(s,o,t,n){if(n===void 0)n=t;s[n]=o[t]}));var C=exports&&exports.__setModuleDefault||(Object.create?(function(s,o){Object.defineProperty(s,"default",{enumerable:true,value:o})}):function(s,o){s["default"]=o});var h=exports&&exports.__importStar||(function(){var s=function(o){s=Object.getOwnPropertyNames||function(t){var n=[];for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e))n[n.length]=e;return n};return s(o)};return function(o){if(o&&o.__esModule)return o;var t={};if(o!=null){for(var n=s(o),e=0;e<n.length;e++)if(n[e]!=="default")S(t,o,n[e])}C(t,o);return t}})();Object.defineProperty(exports,"__esModule",{value:true});exports.CRON_RUNTIME_LIFECYCLE_MANAGED=void 0;exports.formatDisplayTimestamp=m;exports.main=b;const f=h(require("fs"));const p=h(require("path"));let _="unknown";try{const s=f.existsSync(p.join(__dirname,"package.json"))?p.join(__dirname,"package.json"):p.join(__dirname,"..","package.json");const o=JSON.parse(f.readFileSync(s,"utf-8"));if(o?.version)_=String(o.version)}catch{}async function E(){try{return await Promise.resolve().then(()=>h(require("@crewx/shared/skill-tracer")))}catch{return null}}const N=require("@crewx/sdk");const a=require("./src/engine");exports.CRON_RUNTIME_LIFECYCLE_MANAGED="CRON_RUNTIME_LIFECYCLE_MANAGED";function y(s,o){if(s==="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(s==="APP_ROW_INVALID")return"This App schedule is not in its managed form, so it was not run.";if(s==="MODE_UNSUPPORTED")return`Unsupported schedule mode: ${o.mode}`;return"A desktop update is draining active work; cannot start a new schedule run right now."}function v(s){return s.app!==void 0?(0,N.appScheduleCommandLabel)(s.app):s.command}function $(s){const o=new Error(`${exports.CRON_RUNTIME_LIFECYCLE_MANAGED}: cron ${s} is managed by the CrewX server runtime; start the server instead`);o.code=exports.CRON_RUNTIME_LIFECYCLE_MANAGED;return o}function i(s,o,t){for(let n=0;n<s.length;n++){const e=s[n];if(!e)continue;if(e===o||t&&e===t){return s[n+1]}if(e.startsWith(o+"=")){return e.slice(o.length+1)}if(t&&e.startsWith(t+"=")){return e.slice(t.length+1)}}return void 0}function d(s,o,t){return s.includes(o)||(t?s.includes(t):false)}function O(){const s=p.join(__dirname,"..","SKILL.md");if(f.existsSync(s)){process.stdout.write(f.readFileSync(s,"utf-8"))}else{console.log("No SKILL.md found. Use --help for usage.")}}function m(s){const o=s.toISOString();return`${o.slice(0,10)} ${o.slice(11,19)} UTC`}function w(){console.log(`
3
3
  @crewx/cron@${_} - Cron-based task scheduler for AI agents
4
4
 
5
5
  Usage:
@@ -30,7 +30,7 @@ Examples:
30
30
  cron start
31
31
 
32
32
  For detailed usage guide: cron usage
33
- `)}async function b(t){const n=t??process.argv.slice(2);const s=n[0];if(d(n,"--version")){console.log(_);return}if(!s||s==="help"||d(n,"--help","-h")){v();return}switch(s){case"usage":{E();break}case"add":{const o=[];for(let u=1;u<n.length;u++){const g=n[u];if(!g)continue;if(g.startsWith("-")){if(["--name","-n","--mode","-m","--timezone","-t","--dir","-d","--timeout","--model","--provider"].includes(g)){u++}continue}o.push(g)}if(o.length<2){console.error("Usage: cron add <schedule> <command> [--name <name>] [--mode <mode>] [--model <model>] [--provider <provider>]");process.exit(1)}const e=o[0];const c=o.slice(1).join(" ");const r=n.slice(1);const l=(0,a.addSchedule)(e,c,{name:i(r,"--name","-n"),mode:i(r,"--mode","-m"),timezone:i(r,"--timezone","-t"),dir:i(r,"--dir","-d"),timeout:i(r,"--timeout"),allowConcurrent:d(r,"--allow-concurrent"),model:i(r,"--model"),provider:i(r,"--provider")});console.log(`Schedule created: ${l.id}`);console.log(`Cron: ${e} (${(0,a.describeCron)(e)})`);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: ${m(new Date(l.next_run))}`);break}case"list":case"ls":{const o=d(n,"--json");const e=(0,a.loadSchedules)();if(o){console.log(JSON.stringify(e,null,2));return}if(e.length===0){console.log("No schedules found.");return}console.log(`
33
+ `)}async function b(s){const o=s??process.argv.slice(2);const t=o[0];if(d(o,"--version")){console.log(_);return}if(!t||t==="help"||d(o,"--help","-h")){w();return}switch(t){case"usage":{O();break}case"add":{const n=[];for(let u=1;u<o.length;u++){const g=o[u];if(!g)continue;if(g.startsWith("-")){if(["--name","-n","--mode","-m","--timezone","-t","--dir","-d","--timeout","--model","--provider"].includes(g)){u++}continue}n.push(g)}if(n.length<2){console.error("Usage: cron add <schedule> <command> [--name <name>] [--mode <mode>] [--model <model>] [--provider <provider>]");process.exit(1)}const e=n[0];const c=n.slice(1).join(" ");const r=o.slice(1);const l=(0,a.addSchedule)(e,c,{name:i(r,"--name","-n"),mode:i(r,"--mode","-m"),timezone:i(r,"--timezone","-t"),dir:i(r,"--dir","-d"),timeout:i(r,"--timeout"),allowConcurrent:d(r,"--allow-concurrent"),model:i(r,"--model"),provider:i(r,"--provider")});console.log(`Schedule created: ${l.id}`);console.log(`Cron: ${e} (${(0,a.describeCron)(e)})`);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: ${m(new Date(l.next_run))}`);break}case"list":case"ls":{const n=d(o,"--json");const e=(0,a.loadSchedules)();if(n){console.log(JSON.stringify(e,null,2));return}if(e.length===0){console.log("No schedules found.");return}console.log(`
34
34
  Schedules (${e.length}):
35
- `);console.log("| ID | Name | Cron | Status | Command |");console.log("|--------|----------------|-------------|--------|----------------------------|");for(const c of e){const r=c.enabled?"ON ":"OFF";const l=(c.name??"-").substring(0,14).padEnd(14);const u=c.cron.substring(0,11).padEnd(11);const g=c.command.substring(0,26).padEnd(26);console.log(`| ${c.id} | ${l} | ${u} | ${r} | ${g} |`)}console.log("");break}case"remove":case"rm":{const o=n[1];if(!o){console.error("Usage: cron remove <id>");process.exit(1)}try{const e=(0,a.removeSchedule)(o);console.log(`Removed schedule: ${o}`);console.log(`Cron: ${e.cron}`);console.log(`Command: ${e.command}`)}catch(e){const c=e;console.error(c.message);process.exit(1)}break}case"enable":{const o=n[1];if(!o){console.error("Usage: cron enable <id>");process.exit(1)}try{(0,a.enableSchedule)(o);console.log(`Enabled schedule: ${o}`)}catch(e){const c=e;console.error(c.message);process.exit(1)}break}case"disable":{const o=n[1];if(!o){console.error("Usage: cron disable <id>");process.exit(1)}try{(0,a.disableSchedule)(o);console.log(`Disabled schedule: ${o}`)}catch(e){const c=e;console.error(c.message);process.exit(1)}break}case"update":{const o=n[1];if(!o){console.error("Usage: cron update <id> [--cron <expr>] [--command <cmd>] [--name <name>] [--model <model>] [--clear-model] [--provider <provider>] [--clear-provider]");process.exit(1)}const e=n.slice(1);try{const c={cron:i(e,"--cron","-c"),command:i(e,"--command","-C"),name:i(e,"--name","-n"),mode:i(e,"--mode","-m"),timezone:i(e,"--timezone","-t"),working_directory:i(e,"--dir","-d"),timeout_ms:i(e,"--timeout")?parseInt(i(e,"--timeout"),10):void 0,allow_concurrent:d(e,"--allow-concurrent")?true:d(e,"--no-allow-concurrent")?false:void 0,model:d(e,"--clear-model")?null:i(e,"--model"),provider:d(e,"--clear-provider")?null:i(e,"--provider")};const{schedule:r,changes:l}=(0,a.updateSchedule)(o,c);if(l.length===0){console.log("No changes specified. Use --cron, --command, --name, etc.");process.exit(1)}console.log(`Updated schedule: ${o}`);l.forEach(u=>console.log(` ${u}`));if(r.next_run){console.log(`Next run: ${m(new Date(r.next_run))}`)}}catch(c){const r=c;console.error(r.message);process.exit(1)}break}case"info":{const o=n[1];if(!o){console.error("Usage: cron info <id>");process.exit(1)}const e=d(n,"--json");const c=(0,a.loadSchedules)();const r=c.find(l=>l.id===o);if(!r){console.error(`Schedule not found: ${o}`);process.exit(1)}if(e){console.log(JSON.stringify(r,null,2));return}console.log(`
36
- Schedule: ${r.id}`);console.log("\u2500".repeat(40));console.log(`Name: ${r.name??"-"}`);console.log(`Cron: ${r.cron} (${(0,a.describeCron)(r.cron)})`);console.log(`Command: ${r.command}`);console.log(`Mode: ${r.mode}`);console.log(`Model: ${r.model??"(agent default)"}`);console.log(`Provider: ${r.provider??"(agent default)"}`);console.log(`Status: ${r.enabled?"Enabled":"Disabled"}`);console.log(`Timezone: ${r.timezone??"Local"}`);console.log(`Working Dir: ${r.working_directory??"Project root"}`);console.log(`Timeout: ${r.timeout_ms/1e3}s`);console.log(`Allow Concurrent: ${r.allow_concurrent?"Yes":"No"}`);console.log("\u2500".repeat(40));console.log(`Created: ${m(new Date(r.created_at))}`);console.log(`Updated: ${m(new Date(r.updated_at))}`);console.log(`Last Run: ${r.last_run?m(new Date(r.last_run)):"Never"}`);console.log(`Next Run: ${r.next_run?m(new Date(r.next_run)):"Unknown"}`);console.log(`Run Count: ${r.run_count??0}`);console.log("");break}case"run":{const o=n[1];if(!o){console.error("Usage: cron run <id>");process.exit(1)}const e=(0,a.loadSchedules)();const c=e.find(u=>u.id===o);if(!c){console.error(`Schedule not found: ${o}`);process.exit(1)}console.log(`Running schedule: ${o}`);const r=await(0,a.executeSchedule)(c,{trigger:"cron_manual"});if(r.status==="blocked"){console.error("A desktop update is draining active work; cannot start a new schedule run right now.");process.exit(1)}if(r.status==="conflict"){console.error(`Schedule already running (task: ${r.runningTaskId})`);process.exit(1)}console.log(`Task started: ${r.taskId}`);const l=await r.done;console.log(`Result: ${l.success?"Success":"Failed"}`);if(l.error)console.log(`Error: ${l.error}`);break}case"start":{throw $(s)}case"stop":{throw $(s)}case"status":{const o=d(n,"--json");const e=(0,a.getDaemonStatus)();if(o){console.log(JSON.stringify(e,null,2));return}if(e.running&&e.pid){console.log(`Daemon is running (PID: ${e.pid})`);if(e.started_at){console.log(`Started: ${m(new Date(e.started_at))}`)}}else{console.log("Daemon is not running")}console.log(`Schedules: ${e.schedules.enabled}/${e.schedules.total} enabled`);break}case"daemon":{if(d(n,"--foreground")){(0,a.runDaemonForeground)()}else{throw $(s)}break}default:{console.error(`Unknown command: ${s}`);v();process.exit(1)}}}if(require.main===module){const t=process.argv.slice(2);const n=t[0]==="daemon"&&t.includes("--foreground");(n?Promise.resolve(null):C()).then(s=>{const o=s?{skillVersion:s.getOwnSkillVersion(__dirname)}:{};return s?s.run("crewx/cron",()=>b(),o):b()}).catch(s=>{console.error(s.message);process.exit(1)})}
35
+ `);console.log("| ID | Name | Cron | Status | Command |");console.log("|--------|----------------|-------------|--------|----------------------------|");for(const c of e){const r=(0,a.effectiveEnabled)(c)?"ON ":"OFF";const l=(c.name??"-").substring(0,14).padEnd(14);const u=c.cron.substring(0,11).padEnd(11);const g=v(c).substring(0,26).padEnd(26);console.log(`| ${c.id} | ${l} | ${u} | ${r} | ${g} |`)}console.log("");break}case"remove":case"rm":{const n=o[1];if(!n){console.error("Usage: cron remove <id>");process.exit(1)}try{const e=(0,a.removeSchedule)(n);console.log(`Removed schedule: ${n}`);console.log(`Cron: ${e.cron}`);console.log(`Command: ${e.command}`)}catch(e){const c=e;console.error(c.message);process.exit(1)}break}case"enable":{const n=o[1];if(!n){console.error("Usage: cron enable <id>");process.exit(1)}try{(0,a.enableSchedule)(n);console.log(`Enabled schedule: ${n}`)}catch(e){const c=e;console.error(c.message);process.exit(1)}break}case"disable":{const n=o[1];if(!n){console.error("Usage: cron disable <id>");process.exit(1)}try{(0,a.disableSchedule)(n);console.log(`Disabled schedule: ${n}`)}catch(e){const c=e;console.error(c.message);process.exit(1)}break}case"update":{const n=o[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 e=o.slice(1);try{const c={cron:i(e,"--cron","-c"),command:i(e,"--command","-C"),name:i(e,"--name","-n"),mode:i(e,"--mode","-m"),timezone:i(e,"--timezone","-t"),working_directory:i(e,"--dir","-d"),timeout_ms:i(e,"--timeout")?parseInt(i(e,"--timeout"),10):void 0,allow_concurrent:d(e,"--allow-concurrent")?true:d(e,"--no-allow-concurrent")?false:void 0,model:d(e,"--clear-model")?null:i(e,"--model"),provider:d(e,"--clear-provider")?null:i(e,"--provider")};const{schedule:r,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(u=>console.log(` ${u}`));if(r.next_run){console.log(`Next run: ${m(new Date(r.next_run))}`)}}catch(c){const r=c;console.error(r.message);process.exit(1)}break}case"info":{const n=o[1];if(!n){console.error("Usage: cron info <id>");process.exit(1)}const e=d(o,"--json");const c=(0,a.loadSchedules)();const r=c.find(l=>l.id===n);if(!r){console.error(`Schedule not found: ${n}`);process.exit(1)}if(e){console.log(JSON.stringify(r,null,2));return}console.log(`
36
+ Schedule: ${r.id}`);console.log("\u2500".repeat(40));console.log(`Name: ${r.name??"-"}`);console.log(`Cron: ${r.cron} (${(0,a.describeCron)(r.cron)})`);console.log(`Command: ${v(r)}`);console.log(`Mode: ${r.mode}`);console.log(`Model: ${r.model??"(agent default)"}`);console.log(`Provider: ${r.provider??"(agent default)"}`);console.log(`Status: ${(0,a.effectiveEnabled)(r)?"Enabled":"Disabled"}`);if(r.app!==void 0)console.log(`App: ${r.app.appId} (${r.app.actionId}); change it from the App`);console.log(`Timezone: ${r.timezone??"Local"}`);console.log(`Working Dir: ${r.working_directory??"Project root"}`);console.log(`Timeout: ${r.timeout_ms/1e3}s`);console.log(`Allow Concurrent: ${r.allow_concurrent?"Yes":"No"}`);console.log("\u2500".repeat(40));console.log(`Created: ${m(new Date(r.created_at))}`);console.log(`Updated: ${m(new Date(r.updated_at))}`);console.log(`Last Run: ${r.last_run?m(new Date(r.last_run)):"Never"}`);console.log(`Next Run: ${r.next_run?m(new Date(r.next_run)):"Unknown"}`);console.log(`Run Count: ${r.run_count??0}`);console.log("");break}case"run":{const n=o[1];if(!n){console.error("Usage: cron run <id>");process.exit(1)}const e=(0,a.loadSchedules)();const c=e.find(u=>u.id===n);if(!c){console.error(`Schedule not found: ${n}`);process.exit(1)}console.log(`Running schedule: ${n}`);const r=await(0,a.executeSchedule)(c,{trigger:"cron_manual"});if(r.status==="blocked"){console.error(y(r.reason,c));process.exit(1)}if(r.status==="conflict"){console.error(`Schedule already running (task: ${r.runningTaskId})`);process.exit(1)}if(r.status==="skipped"){console.error(`Schedule not run: ${r.reason}`);process.exit(1)}console.log(`Task started: ${r.taskId}`);const l=await r.done;console.log(`Result: ${l.success?"Success":"Failed"}`);if(l.error)console.log(`Error: ${l.error}`);break}case"start":{throw $(t)}case"stop":{throw $(t)}case"status":{const n=d(o,"--json");const e=(0,a.getDaemonStatus)();if(n){console.log(JSON.stringify(e,null,2));return}if(e.running&&e.pid){console.log(`Daemon is running (PID: ${e.pid})`);if(e.started_at){console.log(`Started: ${m(new Date(e.started_at))}`)}}else{console.log("Daemon is not running")}console.log(`Schedules: ${e.schedules.enabled}/${e.schedules.total} enabled`);break}case"daemon":{if(d(o,"--foreground")){(0,a.runDaemonForeground)()}else{throw $(t)}break}default:{console.error(`Unknown command: ${t}`);w();process.exit(1)}}}if(require.main===module){const s=process.argv.slice(2);const o=s[0]==="daemon"&&s.includes("--foreground");(o?Promise.resolve(null):E()).then(t=>{const n=t?{skillVersion:t.getOwnSkillVersion(__dirname)}:{};return t?t.run("crewx/cron",()=>b(),n):b()}).catch(t=>{console.error(t.message);process.exit(1)})}
@@ -1,9 +1,9 @@
1
1
  import { spawn } from 'child_process';
2
2
  import { CronStoreError } from './types';
3
- import type { Schedule, ExecutionMode, ExecuteResult, ExecuteScheduleOptions, ExecuteScheduleOutcome, DaemonStatus, UpdateOptions, StartDaemonResult, CronStoreErrorCode, ScheduleStore, ScheduleStoreLock, ScheduleStoreUpdate, ClaimOccurrenceOptions, ClaimOccurrenceResult, RecordFinishedOptions, RecordStartedOptions } 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
4
  import { BUILTIN_SCHEDULES, getProjectRoot } from './builtins';
5
5
  import type { BuiltinScheduleDef } from './builtins';
6
- export type { Schedule, ExecutionMode, ExecuteResult, ExecuteScheduleOptions, ExecuteScheduleOutcome, DaemonStatus, UpdateOptions, StartDaemonResult, CronStoreErrorCode, ScheduleStore, ScheduleStoreLock, ScheduleStoreUpdate, ClaimOccurrenceOptions, ClaimOccurrenceResult, RecordFinishedOptions, RecordStartedOptions, };
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
7
  export { CronStoreError };
8
8
  export type { BuiltinScheduleDef };
9
9
  export { BUILTIN_SCHEDULES, getProjectRoot };
@@ -13,6 +13,7 @@ export declare function acquireWorkspaceLock(workspacePath: string, timeout?: nu
13
13
  export declare function releaseWorkspaceLock(owner: ScheduleStoreLock): boolean;
14
14
  export declare function migrateLegacyMemoryDebounceSchedule(workspacePath?: string): void;
15
15
  export declare function normalizeMode(mode: string): ExecutionMode;
16
+ export declare function effectiveEnabled(schedule: Pick<Schedule, 'enabled' | 'app'>): boolean;
16
17
  export declare function createScheduleStore(workspacePath?: string): ScheduleStore;
17
18
  export declare function loadSchedules(dir?: string): Schedule[];
18
19
  export declare function saveSchedules(schedules: Schedule[], dir?: string): void;
@@ -39,7 +40,7 @@ export declare function executeSchedule(schedule: Schedule, options?: ExecuteSch
39
40
  export declare function getLocalMinuteKey(now: Date, timezone?: string | null): string;
40
41
  export declare function buildOccurrenceKey(cronExpression: string, scheduledMinute: string): string;
41
42
  export declare function daemonTick(dir?: string): Promise<void>;
42
- export { createCronRuntime, CRON_RUNTIME_PROCESS_LEASE_FILENAME, } from './runtime';
43
+ export { createCronRuntime, CRON_RUNTIME_PROCESS_LEASE_FILENAME, scheduledPeriodicAvailability, } from './runtime';
43
44
  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';
44
45
  export declare function runDaemonForeground(dir?: string): void;
45
46
  export declare function addSchedule(cron: string, command: string, options: {
@@ -1,5 +1,5 @@
1
- "use strict";var Ue=exports&&exports.__createBinding||(Object.create?(function(e,n,t,r){if(r===void 0)r=t;var o=Object.getOwnPropertyDescriptor(n,t);if(!o||("get"in o?!n.__esModule:o.writable||o.configurable)){o={enumerable:true,get:function(){return n[t]}}}Object.defineProperty(e,r,o)}):(function(e,n,t,r){if(r===void 0)r=t;e[r]=n[t]}));var Me=exports&&exports.__setModuleDefault||(Object.create?(function(e,n){Object.defineProperty(e,"default",{enumerable:true,value:n})}):function(e,n){e["default"]=n});var de=exports&&exports.__importStar||(function(){var e=function(n){e=Object.getOwnPropertyNames||function(t){var r=[];for(var o in t)if(Object.prototype.hasOwnProperty.call(t,o))r[r.length]=o;return r};return e(n)};return function(n){if(n&&n.__esModule)return n;var t={};if(n!=null){for(var r=e(n),o=0;o<r.length;o++)if(r[o]!=="default")Ue(t,n,r[o])}Me(t,n);return t}})();Object.defineProperty(exports,"__esModule",{value:true});exports.DATA_PATHS=exports.CRON_RUNTIME_PROCESS_LEASE_FILENAME=exports.createCronRuntime=exports.getProjectRoot=exports.BUILTIN_SCHEDULES=exports.CronStoreError=void 0;exports.getLocalTimestamp=g;exports.logUsage=Ve;exports.acquireWorkspaceLock=G;exports.releaseWorkspaceLock=B;exports.migrateLegacyMemoryDebounceSchedule=nn;exports.normalizeMode=oe;exports.createScheduleStore=D;exports.loadSchedules=rn;exports.saveSchedules=on;exports.getRemovedBuiltins=ve;exports.seedBuiltinSchedules=an;exports.acquireLock=un;exports.releaseLock=ln;exports.releaseRunLock=Ee;exports.shouldRunNow=ke;exports.describeCron=_n;exports.calculateNextRun=j;exports.isDaemonRunning=ue;exports.startDaemon=In;exports.stopDaemon=On;exports.startDaemonSafe=Le;exports.ensureDaemonRunning=Tn;exports.getDaemonStatus=Cn;exports.executeSchedule=Pe;exports.getLocalMinuteKey=Re;exports.buildOccurrenceKey=Ne;exports.daemonTick=le;exports.runDaemonForeground=$n;exports.addSchedule=Ln;exports.removeSchedule=Pn;exports.enableSchedule=Rn;exports.disableSchedule=Nn;exports.updateSchedule=bn;const b=require("child_process");const q=require("crypto");const d=de(require("path"));const u=de(require("fs"));const L=require("./types");Object.defineProperty(exports,"CronStoreError",{enumerable:true,get:function(){return L.CronStoreError}});const k=require("@crewx/sdk");const A=require("./builtins");Object.defineProperty(exports,"BUILTIN_SCHEDULES",{enumerable:true,get:function(){return A.BUILTIN_SCHEDULES}});Object.defineProperty(exports,"getProjectRoot",{enumerable:true,get:function(){return A.getProjectRoot}});const p=d.resolve(process.cwd());const F=d.join(p,".crewx");const je=d.join(F,".cron-data.json");const xe=d.join(F,".cron-daemon.log");const ze=d.join(F,".cron-data.json.lock");const Be=d.join(F,"cron-usage.log");const He=d.join(F,".cron-daemon.pid");const Ke=d.join(F,".cron-builtins.json");function P(e){return d.join(d.resolve(e??p),".crewx")}function ne(e){return d.join(P(e),".cron-data.json")}function fe(e){return d.join(P(e),".cron-data.json.lock")}function We(e){return d.join(P(e),"cron-usage.log")}function z(e){return d.join(P(e),".cron-daemon.pid")}function me(e){return d.join(P(e),".cron-builtins.json")}function qe(e,n,t){const r=(0,k.reserveUpdateAdmission)(e,n,t);if(!r){console.error(`[${g()}] Failed to record update-admission reservation for task ${e}`)}return r}function Ge(e){(0,k.releaseUpdateAdmissionReservation)(e)}function Se(e,n){return d.join(P(n),`.cron-run-${e}.lock`)}const Je=60*1e3;const ge=5e3;const Xe=25;const Ze=3e4;const ye=5e3;function g(){const e=new Date;const n=e.getFullYear();const t=String(e.getMonth()+1).padStart(2,"0");const r=String(e.getDate()).padStart(2,"0");const o=String(e.getHours()).padStart(2,"0");const c=String(e.getMinutes()).padStart(2,"0");const i=String(e.getSeconds()).padStart(2,"0");return`${n}-${t}-${r} ${o}:${c}:${i}`}function Ve(e,...n){const t=s=>s!==void 0&&(s==="."||s===".."||d.isAbsolute(s)||s.includes(d.sep)||s.includes("/")||s.includes("\\")||s.endsWith(".crewx")||(()=>{try{return u.statSync(s).isDirectory()}catch{return false}})());let r;let o;if(n.length>0&&(e===void 0||t(e))){r=e;o=n}else if(n.length===0&&t(e)){r=e;o=[]}else if(n.length===1&&t(n[0])){r=n[0];o=e===void 0?[]:[e]}else{r=void 0;o=e===void 0?n:[e,...n]}U(r);const c=g();const i=o.join(" ");const a=`${c} | [cron] ${i}
2
- `;u.appendFileSync(We(r),a)}function U(e){const n=P(e);if(!u.existsSync(n)){u.mkdirSync(n,{recursive:true})}}function te(e){try{return JSON.parse(u.readFileSync(e,"utf8"))}catch{return null}}const Ye=new Int32Array(new SharedArrayBuffer(4));function Qe(){Atomics.wait(Ye,0,0,Xe)}function he(e){try{const n=JSON.parse(u.readFileSync(e,"utf8"));if(typeof n.token!=="string"||typeof n.pid!=="number"||typeof n.created_at!=="number"){return null}return n}catch{return null}}function G(e,n=ge){const t=d.resolve(e);U(t);const r=fe(t);const o=(0,q.randomUUID)();const c=Date.now()+Math.max(0,n);const i={workspacePath:t,lockPath:r,token:o};while(true){const a={token:o,pid:process.pid,created_at:Date.now()};try{u.writeFileSync(r,JSON.stringify(a),{flag:"wx",mode:384});return i}catch(s){const f=s;if(f.code!=="EEXIST")throw s;const w=he(r);if(w&&Date.now()-w.created_at>Ze){B({...i,token:w.token});continue}if(Date.now()>=c){throw new L.CronStoreError("CRON_STORE_LOCK_TIMEOUT",`Timed out waiting for cron store lock: ${r}`,r)}Qe()}}}function B(e){const n=he(e.lockPath);if(!n||n.token!==e.token)return false;try{u.unlinkSync(e.lockPath);return true}catch(t){const r=t;if(r.code==="ENOENT")return false;throw t}}const re=(0,A.findBuiltinById)("memory-debounce");function en(e){if(!e.includes("/skills/memory-v2/memory-v2.js")){return e}return re.buildCommand()}function nn(e=(0,A.getProjectRoot)()){const n=d.resolve(e);const t=d.join(n,"skills","cron",".cron-data.json");if(!u.existsSync(t)){return}const r=te(t);if(!Array.isArray(r)){return}const o=r.find(s=>s.name===re.name);if(!o){return}const c=D(n);const i=c.list();if(i.some(s=>s.name===re.name)){return}const a={...o,command:en(o.command),updated_at:new Date().toISOString(),next_run:j(o.cron,o.timezone)};c.create(a)}function we(e){if(e.includes("--overdrive")){console.warn("warning: --overdrive in cron command is ignored and may silently override --model")}}function oe(e){if(e==="query")return"query";if(e==="command")return"command";return"execute"}function O(e){return{...e,...e.env?{env:{...e.env}}:{}}}function Z(e){let n;try{n=u.readFileSync(e,"utf8")}catch(r){const o=r;if(o.code==="ENOENT")return[];throw r}let t;try{t=JSON.parse(n)}catch(r){throw new L.CronStoreError("CRON_STORE_CORRUPT",`Cron schedule store is not valid JSON: ${e}`,e)}if(!Array.isArray(t)){throw new L.CronStoreError("CRON_STORE_CORRUPT",`Cron schedule store must contain a top-level array: ${e}`,e)}return t}function tn(e){if(process.platform==="win32")return;try{const n=u.openSync(e,"r");try{u.fsyncSync(n)}finally{u.closeSync(n)}}catch{}}function pe(e,n){const t=d.dirname(e);const r=d.join(t,`.${d.basename(e)}.${process.pid}.${(0,q.randomUUID)()}.tmp`);const o=JSON.stringify(n,null,2);let c;try{c=u.openSync(r,"wx",384);u.writeFileSync(c,o);u.fsyncSync(c);u.closeSync(c);c=void 0;u.renameSync(r,e);tn(t)}finally{if(c!==void 0){try{u.closeSync(c)}catch{}}try{u.unlinkSync(r)}catch{}}}function J(e,n){const t=e.find(r=>r.id===n);if(!t){throw new L.CronStoreError("CRON_SCHEDULE_NOT_FOUND",`Schedule not found: ${n}`)}return t}function M(e,n){const t=G(e);try{const r=ne(e);const o=Z(r);const c=n(o);pe(r,o);return c}finally{B(t)}}function D(e=p){const n=d.resolve(e);const t=P(n);const r=ne(n);const o=fe(n);return{workspacePath:n,dataDir:t,schedulesFile:r,lockFile:o,list(){return Z(r).map(O)},get(c){const i=Z(r).find(a=>a.id===c);return i?O(i):void 0},create(c){return M(n,i=>{if(i.some(a=>a.id===c.id)){throw new L.CronStoreError("CRON_SCHEDULE_EXISTS",`Schedule already exists: ${c.id}`)}i.push(O(c));return O(c)})},update(c,i){return M(n,a=>{const s=J(a,c);if(i.cron!==void 0)s.cron=i.cron;if(i.command!==void 0)s.command=i.command;if(i.mode!==void 0)s.mode=i.mode;if(i.enabled!==void 0)s.enabled=i.enabled;if(i.name!==void 0)s.name=i.name;if(i.working_directory!==void 0)s.working_directory=i.working_directory;if(i.timezone!==void 0)s.timezone=i.timezone;if(i.timeout_ms!==void 0)s.timeout_ms=i.timeout_ms;if(i.allow_concurrent!==void 0)s.allow_concurrent=i.allow_concurrent;if(i.env!==void 0){if(i.env===null)delete s.env;else s.env={...i.env}}if(i.model!==void 0){if(i.model===null)delete s.model;else s.model=i.model}if(i.provider!==void 0){if(i.provider===null)delete s.provider;else s.provider=i.provider}s.updated_at=new Date().toISOString();s.next_run=j(s.cron,s.timezone);return O(s)})},remove(c){return M(n,i=>{const a=i.findIndex(f=>f.id===c);if(a===-1){throw new L.CronStoreError("CRON_SCHEDULE_NOT_FOUND",`Schedule not found: ${c}`)}const[s]=i.splice(a,1);return O(s)})},toggle(c,i){return M(n,a=>{const s=J(a,c);s.enabled=i??!s.enabled;s.updated_at=new Date().toISOString();if(s.enabled){s.next_run=j(s.cron,s.timezone)}return O(s)})},claimOccurrence(c,i){return M(n,a=>{const s=J(a,typeof c==="string"?c:c.id);if(s.last_occurrence_key===i.occurrenceKey){return{claimed:false,schedule:O(s)}}const f=i.startedAt??new Date().toISOString();s.last_started_at=f;s.last_occurrence_key=i.occurrenceKey;s.updated_at=f;return{claimed:true,schedule:O(s)}})},recordStarted(c,i){return M(n,a=>{const s=J(a,typeof c==="string"?c:c.id);const f=typeof i==="string"?{startedAt:i}:i;const w=f?.startedAt??new Date().toISOString();s.last_started_at=w;if(f?.occurrenceKey!==void 0){s.last_occurrence_key=f.occurrenceKey}s.updated_at=w;return O(s)})},recordFinished(c,i){return M(n,a=>{const s=J(a,typeof c==="string"?c:c.id);const f=i?.finishedAt??new Date().toISOString();s.last_run=f;s.run_count=(s.run_count||0)+1;s.next_run=i?.nextRun!==void 0?i.nextRun:j(s.cron,s.timezone);if(i?.outcome!==void 0)s.last_outcome=i.outcome;else if(i?.success!==void 0)s.last_outcome=i.success?"success":"failure";s.updated_at=f;return O(s)})}}}function rn(e){return D(e??p).list()}function on(e,n){const t=d.resolve(n??p);const r=G(t);try{const o=ne(t);Z(o);pe(o,e.map(O))}finally{B(r)}}function _e(e){const n=te(me(e));return{removed_builtins:Array.isArray(n?.removed_builtins)?n.removed_builtins:[]}}function cn(e,n){U(n);const t=me(n);const r=`${t}.tmp`;u.writeFileSync(r,JSON.stringify(e,null,2));u.renameSync(r,t)}function ve(e){return _e(e).removed_builtins}function sn(e,n){const t=_e(n);if(!t.removed_builtins.includes(e)){t.removed_builtins.push(e);cn(t,n)}}function an(e){const n=D(e??p);const t=n.list();const r=new Set(t.map(i=>i.name));const o=new Set(ve(e));const c=[];for(const i of A.BUILTIN_SCHEDULES){if(r.has(i.name))continue;if(o.has(i.builtin_id))continue;const a=new Date().toISOString();const s={id:(0,k.generateId)("cron"),cron:i.cron,command:i.buildCommand(),mode:i.mode,enabled:true,name:i.name,working_directory:null,timezone:null,timeout_ms:6e5,allow_concurrent:false,created_at:a,updated_at:a,run_count:0,next_run:j(i.cron,null)};n.create(s);r.add(i.name);c.push(i.builtin_id)}return c}const ie=new Map;async function un(e=ge,n){const t=d.resolve(n??p);try{ie.set(t,G(t,e));return true}catch(r){if(r instanceof L.CronStoreError&&r.code==="CRON_STORE_LOCK_TIMEOUT")return false;throw r}}function ln(e){const n=d.resolve(e??p);const t=ie.get(n);if(!t)return;ie.delete(n);B(t)}function X(e){return te(e)}function dn(e,n){const t=d.dirname(e);const r=d.join(t,`.${d.basename(e)}.${process.pid}.${(0,q.randomUUID)()}.tmp`);let o;try{o=u.openSync(r,"wx",384);u.writeFileSync(o,JSON.stringify(n));u.fsyncSync(o);u.closeSync(o);o=void 0;u.renameSync(r,e)}finally{if(o!==void 0){try{u.closeSync(o)}catch{}}try{u.unlinkSync(r)}catch{}}}function ce(e,n,t){const r=G(e);try{return t(Se(n,e))}finally{B(r)}}function fn(e){try{return Math.max(0,Date.now()-u.statSync(e).mtimeMs)}catch{return null}}function mn(e,n){if(e.startTime!==null&&n.startTime!==null){return e.startTime===n.startTime}if(e.commandLine!==null&&n.commandLine!==null){return e.commandLine===n.commandLine}return null}function Sn(e,n,t){if(e.phase!=="child"){const a=fn(n);if(a===null)return false;const s=e.hostPid??e.pid;const f=ae(s);return f===false||a>t+ye}const r=e.childPid??e.pid;const o=ae(r);if(o===false)return true;if(o!==true)return false;if(!e.childIdentity)return false;const c=Oe(r);if(!c)return false;const i=mn(e.childIdentity,c);if(i===false)return true;return false}function gn(e,n,t,r){const o=d.resolve(r??p);U(o);const c=Se(e,o);const i=(0,q.randomUUID)();const a=(0,q.randomUUID)();const s={leaseId:i,ownerToken:a,phase:"admitting",hostPid:process.pid,pid:process.pid,taskId:n,startedAt:new Date().toISOString()};return ce(o,e,()=>{for(let w=0;w<2;w++){try{u.writeFileSync(c,JSON.stringify(s),{flag:"wx",mode:384});return{acquired:true,lease:{scheduleId:e,workspacePath:o,lockFile:c,leaseId:i,ownerToken:a,taskId:n}}}catch(R){const T=R;if(T.code!=="EEXIST")throw T;const S=X(c);if(!S){return{acquired:false,runningTaskId:"unknown",reason:"execution_lease"}}if(Sn(S,c,t)){const _=X(c);if(_?.leaseId!==void 0&&_.leaseId!==S.leaseId){continue}try{u.unlinkSync(c)}catch{}continue}return{acquired:false,runningTaskId:S.taskId,reason:"execution_lease"}}}const f=X(c);return{acquired:false,runningTaskId:f?.taskId??"unknown",reason:"execution_lease"}})}function yn(e,n,t){return ce(e.workspacePath,e.scheduleId,r=>{const o=X(r);if(!o||o.leaseId!==e.leaseId||o.ownerToken!==e.ownerToken){return false}dn(r,{...o,phase:"child",pid:n,childPid:n,childIdentity:t});return true})}function Ee(e,n,t){const r=d.resolve(t??p);U(r);return ce(r,e,o=>{const c=X(o);if(!c||c.leaseId!==n)return false;try{u.unlinkSync(o);return true}catch(i){const a=i;if(a.code==="ENOENT")return false;throw i}})}const hn={SUN:0,MON:1,TUE:2,WED:3,THU:4,FRI:5,SAT:6};const wn={JAN:1,FEB:2,MAR:3,APR:4,MAY:5,JUN:6,JUL:7,AUG:8,SEP:9,OCT:10,NOV:11,DEC:12};function H(e,n){const t=e.toUpperCase();if(n===4){const r=hn[t];if(r!==void 0)return r;const o=parseInt(e,10);return o===7?0:o}if(n===3){const r=wn[t];if(r!==void 0)return r}return parseInt(e,10)}function pn(e,n,t){if(e==="*")return true;if(e.includes("/")){const r=e.indexOf("/");const o=e.slice(0,r);const c=parseInt(e.slice(r+1),10);if(isNaN(c)||c<=0)return false;if(o==="*"){return n%c===0}if(o.includes("-")){const a=o.indexOf("-");const s=H(o.slice(0,a),t);const f=H(o.slice(a+1),t);return n>=s&&n<=f&&(n-s)%c===0}const i=H(o,t);return n>=i&&(n-i)%c===0}if(e.includes("-")){const r=e.indexOf("-");const o=H(e.slice(0,r),t);const c=H(e.slice(r+1),t);if(o<=c){return n>=o&&n<=c}return n>=o||n<=c}return H(e,t)===n}function I(e,n,t){return e.split(",").some(r=>pn(r.trim(),n,t))}function K(e){try{Intl.DateTimeFormat("en-US",{timeZone:e});return true}catch{return false}}function ke(e,n,t){let r=n;if(t){if(!K(t)){console.error(`Invalid timezone: ${t}, skipping execution`);return false}else{const C=new Intl.DateTimeFormat("en-US",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:false});const y=C.formatToParts(n);const v=E=>parseInt(y.find(N=>N.type===E)?.value??"0",10);const l=v("year");const m=v("month");const h=v("day");r={getMinutes:()=>v("minute"),getHours:()=>v("hour"),getDate:()=>v("day"),getMonth:()=>v("month")-1,getDay:()=>new Date(l,m-1,h).getDay()}}}const o=e.trim().split(/\s+/);if(o.length!==5){console.error(`Invalid cron expression: ${e}`);return false}const[c,i,a,s,f]=o;const w=r.getMinutes();const R=r.getHours();const T=r.getDate();const S=r.getMonth()+1;const _=r.getDay();return I(c,w,0)&&I(i,R,1)&&I(a,T,2)&&I(s,S,3)&&I(f,_,4)}function _n(e){const n=e.trim().split(/\s+/);if(n.length!==5)return e;const[t,r,o,c,i]=n;if(t==="0"&&r!=="*"&&o==="*"&&c==="*"&&i==="*"){return`Daily at ${r}:00`}if(t!=="*"&&r!=="*"&&o==="*"&&c==="*"&&i==="*"){return`Daily at ${r}:${t.padStart(2,"0")}`}if(e==="* * * * *"){return"Every minute"}if(t==="*/5"&&r==="*"&&o==="*"&&c==="*"&&i==="*"){return"Every 5 minutes"}return e}function se(e,n){if(n&&K(n)){const t=new Intl.DateTimeFormat("en-US",{timeZone:n,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:false,weekday:"short"});const r=t.formatToParts(e);const o=a=>parseInt(r.find(s=>s.type===a)?.value??"0",10);const c=r.find(a=>a.type==="weekday")?.value??"";const i={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6};return{minute:o("minute"),hour:o("hour"),day:o("day"),month:o("month"),weekday:i[c]??e.getDay()}}return{minute:e.getMinutes(),hour:e.getHours(),day:e.getDate(),month:e.getMonth()+1,weekday:e.getDay()}}function vn(e,n){const t=e.toLocaleString("en-US",{timeZone:"UTC"});const r=e.toLocaleString("en-US",{timeZone:n});return(new Date(r).getTime()-new Date(t).getTime())/6e4}function j(e,n){const t=e.trim().split(/\s+/);if(t.length!==5)return null;const[r,o,c,i,a]=t;const s=[];for(let S=0;S<24;S++){if(I(o,S,1))s.push(S)}const f=[];for(let S=0;S<60;S++){if(I(r,S,0))f.push(S)}if(s.length===0||f.length===0)return null;const w=new Date;const R=n&&K(n);const T=se(w,n);for(let S=0;S<=366;S++){const _=new Date(w.getTime()+S*864e5);const C=se(_,n);if(!I(i,C.month,3))continue;if(!I(c,C.day,2))continue;if(!I(a,C.weekday,4))continue;for(const y of s){for(const v of f){if(S===0&&(y<T.hour||y===T.hour&&v<=T.minute)){continue}let l;if(R){const h=vn(_,n);l=new Date(_);l.setUTCHours(y-Math.floor(h/60),v-h%60,0,0)}else{l=new Date(_);l.setHours(y,v,0,0)}if(l.getTime()<=w.getTime())continue;const m=se(l,n);if(m.hour===y&&m.minute===v&&I(c,m.day,2)&&I(i,m.month,3)&&I(a,m.weekday,4)){return l.toISOString()}}}}return null}function x(e){try{const n=u.readFileSync(z(e),"utf8").trim();if(!/^\d+$/.test(n))return null;const t=Number(n);return Number.isSafeInteger(t)&&t>0?t:null}catch{return null}}function De(e,n){U(n);u.writeFileSync(z(n),`${e}
3
- `)}function V(e){try{u.unlinkSync(z(e))}catch{}}function ae(e){try{process.kill(e,0);return true}catch(n){const t=n;return t.code==="ESRCH"?false:"unknown"}}function Ie(e){try{const n=process.platform==="win32"?(0,b.execFileSync)("powershell.exe",["-NoLogo","-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${e}").CommandLine`],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}):(0,b.execFileSync)("ps",["-ww","-p",String(e),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return n.trim()||null}catch{return null}}function En(e){try{const n=process.platform==="win32"?(0,b.execFileSync)("powershell.exe",["-NoLogo","-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${e}").CreationDate.ToUniversalTime().ToString("o")`],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}):(0,b.execFileSync)("ps",["-p",String(e),"-o","lstart="],{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return n.trim()||null}catch{return null}}function Oe(e){const n={commandLine:Ie(e),startTime:En(e)};return n.commandLine!==null||n.startTime!==null?n:null}const W={isAlive:ae,getCommandLine:Ie};function Te(e){const n=e.replace(/\\/g,"/");return process.platform==="win32"?n.toLowerCase():n}function kn(){try{const e=Te(Ce()).split("/").filter(Boolean);const n=e.slice(-3).join("/");return n||null}catch{return null}}function Dn(e){if(!e?.trim())return"unknown";const n=kn();if(!n)return"unknown";const t=Te(e);return t.includes("daemon --foreground")&&t.includes(n)?"running":"stale"}function Ce(){const e=[d.join(__dirname,"..","cli.js"),d.join(__dirname,"..","dist","cli.js")];const n=e.find(t=>u.existsSync(t));if(n){return n}throw new Error(`Cron CLI entrypoint not found: ${e[0]}`)}function Y(e,n=W){const t=x(e);if(!t){V(e);return"stale"}let r;try{r=n.isAlive(t)}catch{r="unknown"}if(!r){V(e);return"stale"}let o;try{o=n.getCommandLine(t)}catch{return"unknown"}const c=Dn(o);if(c==="stale"){V(e)}return c}function ue(e,n=W){return Y(e,n)==="running"}function $e(e,n=b.spawn){if((0,k.isDurablyQuiescing)()){throw new Error("Cannot start cron daemon: a desktop update is draining active work")}U(e);const t=Ce();const r={...process.env};if(process.versions.electron){r.ELECTRON_RUN_AS_NODE="1"}const o=n(process.execPath,[t,"daemon","--foreground"],{cwd:e||void 0,detached:true,stdio:"ignore",windowsHide:true,env:r});if(!o.pid){throw new Error("Failed to start daemon: no PID returned")}o.unref();De(o.pid,e);return o.pid}function In(e,n=W){const t=Y(e,n);if(t==="running"){const r=x(e);if(r)return r;throw new Error("Daemon is already running")}if(t==="unknown"){const r=x(e);throw new Error(`Unable to determine cron daemon liveness (pid=${r??"unknown"}, pidFile=${z(e)}); refusing to start`)}return $e(e,n.spawnImpl)}function On(e,n=W){if(Y(e,n)!=="running")return false;const t=x(e);if(!t)return false;process.kill(t,"SIGTERM");return true}function Le(e,n=W){const t=Y(e,n);if(t==="running"){return{started:false}}if(t==="unknown"){return{started:false,error:`Unable to determine cron daemon liveness (pid=${x(e)??"unknown"}, pidFile=${z(e)}); refusing to start`}}try{const r=$e(e,n.spawnImpl);return{started:true,pid:r}}catch(r){const o=r;return{started:false,error:o.message}}}function Tn(e,n=W){if(ue(e,n))return;console.log("\u26A1 Cron daemon is not running; starting it automatically...");const t=Le(e,n);if(!t.started){console.error("Failed to auto-start daemon:",t.error);process.exit(1)}}function Cn(e){const n=D(e??p).list();const t=n.filter(a=>a.enabled).length;const r=ue(e);const o=r?x(e):null;let c=null;const i=z(e);if(r&&u.existsSync(i)){try{c=u.statSync(i).mtime.toISOString()}catch{c=null}}return{running:r,pid:r?o:null,started_at:c,schedules:{total:n.length,enabled:t}}}async function Pe(e,n){const t=n?.dir;const r=d.resolve(t??p);const o=n?.trigger??"cron";const c=e.timeout_ms||6e5;const i=(0,k.generateId)("tsk");let a;if(!e.allow_concurrent){const l=gn(e.id,i,c,t);if(!l.acquired){console.log(`[${g()}] Schedule ${e.id} already running (task ${l.runningTaskId}), skipping`);return{status:"conflict",runningTaskId:l.runningTaskId,reason:l.reason}}a=l.lease}const s=()=>{if(a){Ee(e.id,a.leaseId,t);a=void 0}Ge(i)};if(!qe(i,e.id,c)){console.log(`[${g()}] Schedule ${e.id} blocked: could not durably record the update-admission reservation`);s();return{status:"blocked",reason:"ADMISSION_UNKNOWN"}}if((0,k.isDurablyQuiescing)()){console.log(`[${g()}] Schedule ${e.id} blocked: a desktop update is draining active work`);s();return{status:"blocked",reason:"UPDATE_QUIESCING"}}try{const l=D(r);const m=new Date().toISOString();if(n?.occurrenceKey!==void 0){const h=l.claimOccurrence(e.id,{occurrenceKey:n.occurrenceKey,startedAt:m});if(!h.claimed){s();console.log(`[${g()}] Schedule ${e.id} occurrence ${n.occurrenceKey} already claimed, skipping`);return{status:"conflict",runningTaskId:"",reason:"occurrence_claim"}}}else{if(l.get(e.id)){l.recordStarted(e.id,{startedAt:m})}}}catch(l){s();throw l}const f=e.working_directory||n?.dir||(0,A.getProjectRoot)();const w=e.mode;const R=w==="execute"?"x":"q";const T=n?.overrides?.model??e.model;const S=n?.overrides?.provider??e.provider;console.log(`[${g()}] Executing schedule ${e.id}: ${e.name??e.cron} (task ${i})`);console.log(`[${g()}] Command: ${e.command}`);const _=(0,k.withoutCrewxRootContext)({...process.env,...e.env,CREWX_TRACE_ID:i});delete _["CLAUDECODE"];if(!e.env||!("CREWX_CONFIG"in e.env)){delete _["CREWX_CONFIG"]}_["CREWX_WORKSPACE"]=f;const C=[R,e.command];if(T){C.push("--model",T)}if(w!=="command"&&S){C.push("--provider",S)}C.push("--metadata",JSON.stringify({trigger:o,schedule_id:e.id}));let y;try{if(w==="command"){y=(0,b.spawn)("sh",["-c",e.command],{cwd:f,stdio:"ignore",windowsHide:true,detached:true,env:_})}else{const l=(0,k.resolveCrewxExecutable)({env:_,cwd:f});if(!l.ok){const N=new Error((0,k.formatCrewxExecutableFailure)(l));Object.assign(N,{code:"CLI_UNRESOLVABLE"});throw N}const m=(0,k.createCrewxChildInvocation)(l,{baseEnv:_});const h=(0,k.resolveWindowsSpawnProgram)({command:m.command,env:m.env,cwd:f,packageName:"crewx",allowShellFallback:true});const E=(0,k.materializeWindowsSpawnProgram)(h,[...m.args,...C]);y=(0,b.spawn)(E.command,E.argv,{cwd:f,stdio:"ignore",windowsHide:E.windowsHide,detached:true,env:m.env,shell:E.shell??false})}await new Promise((l,m)=>{y.once("spawn",()=>l());y.once("error",h=>m(h))})}catch(l){const m=l;console.error(`[${g()}] Schedule ${e.id} failed to spawn: ${m.message}`);s();throw m}if(a&&y.pid){const l=yn(a,y.pid,Oe(y.pid));if(!l){const m=new Error("Cron execution lease was replaced before child ownership was established");console.error(`[${g()}] Schedule ${e.id} failed to hand off its execution lease: ${m.message}`);try{y.kill("SIGTERM")}catch{}s();throw m}}y.unref();const v=new Promise(l=>{let m=false;let h=false;let E;const N=setTimeout(()=>{m=true;console.log(`[${g()}] Schedule ${e.id} timeout, killing process`);try{y.kill("SIGTERM")}catch($){const Q=$;console.error(`Failed to kill process: ${Q.message}`)}E=setTimeout(()=>{try{y.kill("SIGKILL")}catch{}},ye);if(typeof E==="object"&&E!==null&&"unref"in E){E.unref()}if(!h){h=true;l({success:false,error:"Timeout"})}},c);y.on("close",$=>{clearTimeout(N);if(E)clearTimeout(E);s();const Q=new Date().toISOString();const Ae=m?"timeout":$===0?"success":"failure";try{D(r).recordFinished(e.id,{finishedAt:Q,outcome:Ae})}catch(ee){const Fe=ee;if(!(ee instanceof L.CronStoreError&&ee.code==="CRON_SCHEDULE_NOT_FOUND")){console.error(`[${g()}] Failed to record schedule ${e.id} completion: ${Fe.message}`)}}if(m){console.log(`[${g()}] Schedule ${e.id} terminated after timeout`);if(!h){h=true;l({success:false,error:"Timeout"})}}else if($===0){console.log(`[${g()}] Schedule ${e.id} completed successfully`);if(!h){h=true;l({success:true})}}else{console.log(`[${g()}] Schedule ${e.id} failed with code ${$}`);if(!h){h=true;l({success:false,error:`Exit code: ${$}`})}}});y.on("error",$=>{clearTimeout(N);console.error(`[${g()}] Schedule ${e.id} error: ${$.message}`);if(!h){h=true;l({success:false,error:$.message})}})});return{status:"running",taskId:i,done:v}}function Re(e,n){if(!n||!K(n)){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")} ${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}const t=new Intl.DateTimeFormat("en-CA",{timeZone:n,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:false});return t.format(e)}function Ne(e,n){return`${e.trim()}|${n}`}async function le(e){if((0,k.isDurablyQuiescing)()){console.log(`[${g()}] Daemon tick skipped: a desktop update is draining active work`);return}const n=new Date;const t=D(e??p).list();const r=t.filter(o=>o.enabled);if(r.length===0){return}for(const o of r){if(ke(o.cron,n,o.timezone)){const c=Re(n,o.timezone);const i=Ne(o.cron,c);try{await Pe(o,{dir:e,occurrenceKey:i})}catch(a){const s=a;console.error(`[${g()}] Schedule ${o.id} failed to spawn: ${s.message}`)}}}}var be=require("./runtime");Object.defineProperty(exports,"createCronRuntime",{enumerable:true,get:function(){return be.createCronRuntime}});Object.defineProperty(exports,"CRON_RUNTIME_PROCESS_LEASE_FILENAME",{enumerable:true,get:function(){return be.CRON_RUNTIME_PROCESS_LEASE_FILENAME}});function $n(e){De(process.pid,e);let n=false;const t=()=>{if(n)return;n=true;const c=x(e);if(c===process.pid){V(e)}};process.on("SIGTERM",()=>{t();process.exit(0)});process.on("SIGINT",()=>{t();process.exit(0)});process.on("exit",t);console.log(`[${g()}] Cron daemon starting in foreground mode`);console.log(`[${g()}] Check interval: 1 minute`);console.log(`[${g()}] Press Ctrl+C to stop
4
- `);const r=D(e??p).list();const o=r.filter(c=>c.enabled).length;console.log(`[${g()}] Active schedules: ${o}/${r.length}
5
- `);void le(e);setInterval(()=>{void le(e)},Je)}function Ln(e,n,t,r){if(t.timezone&&!K(t.timezone)){throw new Error(`Invalid timezone: ${t.timezone}`)}we(n);const o={id:(0,k.generateId)("cron"),cron:e,command:n,mode:oe(t.mode??"execute"),enabled:true,name:t.name??null,working_directory:t.dir??null,timezone:t.timezone??null,timeout_ms:parseInt(t.timeout??"600000",10),allow_concurrent:t.allowConcurrent??false,created_at:new Date().toISOString(),updated_at:new Date().toISOString(),run_count:0};if(t.model){o.model=t.model}if(t.provider){o.provider=t.provider}o.next_run=j(e,o.timezone);return D(r??p).create(o)}function Pn(e,n){const t=D(n??p).remove(e);const r=(0,A.findBuiltinByName)(t.name);if(r){sn(r.builtin_id,n)}return t}function Rn(e,n){return D(n??p).toggle(e,true)}function Nn(e,n){return D(n??p).toggle(e,false)}function bn(e,n,t){if(n.timezone!==void 0&&n.timezone!==null&&!K(n.timezone)){throw new Error(`Invalid timezone: ${n.timezone}`)}const r=D(t??p);const o=r.get(e);if(!o){throw new Error(`Schedule not found: ${e}`)}const c=[];const i={};if(n.cron!==void 0){i.cron=n.cron;c.push(`cron: ${n.cron}`)}if(n.command!==void 0){we(n.command);i.command=n.command;c.push(`command: ${n.command}`)}if(n.name!==void 0){i.name=n.name;c.push(`name: ${n.name}`)}if(n.mode!==void 0){i.mode=oe(n.mode);c.push(`mode: ${i.mode}`)}if(n.timezone!==void 0){i.timezone=n.timezone;c.push(`timezone: ${n.timezone}`)}if(n.working_directory!==void 0){i.working_directory=n.working_directory;c.push(`working_directory: ${n.working_directory}`)}if(n.timeout_ms!==void 0){i.timeout_ms=n.timeout_ms;c.push(`timeout: ${n.timeout_ms}ms`)}if(n.allow_concurrent!==void 0){i.allow_concurrent=n.allow_concurrent;c.push(`allow_concurrent: ${n.allow_concurrent}`)}if(n.model!==void 0){if(n.model===null){i.model=null;c.push("model: (cleared, reverts to agent default)")}else{i.model=n.model;c.push(`model: ${n.model}`)}}if(n.provider!==void 0){if(n.provider===null){i.provider=null;c.push("provider: (cleared, reverts to agent default)")}else{i.provider=n.provider;c.push(`provider: ${n.provider}`)}}return{schedule:r.update(o.id,i),changes:c}}exports.DATA_PATHS={DATA_DIR:F,SCHEDULES_FILE:je,LOG_FILE:xe,LOCK_FILE:ze,USAGE_LOG_FILE:Be,PID_FILE:He,BUILTINS_META_FILE:Ke};
1
+ "use strict";var Qe=exports&&exports.__createBinding||(Object.create?(function(e,n,t,r){if(r===void 0)r=t;var i=Object.getOwnPropertyDescriptor(n,t);if(!i||("get"in i?!n.__esModule:i.writable||i.configurable)){i={enumerable:true,get:function(){return n[t]}}}Object.defineProperty(e,r,i)}):(function(e,n,t,r){if(r===void 0)r=t;e[r]=n[t]}));var en=exports&&exports.__setModuleDefault||(Object.create?(function(e,n){Object.defineProperty(e,"default",{enumerable:true,value:n})}):function(e,n){e["default"]=n});var Ce=exports&&exports.__importStar||(function(){var e=function(n){e=Object.getOwnPropertyNames||function(t){var r=[];for(var i in t)if(Object.prototype.hasOwnProperty.call(t,i))r[r.length]=i;return r};return e(n)};return function(n){if(n&&n.__esModule)return n;var t={};if(n!=null){for(var r=e(n),i=0;i<r.length;i++)if(r[i]!=="default")Qe(t,n,r[i])}en(t,n);return t}})();Object.defineProperty(exports,"__esModule",{value:true});exports.DATA_PATHS=exports.scheduledPeriodicAvailability=exports.CRON_RUNTIME_PROCESS_LEASE_FILENAME=exports.createCronRuntime=exports.getProjectRoot=exports.BUILTIN_SCHEDULES=exports.CronStoreError=void 0;exports.getLocalTimestamp=y;exports.logUsage=pn;exports.acquireWorkspaceLock=Y;exports.releaseWorkspaceLock=W;exports.migrateLegacyMemoryDebounceSchedule=hn;exports.normalizeMode=de;exports.effectiveEnabled=Q;exports.createScheduleStore=I;exports.loadSchedules=Cn;exports.saveSchedules=In;exports.getRemovedBuiltins=Ue;exports.seedBuiltinSchedules=kn;exports.acquireLock=Tn;exports.releaseLock=vn;exports.releaseRunLock=Fe;exports.shouldRunNow=Me;exports.describeCron=xn;exports.calculateNextRun=M;exports.isDaemonRunning=ye;exports.startDaemon=Wn;exports.stopDaemon=Gn;exports.startDaemonSafe=We;exports.ensureDaemonRunning=qn;exports.getDaemonStatus=Vn;exports.executeSchedule=Ge;exports.getLocalMinuteKey=qe;exports.buildOccurrenceKey=Ve;exports.daemonTick=ge;exports.runDaemonForeground=ct;exports.addSchedule=at;exports.removeSchedule=st;exports.enableSchedule=ut;exports.disableSchedule=dt;exports.updateSchedule=lt;const j=require("child_process");const Z=require("crypto");const m=Ce(require("path"));const f=Ce(require("fs"));const O=require("./types");Object.defineProperty(exports,"CronStoreError",{enumerable:true,get:function(){return O.CronStoreError}});const g=require("@crewx/sdk");const x=require("./builtins");Object.defineProperty(exports,"BUILTIN_SCHEDULES",{enumerable:true,get:function(){return x.BUILTIN_SCHEDULES}});Object.defineProperty(exports,"getProjectRoot",{enumerable:true,get:function(){return x.getProjectRoot}});const w=m.resolve(process.cwd());const H=m.join(w,".crewx");const nn=m.join(H,".cron-data.json");const tn=m.join(H,".cron-daemon.log");const rn=m.join(H,".cron-data.json.lock");const on=m.join(H,"cron-usage.log");const cn=m.join(H,".cron-daemon.pid");const an=m.join(H,".cron-builtins.json");function F(e){return m.join(m.resolve(e??w),".crewx")}function ae(e){return m.join(F(e),".cron-data.json")}function Ie(e){return m.join(F(e),".cron-data.json.lock")}function sn(e){return m.join(F(e),"cron-usage.log")}function K(e){return m.join(F(e),".cron-daemon.pid")}function Ae(e){return m.join(F(e),".cron-builtins.json")}function un(e,n,t){const r=(0,g.reserveUpdateAdmission)(e,n,t);if(!r){console.error(`[${y()}] Failed to record update-admission reservation for task ${e}`)}return r}function dn(e){(0,g.releaseUpdateAdmissionReservation)(e)}function Pe(e,n){return m.join(F(n),`.cron-run-${e}.lock`)}const ln=60*1e3;const ke=5e3;const fn=25;const mn=3e4;const Te=5e3;function y(){const e=new Date;const n=e.getFullYear();const t=String(e.getMonth()+1).padStart(2,"0");const r=String(e.getDate()).padStart(2,"0");const i=String(e.getHours()).padStart(2,"0");const c=String(e.getMinutes()).padStart(2,"0");const o=String(e.getSeconds()).padStart(2,"0");return`${n}-${t}-${r} ${i}:${c}:${o}`}function pn(e,...n){const t=a=>a!==void 0&&(a==="."||a===".."||m.isAbsolute(a)||a.includes(m.sep)||a.includes("/")||a.includes("\\")||a.endsWith(".crewx")||(()=>{try{return f.statSync(a).isDirectory()}catch{return false}})());let r;let i;if(n.length>0&&(e===void 0||t(e))){r=e;i=n}else if(n.length===0&&t(e)){r=e;i=[]}else if(n.length===1&&t(n[0])){r=n[0];i=e===void 0?[]:[e]}else{r=void 0;i=e===void 0?n:[e,...n]}z(r);const c=y();const o=i.join(" ");const s=`${c} | [cron] ${o}
2
+ `;f.appendFileSync(sn(r),s)}function z(e){const n=F(e);if(!f.existsSync(n)){f.mkdirSync(n,{recursive:true})}}function se(e){try{return JSON.parse(f.readFileSync(e,"utf8"))}catch{return null}}const Sn=new Int32Array(new SharedArrayBuffer(4));function yn(){Atomics.wait(Sn,0,0,fn)}function ve(e){try{const n=JSON.parse(f.readFileSync(e,"utf8"));if(typeof n.token!=="string"||typeof n.pid!=="number"||typeof n.created_at!=="number"){return null}return n}catch{return null}}function Y(e,n=ke){const t=m.resolve(e);z(t);const r=Ie(t);const i=(0,Z.randomUUID)();const c=Date.now()+Math.max(0,n);const o={workspacePath:t,lockPath:r,token:i};while(true){const s={token:i,pid:process.pid,created_at:Date.now()};try{f.writeFileSync(r,JSON.stringify(s),{flag:"wx",mode:384});return o}catch(a){const d=a;if(d.code!=="EEXIST")throw a;const l=ve(r);if(l&&Date.now()-l.created_at>mn){W({...o,token:l.token});continue}if(Date.now()>=c){throw new O.CronStoreError("CRON_STORE_LOCK_TIMEOUT",`Timed out waiting for cron store lock: ${r}`,r)}yn()}}}function W(e){const n=ve(e.lockPath);if(!n||n.token!==e.token)return false;try{f.unlinkSync(e.lockPath);return true}catch(t){const r=t;if(r.code==="ENOENT")return false;throw t}}const ue=(0,x.findBuiltinById)("memory-debounce");function _n(e){if(!e.includes("/skills/memory-v2/memory-v2.js")){return e}return ue.buildCommand()}function hn(e=(0,x.getProjectRoot)()){const n=m.resolve(e);const t=m.join(n,"skills","cron",".cron-data.json");if(!f.existsSync(t)){return}const r=se(t);if(!Array.isArray(r)){return}const i=r.find(a=>a.name===ue.name);if(!i){return}const c=I(n);const o=c.list();if(o.some(a=>a.name===ue.name)){return}const s={...i,command:_n(i.command),updated_at:new Date().toISOString(),next_run:M(i.cron,i.timezone)};c.create(s)}function Re(e){if(e.includes("--overdrive")){console.warn("warning: --overdrive in cron command is ignored and may silently override --model")}}function de(e){if(e==="query")return"query";if(e==="command")return"command";return"execute"}function C(e){return{...e,...e.env?{env:{...e.env}}:{}}}function ne(e){let n;try{n=f.readFileSync(e,"utf8")}catch(r){const i=r;if(i.code==="ENOENT")return[];throw r}let t;try{t=JSON.parse(n)}catch(r){throw new O.CronStoreError("CRON_STORE_CORRUPT",`Cron schedule store is not valid JSON: ${e}`,e)}if(!Array.isArray(t)){throw new O.CronStoreError("CRON_STORE_CORRUPT",`Cron schedule store must contain a top-level array: ${e}`,e)}for(const r of t)wn(r,e);return t}const gn=["apps","skills","bundled"];function Q(e){return e.app!==void 0?e.app.enabled===true:e.enabled===true}function wn(e,n){if(typeof e!=="object"||e===null||Array.isArray(e)){throw new O.CronStoreError("CRON_STORE_CORRUPT",`Cron schedule store has a row that is not an object: ${n}`,n)}const t=e;if(t.mode==="app"){throw new O.CronStoreError("CRON_STORE_CORRUPT",`Cron schedule store has a row in the retired app mode: ${n}`,n)}if(t.app!==void 0&&!En(t.app)){throw new O.CronStoreError("CRON_STORE_CORRUPT",`Cron schedule store has a malformed app binding: ${n}`,n)}if(t.last_error_code!==void 0&&(t.app===void 0||!(0,g.isAppScheduleCode)(t.last_error_code))){throw new O.CronStoreError("CRON_STORE_CORRUPT",`Cron schedule store has an error code that is not a managed row's stable code: ${n}`,n)}}function Le(e){if(typeof e!=="object"||e===null)return false;const n=e;return typeof n.appId==="string"&&n.appId.length>0&&typeof n.actionId==="string"&&n.actionId.length>0&&typeof n.source==="string"&&gn.includes(n.source)}function En(e){return Le(e)&&typeof e.enabled==="boolean"}function Ne(e,n){if(n===void 0||n===null)delete e.last_error_code;else e.last_error_code=n}function le(e){return new O.CronStoreError("CRON_SCHEDULE_MANAGED",`CRON_SCHEDULE_MANAGED: ${e.id} is managed by app ${e.app?.appId??"(unknown)"}; change it from the App`)}function Dn(e,n){if(e.app===void 0)return;const t=Object.entries(n).every(([r,i])=>i===void 0||r==="enabled"&&i===false);if(!t)throw le(e)}function On(e){if(process.platform==="win32")return;try{const n=f.openSync(e,"r");try{f.fsyncSync(n)}finally{f.closeSync(n)}}catch{}}function $e(e,n){const t=m.dirname(e);const r=m.join(t,`.${m.basename(e)}.${process.pid}.${(0,Z.randomUUID)()}.tmp`);const i=JSON.stringify(n,null,2);let c;try{c=f.openSync(r,"wx",384);f.writeFileSync(c,i);f.fsyncSync(c);f.closeSync(c);c=void 0;f.renameSync(r,e);On(t)}finally{if(c!==void 0){try{f.closeSync(c)}catch{}}try{f.unlinkSync(r)}catch{}}}function G(e,n){const t=e.find(r=>r.id===n);if(!t){throw new O.CronStoreError("CRON_SCHEDULE_NOT_FOUND",`Schedule not found: ${n}`)}return t}function N(e,n){const t=Y(e);try{const r=ae(e);const i=ne(r);const c=n(i);$e(r,i);return c}finally{W(t)}}function I(e=w){const n=m.resolve(e);const t=F(n);const r=ae(n);const i=Ie(n);return{workspacePath:n,dataDir:t,schedulesFile:r,lockFile:i,list(){return ne(r).map(C)},get(c){const o=ne(r).find(s=>s.id===c);return o?C(o):void 0},create(c){if(c.app!==void 0){throw new O.CronStoreError("CRON_SCHEDULE_MANAGED","CRON_SCHEDULE_MANAGED: an app schedule is created only by the App path")}return N(n,o=>{if(o.some(s=>s.id===c.id)){throw new O.CronStoreError("CRON_SCHEDULE_EXISTS",`Schedule already exists: ${c.id}`)}o.push(C(c));return C(c)})},update(c,o){return N(n,s=>{const a=G(s,c);Dn(a,o);if(o.cron!==void 0)a.cron=o.cron;if(o.command!==void 0)a.command=o.command;if(o.mode!==void 0)a.mode=o.mode;if(o.enabled!==void 0){if(a.app!==void 0)a.app={...a.app,enabled:o.enabled};else a.enabled=o.enabled}if(o.name!==void 0)a.name=o.name;if(o.working_directory!==void 0)a.working_directory=o.working_directory;if(o.timezone!==void 0)a.timezone=o.timezone;if(o.timeout_ms!==void 0)a.timeout_ms=o.timeout_ms;if(o.allow_concurrent!==void 0)a.allow_concurrent=o.allow_concurrent;if(o.env!==void 0){if(o.env===null)delete a.env;else a.env={...o.env}}if(o.model!==void 0){if(o.model===null)delete a.model;else a.model=o.model}if(o.provider!==void 0){if(o.provider===null)delete a.provider;else a.provider=o.provider}a.updated_at=new Date().toISOString();a.next_run=a.app!==void 0&&!a.app.enabled?null:M(a.cron,a.timezone);return C(a)})},remove(c){return N(n,o=>{const s=o.findIndex(d=>d.id===c);if(s===-1){throw new O.CronStoreError("CRON_SCHEDULE_NOT_FOUND",`Schedule not found: ${c}`)}if(o[s].app!==void 0)throw le(o[s]);const[a]=o.splice(s,1);return C(a)})},toggle(c,o){return N(n,s=>{const a=G(s,c);const d=o??!Q(a);const l=new Date().toISOString();if(a.app!==void 0){if(d)throw le(a);a.app={...a.app,enabled:false};a.next_run=null;a.updated_at=l;return C(a)}a.enabled=d;a.updated_at=l;if(a.enabled){a.next_run=M(a.cron,a.timezone)}return C(a)})},setAppSchedule(c,o,s){if(!Le(c))throw new TypeError("setAppSchedule needs an owner with appId, actionId and source");return N(n,a=>{const d=new Date().toISOString();let l=a.find(_=>_.app?.appId===c.appId);const P=l?.app?.enabled===true;if(l===void 0){l={id:(0,g.generateId)("cron"),cron:o.cron,command:g.APP_SCHEDULE_INERT_COMMAND,mode:"command",enabled:false,name:o.name,working_directory:null,timezone:null,timeout_ms:o.timeout_ms,allow_concurrent:false,created_at:d,updated_at:d,run_count:0};a.push(l)}const D=s??l.app?.enabled??false;l.mode="command";l.command=g.APP_SCHEDULE_INERT_COMMAND;l.enabled=false;l.app={appId:c.appId,actionId:c.actionId,source:c.source,enabled:D};l.cron=o.cron;l.timeout_ms=o.timeout_ms;l.name=o.name;l.allow_concurrent=false;l.next_run=D?M(l.cron,l.timezone):null;l.updated_at=d;return{schedule:C(l),started:!P&&D}})},recordSkipped(c,o){if(o.errorCode!==null&&!(0,g.isAppScheduleCode)(o.errorCode)){throw new TypeError("recordSkipped needs a stable error code")}return N(n,s=>{const a=G(s,c);if(a.app===void 0)throw new TypeError("recordSkipped closes only a managed row");const d=o.finishedAt??new Date().toISOString();a.last_run=d;a.last_outcome=o.outcome;Ne(a,o.errorCode);a.updated_at=d;return C(a)})},removeAppSchedule(c){return N(n,o=>{const s=o.findIndex(d=>d.app?.appId===c);if(s===-1)return void 0;const[a]=o.splice(s,1);return C(a)})},claimOccurrence(c,o){return N(n,s=>{const a=G(s,typeof c==="string"?c:c.id);if(a.last_occurrence_key===o.occurrenceKey){return{claimed:false,schedule:C(a)}}const d=o.startedAt??new Date().toISOString();a.last_started_at=d;a.last_occurrence_key=o.occurrenceKey;a.updated_at=d;return{claimed:true,schedule:C(a)}})},recordStarted(c,o){return N(n,s=>{const a=G(s,typeof c==="string"?c:c.id);const d=typeof o==="string"?{startedAt:o}:o;const l=d?.startedAt??new Date().toISOString();a.last_started_at=l;if(d?.occurrenceKey!==void 0){a.last_occurrence_key=d.occurrenceKey}a.updated_at=l;return C(a)})},recordFinished(c,o){if(o?.errorCode!==void 0&&!(0,g.isAppScheduleCode)(o.errorCode)){throw new TypeError("recordFinished needs a stable error code")}return N(n,s=>{const a=G(s,typeof c==="string"?c:c.id);const d=o?.finishedAt??new Date().toISOString();a.last_run=d;a.run_count=(a.run_count||0)+1;a.next_run=o?.nextRun!==void 0?o.nextRun:M(a.cron,a.timezone);if(o?.outcome!==void 0)a.last_outcome=o.outcome;else if(o?.success!==void 0)a.last_outcome=o.success?"success":"failure";if(a.app!==void 0)Ne(a,o?.errorCode);a.updated_at=d;return C(a)})}}}function Cn(e){return I(e??w).list()}function In(e,n){const t=m.resolve(n??w);const r=Y(t);try{const i=ae(t);ne(i);$e(i,e.map(C))}finally{W(r)}}function be(e){const n=se(Ae(e));return{removed_builtins:Array.isArray(n?.removed_builtins)?n.removed_builtins:[]}}function An(e,n){z(n);const t=Ae(n);const r=`${t}.tmp`;f.writeFileSync(r,JSON.stringify(e,null,2));f.renameSync(r,t)}function Ue(e){return be(e).removed_builtins}function Pn(e,n){const t=be(n);if(!t.removed_builtins.includes(e)){t.removed_builtins.push(e);An(t,n)}}function kn(e){const n=I(e??w);const t=n.list();const r=new Set(t.map(o=>o.name));const i=new Set(Ue(e));const c=[];for(const o of x.BUILTIN_SCHEDULES){if(r.has(o.name))continue;if(i.has(o.builtin_id))continue;const s=new Date().toISOString();const a={id:(0,g.generateId)("cron"),cron:o.cron,command:o.buildCommand(),mode:o.mode,enabled:true,name:o.name,working_directory:null,timezone:null,timeout_ms:6e5,allow_concurrent:false,created_at:s,updated_at:s,run_count:0,next_run:M(o.cron,null)};n.create(a);r.add(o.name);c.push(o.builtin_id)}return c}const fe=new Map;async function Tn(e=ke,n){const t=m.resolve(n??w);try{fe.set(t,Y(t,e));return true}catch(r){if(r instanceof O.CronStoreError&&r.code==="CRON_STORE_LOCK_TIMEOUT")return false;throw r}}function vn(e){const n=m.resolve(e??w);const t=fe.get(n);if(!t)return;fe.delete(n);W(t)}function ee(e){return se(e)}function Rn(e,n){const t=m.dirname(e);const r=m.join(t,`.${m.basename(e)}.${process.pid}.${(0,Z.randomUUID)()}.tmp`);let i;try{i=f.openSync(r,"wx",384);f.writeFileSync(i,JSON.stringify(n));f.fsyncSync(i);f.closeSync(i);i=void 0;f.renameSync(r,e)}finally{if(i!==void 0){try{f.closeSync(i)}catch{}}try{f.unlinkSync(r)}catch{}}}function me(e,n,t){const r=Y(e);try{return t(Pe(n,e))}finally{W(r)}}function Ln(e){try{return Math.max(0,Date.now()-f.statSync(e).mtimeMs)}catch{return null}}function Nn(e,n){if(e.startTime!==null&&n.startTime!==null){return e.startTime===n.startTime}if(e.commandLine!==null&&n.commandLine!==null){return e.commandLine===n.commandLine}return null}function $n(e,n,t){if(e.phase!=="child"){const s=Ln(n);if(s===null)return false;const a=e.hostPid??e.pid;const d=Se(a);return d===false||s>t+Te}const r=e.childPid??e.pid;const i=Se(r);if(i===false)return true;if(i!==true)return false;if(!e.childIdentity)return false;const c=He(r);if(!c)return false;const o=Nn(e.childIdentity,c);if(o===false)return true;return false}function bn(e,n,t,r){const i=m.resolve(r??w);z(i);const c=Pe(e,i);const o=(0,Z.randomUUID)();const s=(0,Z.randomUUID)();const a={leaseId:o,ownerToken:s,phase:"admitting",hostPid:process.pid,pid:process.pid,taskId:n,startedAt:new Date().toISOString()};return me(i,e,()=>{for(let l=0;l<2;l++){try{f.writeFileSync(c,JSON.stringify(a),{flag:"wx",mode:384});return{acquired:true,lease:{scheduleId:e,workspacePath:i,lockFile:c,leaseId:o,ownerToken:s,taskId:n}}}catch(P){const D=P;if(D.code!=="EEXIST")throw D;const _=ee(c);if(!_){return{acquired:false,runningTaskId:"unknown",reason:"execution_lease"}}if($n(_,c,t)){const T=ee(c);if(T?.leaseId!==void 0&&T.leaseId!==_.leaseId){continue}try{f.unlinkSync(c)}catch{}continue}return{acquired:false,runningTaskId:_.taskId,reason:"execution_lease"}}}const d=ee(c);return{acquired:false,runningTaskId:d?.taskId??"unknown",reason:"execution_lease"}})}function Un(e,n,t){return me(e.workspacePath,e.scheduleId,r=>{const i=ee(r);if(!i||i.leaseId!==e.leaseId||i.ownerToken!==e.ownerToken){return false}Rn(r,{...i,phase:"child",pid:n,childPid:n,childIdentity:t});return true})}function Fe(e,n,t){const r=m.resolve(t??w);z(r);return me(r,e,i=>{const c=ee(i);if(!c||c.leaseId!==n)return false;try{f.unlinkSync(i);return true}catch(o){const s=o;if(s.code==="ENOENT")return false;throw o}})}const Fn={SUN:0,MON:1,TUE:2,WED:3,THU:4,FRI:5,SAT:6};const Mn={JAN:1,FEB:2,MAR:3,APR:4,MAY:5,JUN:6,JUL:7,AUG:8,SEP:9,OCT:10,NOV:11,DEC:12};function q(e,n){const t=e.toUpperCase();if(n===4){const r=Fn[t];if(r!==void 0)return r;const i=parseInt(e,10);return i===7?0:i}if(n===3){const r=Mn[t];if(r!==void 0)return r}return parseInt(e,10)}function jn(e,n,t){if(e==="*")return true;if(e.includes("/")){const r=e.indexOf("/");const i=e.slice(0,r);const c=parseInt(e.slice(r+1),10);if(isNaN(c)||c<=0)return false;if(i==="*"){return n%c===0}if(i.includes("-")){const s=i.indexOf("-");const a=q(i.slice(0,s),t);const d=q(i.slice(s+1),t);return n>=a&&n<=d&&(n-a)%c===0}const o=q(i,t);return n>=o&&(n-o)%c===0}if(e.includes("-")){const r=e.indexOf("-");const i=q(e.slice(0,r),t);const c=q(e.slice(r+1),t);if(i<=c){return n>=i&&n<=c}return n>=i||n<=c}return q(e,t)===n}function k(e,n,t){return e.split(",").some(r=>jn(r.trim(),n,t))}function V(e){try{Intl.DateTimeFormat("en-US",{timeZone:e});return true}catch{return false}}function Me(e,n,t){let r=n;if(t){if(!V(t)){console.error(`Invalid timezone: ${t}, skipping execution`);return false}else{const b=new Intl.DateTimeFormat("en-US",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:false});const A=b.formatToParts(n);const E=S=>parseInt(A.find(h=>h.type===S)?.value??"0",10);const p=E("year");const $=E("month");const u=E("day");r={getMinutes:()=>E("minute"),getHours:()=>E("hour"),getDate:()=>E("day"),getMonth:()=>E("month")-1,getDay:()=>new Date(p,$-1,u).getDay()}}}const i=e.trim().split(/\s+/);if(i.length!==5){console.error(`Invalid cron expression: ${e}`);return false}const[c,o,s,a,d]=i;const l=r.getMinutes();const P=r.getHours();const D=r.getDate();const _=r.getMonth()+1;const T=r.getDay();return k(c,l,0)&&k(o,P,1)&&k(s,D,2)&&k(a,_,3)&&k(d,T,4)}function xn(e){const n=e.trim().split(/\s+/);if(n.length!==5)return e;const[t,r,i,c,o]=n;if(t==="0"&&r!=="*"&&i==="*"&&c==="*"&&o==="*"){return`Daily at ${r}:00`}if(t!=="*"&&r!=="*"&&i==="*"&&c==="*"&&o==="*"){return`Daily at ${r}:${t.padStart(2,"0")}`}if(e==="* * * * *"){return"Every minute"}if(t==="*/5"&&r==="*"&&i==="*"&&c==="*"&&o==="*"){return"Every 5 minutes"}return e}function pe(e,n){if(n&&V(n)){const t=new Intl.DateTimeFormat("en-US",{timeZone:n,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:false,weekday:"short"});const r=t.formatToParts(e);const i=s=>parseInt(r.find(a=>a.type===s)?.value??"0",10);const c=r.find(s=>s.type==="weekday")?.value??"";const o={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6};return{minute:i("minute"),hour:i("hour"),day:i("day"),month:i("month"),weekday:o[c]??e.getDay()}}return{minute:e.getMinutes(),hour:e.getHours(),day:e.getDate(),month:e.getMonth()+1,weekday:e.getDay()}}function Hn(e,n){const t=e.toLocaleString("en-US",{timeZone:"UTC"});const r=e.toLocaleString("en-US",{timeZone:n});return(new Date(r).getTime()-new Date(t).getTime())/6e4}function M(e,n){const t=e.trim().split(/\s+/);if(t.length!==5)return null;const[r,i,c,o,s]=t;const a=[];for(let _=0;_<24;_++){if(k(i,_,1))a.push(_)}const d=[];for(let _=0;_<60;_++){if(k(r,_,0))d.push(_)}if(a.length===0||d.length===0)return null;const l=new Date;const P=n&&V(n);const D=pe(l,n);for(let _=0;_<=366;_++){const T=new Date(l.getTime()+_*864e5);const b=pe(T,n);if(!k(o,b.month,3))continue;if(!k(c,b.day,2))continue;if(!k(s,b.weekday,4))continue;for(const A of a){for(const E of d){if(_===0&&(A<D.hour||A===D.hour&&E<=D.minute)){continue}let p;if(P){const u=Hn(T,n);p=new Date(T);p.setUTCHours(A-Math.floor(u/60),E-u%60,0,0)}else{p=new Date(T);p.setHours(A,E,0,0)}if(p.getTime()<=l.getTime())continue;const $=pe(p,n);if($.hour===A&&$.minute===E&&k(c,$.day,2)&&k(o,$.month,3)&&k(s,$.weekday,4)){return p.toISOString()}}}}return null}function B(e){try{const n=f.readFileSync(K(e),"utf8").trim();if(!/^\d+$/.test(n))return null;const t=Number(n);return Number.isSafeInteger(t)&&t>0?t:null}catch{return null}}function je(e,n){z(n);f.writeFileSync(K(n),`${e}
3
+ `)}function te(e){try{f.unlinkSync(K(e))}catch{}}function Se(e){try{process.kill(e,0);return true}catch(n){const t=n;return t.code==="ESRCH"?false:"unknown"}}function xe(e){try{const n=process.platform==="win32"?(0,j.execFileSync)("powershell.exe",["-NoLogo","-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${e}").CommandLine`],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}):(0,j.execFileSync)("ps",["-ww","-p",String(e),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return n.trim()||null}catch{return null}}function zn(e){try{const n=process.platform==="win32"?(0,j.execFileSync)("powershell.exe",["-NoLogo","-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${e}").CreationDate.ToUniversalTime().ToString("o")`],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}):(0,j.execFileSync)("ps",["-p",String(e),"-o","lstart="],{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return n.trim()||null}catch{return null}}function He(e){const n={commandLine:xe(e),startTime:zn(e)};return n.commandLine!==null||n.startTime!==null?n:null}const J={isAlive:Se,getCommandLine:xe};function ze(e){const n=e.replace(/\\/g,"/");return process.platform==="win32"?n.toLowerCase():n}function Bn(){try{const e=ze(Be()).split("/").filter(Boolean);const n=e.slice(-3).join("/");return n||null}catch{return null}}function Kn(e){if(!e?.trim())return"unknown";const n=Bn();if(!n)return"unknown";const t=ze(e);return t.includes("daemon --foreground")&&t.includes(n)?"running":"stale"}function Be(){const e=[m.join(__dirname,"..","cli.js"),m.join(__dirname,"..","dist","cli.js")];const n=e.find(t=>f.existsSync(t));if(n){return n}throw new Error(`Cron CLI entrypoint not found: ${e[0]}`)}function re(e,n=J){const t=B(e);if(!t){te(e);return"stale"}let r;try{r=n.isAlive(t)}catch{r="unknown"}if(!r){te(e);return"stale"}let i;try{i=n.getCommandLine(t)}catch{return"unknown"}const c=Kn(i);if(c==="stale"){te(e)}return c}function ye(e,n=J){return re(e,n)==="running"}function Ke(e,n=j.spawn){if((0,g.isDurablyQuiescing)()){throw new Error("Cannot start cron daemon: a desktop update is draining active work")}z(e);const t=Be();const r={...process.env};if(process.versions.electron){r.ELECTRON_RUN_AS_NODE="1"}const i=n(process.execPath,[t,"daemon","--foreground"],{cwd:e||void 0,detached:true,stdio:"ignore",windowsHide:true,env:r});if(!i.pid){throw new Error("Failed to start daemon: no PID returned")}i.unref();je(i.pid,e);return i.pid}function Wn(e,n=J){const t=re(e,n);if(t==="running"){const r=B(e);if(r)return r;throw new Error("Daemon is already running")}if(t==="unknown"){const r=B(e);throw new Error(`Unable to determine cron daemon liveness (pid=${r??"unknown"}, pidFile=${K(e)}); refusing to start`)}return Ke(e,n.spawnImpl)}function Gn(e,n=J){if(re(e,n)!=="running")return false;const t=B(e);if(!t)return false;process.kill(t,"SIGTERM");return true}function We(e,n=J){const t=re(e,n);if(t==="running"){return{started:false}}if(t==="unknown"){return{started:false,error:`Unable to determine cron daemon liveness (pid=${B(e)??"unknown"}, pidFile=${K(e)}); refusing to start`}}try{const r=Ke(e,n.spawnImpl);return{started:true,pid:r}}catch(r){const i=r;return{started:false,error:i.message}}}function qn(e,n=J){if(ye(e,n))return;console.log("\u26A1 Cron daemon is not running; starting it automatically...");const t=We(e,n);if(!t.started){console.error("Failed to auto-start daemon:",t.error);process.exit(1)}}function Vn(e){const n=I(e??w).list();const t=n.filter(s=>Q(s)).length;const r=ye(e);const i=r?B(e):null;let c=null;const o=K(e);if(r&&f.existsSync(o)){try{c=f.statSync(o).mtime.toISOString()}catch{c=null}}return{running:r,pid:r?i:null,started_at:c,schedules:{total:n.length,enabled:t}}}async function Ge(e,n){const t=n?.dir;const r=m.resolve(t??w);const i=n?.trigger??"cron";const c=e.timeout_ms||6e5;const o=(0,g.generateId)("tsk");if(e.app!==void 0){if(e.mode!=="command"||e.command!==g.APP_SCHEDULE_INERT_COMMAND){return{status:"blocked",reason:"APP_ROW_INVALID"}}if(n?.launchApp===void 0)return{status:"blocked",reason:"APP_LAUNCHER_UNAVAILABLE"}}else{if(!rt(e.mode))return{status:"blocked",reason:"MODE_UNSUPPORTED"};if(i==="app_enable")return{status:"blocked",reason:"TRIGGER_UNSUPPORTED"}}let s;if(!e.allow_concurrent){const u=bn(e.id,o,c,t);if(!u.acquired){console.log(`[${y()}] Schedule ${e.id} already running (task ${u.runningTaskId}), skipping`);return{status:"conflict",runningTaskId:u.runningTaskId,reason:u.reason}}s=u.lease}const a=()=>{if(s){Fe(e.id,s.leaseId,t);s=void 0}dn(o)};if(!un(o,e.id,c)){console.log(`[${y()}] Schedule ${e.id} blocked: could not durably record the update-admission reservation`);a();return{status:"blocked",reason:"ADMISSION_UNKNOWN"}}if((0,g.isDurablyQuiescing)()){console.log(`[${y()}] Schedule ${e.id} blocked: a desktop update is draining active work`);a();return{status:"blocked",reason:"UPDATE_QUIESCING"}}try{const u=I(r);const S=new Date().toISOString();if(n?.occurrenceKey!==void 0){const h=u.claimOccurrence(e.id,{occurrenceKey:n.occurrenceKey,startedAt:S});if(!h.claimed){a();console.log(`[${y()}] Schedule ${e.id} occurrence ${n.occurrenceKey} already claimed, skipping`);return{status:"conflict",runningTaskId:"",reason:"occurrence_claim"}}}else{if(u.get(e.id)){u.recordStarted(e.id,{startedAt:S})}}}catch(u){a();throw u}let d;let l;if(e.app!==void 0){let u;try{u=await n.launchApp(e);if(u.kind!=="spawn")it(r,e,u)}catch(S){he(r,e.id,"APP_LAUNCH_FAILED");a();throw S}if(u.kind!=="spawn"){a();const S=u.kind==="refresh"?"APP_SCHEDULE_REFRESHED":u.code;console.log(`[${y()}] Schedule ${e.id} app row ${u.kind}: ${S}`);return{status:"skipped",reason:S,lifecycle:u.kind}}d=u.child;l=typeof u.settle==="function"?u.settle:void 0}const P=e.working_directory||n?.dir||(0,x.getProjectRoot)();const D=e.mode;const _=D==="execute"?"x":"q";const T=n?.overrides?.model??e.model;const b=n?.overrides?.provider??e.provider;console.log(`[${y()}] Executing schedule ${e.id}: ${e.name??e.cron} (task ${o})`);console.log(`[${y()}] Command: ${e.command}`);const A=(0,g.withoutCrewxRootContext)({...process.env,...e.env,CREWX_TRACE_ID:o});delete A["CLAUDECODE"];if(!e.env||!("CREWX_CONFIG"in e.env)){delete A["CREWX_CONFIG"]}A["CREWX_WORKSPACE"]=P;const E=[_,e.command];if(T){E.push("--model",T)}if(D!=="command"&&b){E.push("--provider",b)}E.push("--metadata",JSON.stringify({trigger:i,schedule_id:e.id}));let p;try{if(d!==void 0){p=d;if(p.pid===void 0)throw new Error("App launcher returned a child that did not start")}else if(e.app!==void 0){throw new Error("managed row has no launched child")}else if(D==="command"){p=(0,j.spawn)("sh",["-c",e.command],{cwd:P,stdio:"ignore",windowsHide:true,detached:true,env:A})}else{const u=(0,g.resolveCrewxExecutable)({env:A,cwd:P});if(!u.ok){const R=new Error((0,g.formatCrewxExecutableFailure)(u));Object.assign(R,{code:"CLI_UNRESOLVABLE"});throw R}const S=(0,g.createCrewxChildInvocation)(u,{baseEnv:A});const h=(0,g.resolveWindowsSpawnProgram)({command:S.command,env:S.env,cwd:P,packageName:"crewx",allowShellFallback:true});const v=(0,g.materializeWindowsSpawnProgram)(h,[...S.args,...E]);p=(0,j.spawn)(v.command,v.argv,{cwd:P,stdio:"ignore",windowsHide:v.windowsHide,detached:true,env:S.env,shell:v.shell??false})}if(d===void 0){await new Promise((u,S)=>{p.once("spawn",()=>u());p.once("error",h=>S(h))})}}catch(u){const S=u;console.error(`[${y()}] Schedule ${e.id} failed to spawn: ${S.message}`);if(e.app!==void 0)he(r,e.id,"APP_SPAWN_FAILED");a();throw S}if(s&&p.pid){const u=Un(s,p.pid,He(p.pid));if(!u){const S=new Error("Cron execution lease was replaced before child ownership was established");console.error(`[${y()}] Schedule ${e.id} failed to hand off its execution lease: ${S.message}`);try{p.kill("SIGTERM")}catch{}if(e.app!==void 0)he(r,e.id,"APP_HANDOFF_FAILED");a();throw S}}p.unref();const $=new Promise(u=>{let S=false;let h=false;let v;let R;let Ee=false;const De=()=>{if(R!==void 0||!p.stdout&&!p.stderr)return;R=setTimeout(()=>{Ee=true;p.stdout?.destroy();p.stderr?.destroy()},Xn);if(typeof R==="object"&&R!==null&&"unref"in R){R.unref()}};if(e.app!==void 0){p.once("exit",De);if(p.exitCode!==null||p.signalCode!==null)De()}const Oe=setTimeout(()=>{S=true;console.log(`[${y()}] Schedule ${e.id} timeout, killing process`);try{p.kill("SIGTERM")}catch(L){const ie=L;console.error(`Failed to kill process: ${ie.message}`)}v=setTimeout(()=>{try{p.kill("SIGKILL")}catch{}},Te);if(typeof v==="object"&&v!==null&&"unref"in v){v.unref()}if(!h){h=true;u({success:false,error:"Timeout"})}},c);p.on("close",(L,ie)=>{clearTimeout(Oe);if(v)clearTimeout(v);if(R)clearTimeout(R);a();const U=e.app!==void 0&&!S?Zn({code:L,signal:ie},l,Ee):void 0;const Je=new Date().toISOString();const Xe=S?"timeout":U!==void 0?U.outcome:L===0?"success":"failure";const Ze=e.app===void 0?void 0:S?Jn:U?.outcome==="failure"?U.code:void 0;try{I(r).recordFinished(e.id,{finishedAt:Je,outcome:Xe,errorCode:Ze})}catch(ce){const Ye=ce;if(!(ce instanceof O.CronStoreError&&ce.code==="CRON_SCHEDULE_NOT_FOUND")){console.error(`[${y()}] Failed to record schedule ${e.id} completion: ${Ye.message}`)}}if(S){console.log(`[${y()}] Schedule ${e.id} terminated after timeout`);if(!h){h=true;u({success:false,error:"Timeout"})}}else if(U!==void 0){if(U.outcome==="success"){console.log(`[${y()}] Schedule ${e.id} completed successfully`);if(!h){h=true;u({success:true})}}else{console.log(`[${y()}] Schedule ${e.id} failed with ${U.code}`);if(!h){h=true;u({success:false,error:U.code})}}}else if(L===0){console.log(`[${y()}] Schedule ${e.id} completed successfully`);if(!h){h=true;u({success:true})}}else{console.log(`[${y()}] Schedule ${e.id} failed with code ${L}`);if(!h){h=true;u({success:false,error:`Exit code: ${L}`})}}});p.on("error",L=>{clearTimeout(Oe);console.error(`[${y()}] Schedule ${e.id} error: ${L.message}`);if(!h){h=true;u({success:false,error:L.message})}})});return{status:"running",taskId:o,done:$}}const Jn="APP_TIMEOUT";const Xn=5e3;function Zn(e,n,t){if(e.signal!==null)return X("APP_SIGNALED");if(e.code!==0)return X("APP_EXIT_NONZERO");if(t)return X("APP_STDIO_NOT_DRAINED");if(n===void 0)return X("APP_VERDICT_FAILED");let r;try{r=n(e)}catch{return X("APP_VERDICT_FAILED")}return et(r)}const Yn=64;const Qn=3;function et(e){try{if(typeof e==="object"&&e!==null&&!Array.isArray(e)&&typeof e.then!=="function"){const n=Object.keys(e);const{outcome:t,code:r}=e;if(t==="success"&&n.length===1)return{outcome:"success"};if(t==="failure"&&n.length===2&&n.includes("code")){return(0,g.isAppScheduleCode)(r)?{outcome:"failure",code:r}:_e(e,"APP_OUTPUT_INVALID")}}return _e(e,"APP_VERDICT_FAILED")}catch{return _e(e,"APP_VERDICT_FAILED")}}function _e(e,n){nt(e);return X(n)}const oe=()=>void 0;function nt(e){const n=[{value:e,depth:0}];for(let t=0;t<Yn&&n.length>0;t+=1){const{value:r,depth:i}=n.shift();if(typeof r!=="object"&&typeof r!=="function"||r===null)continue;try{if(Object.getPrototypeOf(r)===Promise.prototype){Promise.prototype.then.call(r,oe,oe);continue}const c=r.then;if(typeof c==="function"){c.call(r,oe,oe);continue}if(i<Qn){for(const o of Object.keys(r)){const s=Object.getOwnPropertyDescriptor(r,o);if(s!==void 0&&"value"in s)n.push({value:s.value,depth:i+1})}}}catch{}}}function X(e){return{outcome:"failure",code:e}}const tt=["query","execute","command"];function rt(e){return tt.includes(e)}function ot(e){return{appId:e.appId,actionId:e.actionId,source:e.source}}function it(e,n,t){const r=I(e);const i=ot(n.app);const c={cron:n.cron,timeout_ms:n.timeout_ms,name:n.name};switch(t.kind){case"skip":{const o=r.setAppSchedule(i,c).schedule;r.recordSkipped(o.id,{outcome:t.code,errorCode:t.code});return}case"disable":{const o=r.setAppSchedule(i,c,false).schedule;r.recordSkipped(o.id,{outcome:t.code,errorCode:t.code});return}case"remove":r.removeAppSchedule(i.appId);return;case"refresh":{const o=r.setAppSchedule(t.owner,t.template).schedule;r.recordSkipped(o.id,{outcome:"APP_SCHEDULE_REFRESHED",errorCode:null});return}}}function he(e,n,t){try{I(e).recordSkipped(n,{outcome:t,errorCode:t})}catch(r){if(r instanceof O.CronStoreError&&r.code==="CRON_SCHEDULE_NOT_FOUND")return;console.error(`[${y()}] Schedule ${n} could not record its ${t} outcome: ${r.message}`)}}function qe(e,n){if(!n||!V(n)){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")} ${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}const t=new Intl.DateTimeFormat("en-CA",{timeZone:n,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:false});return t.format(e)}function Ve(e,n){return`${e.trim()}|${n}`}async function ge(e){if((0,g.isDurablyQuiescing)()){console.log(`[${y()}] Daemon tick skipped: a desktop update is draining active work`);return}const n=new Date;const t=I(e??w).list();const r=t.filter(i=>Q(i));if(r.length===0){return}for(const i of r){if(Me(i.cron,n,i.timezone)){const c=qe(n,i.timezone);const o=Ve(i.cron,c);try{await Ge(i,{dir:e,occurrenceKey:o})}catch(s){const a=s;console.error(`[${y()}] Schedule ${i.id} failed to spawn: ${a.message}`)}}}}var we=require("./runtime");Object.defineProperty(exports,"createCronRuntime",{enumerable:true,get:function(){return we.createCronRuntime}});Object.defineProperty(exports,"CRON_RUNTIME_PROCESS_LEASE_FILENAME",{enumerable:true,get:function(){return we.CRON_RUNTIME_PROCESS_LEASE_FILENAME}});Object.defineProperty(exports,"scheduledPeriodicAvailability",{enumerable:true,get:function(){return we.scheduledPeriodicAvailability}});function ct(e){je(process.pid,e);let n=false;const t=()=>{if(n)return;n=true;const c=B(e);if(c===process.pid){te(e)}};process.on("SIGTERM",()=>{t();process.exit(0)});process.on("SIGINT",()=>{t();process.exit(0)});process.on("exit",t);console.log(`[${y()}] Cron daemon starting in foreground mode`);console.log(`[${y()}] Check interval: 1 minute`);console.log(`[${y()}] Press Ctrl+C to stop
4
+ `);const r=I(e??w).list();const i=r.filter(c=>Q(c)).length;console.log(`[${y()}] Active schedules: ${i}/${r.length}
5
+ `);void ge(e);setInterval(()=>{void ge(e)},ln)}function at(e,n,t,r){if(t.timezone&&!V(t.timezone)){throw new Error(`Invalid timezone: ${t.timezone}`)}Re(n);const i={id:(0,g.generateId)("cron"),cron:e,command:n,mode:de(t.mode??"execute"),enabled:true,name:t.name??null,working_directory:t.dir??null,timezone:t.timezone??null,timeout_ms:parseInt(t.timeout??"600000",10),allow_concurrent:t.allowConcurrent??false,created_at:new Date().toISOString(),updated_at:new Date().toISOString(),run_count:0};if(t.model){i.model=t.model}if(t.provider){i.provider=t.provider}i.next_run=M(e,i.timezone);return I(r??w).create(i)}function st(e,n){const t=I(n??w).remove(e);const r=(0,x.findBuiltinByName)(t.name);if(r){Pn(r.builtin_id,n)}return t}function ut(e,n){return I(n??w).toggle(e,true)}function dt(e,n){return I(n??w).toggle(e,false)}function lt(e,n,t){if(n.timezone!==void 0&&n.timezone!==null&&!V(n.timezone)){throw new Error(`Invalid timezone: ${n.timezone}`)}const r=I(t??w);const i=r.get(e);if(!i){throw new Error(`Schedule not found: ${e}`)}const c=[];const o={};if(n.cron!==void 0){o.cron=n.cron;c.push(`cron: ${n.cron}`)}if(n.command!==void 0){Re(n.command);o.command=n.command;c.push(`command: ${n.command}`)}if(n.name!==void 0){o.name=n.name;c.push(`name: ${n.name}`)}if(n.mode!==void 0){o.mode=de(n.mode);c.push(`mode: ${o.mode}`)}if(n.timezone!==void 0){o.timezone=n.timezone;c.push(`timezone: ${n.timezone}`)}if(n.working_directory!==void 0){o.working_directory=n.working_directory;c.push(`working_directory: ${n.working_directory}`)}if(n.timeout_ms!==void 0){o.timeout_ms=n.timeout_ms;c.push(`timeout: ${n.timeout_ms}ms`)}if(n.allow_concurrent!==void 0){o.allow_concurrent=n.allow_concurrent;c.push(`allow_concurrent: ${n.allow_concurrent}`)}if(n.model!==void 0){if(n.model===null){o.model=null;c.push("model: (cleared, reverts to agent default)")}else{o.model=n.model;c.push(`model: ${n.model}`)}}if(n.provider!==void 0){if(n.provider===null){o.provider=null;c.push("provider: (cleared, reverts to agent default)")}else{o.provider=n.provider;c.push(`provider: ${n.provider}`)}}return{schedule:r.update(i.id,o),changes:c}}exports.DATA_PATHS={DATA_DIR:H,SCHEDULES_FILE:nn,LOG_FILE:tn,LOCK_FILE:rn,USAGE_LOG_FILE:on,PID_FILE:cn,BUILTINS_META_FILE:an};
@@ -1,4 +1,4 @@
1
- import type { ProcessLeaseAcquireResult, ProcessLeaseOptions } from '@crewx/sdk';
1
+ import type { AppScheduleAvailability, ProcessLeaseAcquireResult, ProcessLeaseOptions } from '@crewx/sdk';
2
2
  import { shouldRunNow } from './engine';
3
3
  import type { ExecuteScheduleOptions, ExecuteScheduleOutcome, Schedule, ScheduleStore } from './types';
4
4
  export declare const CRON_RUNTIME_PROCESS_LEASE_FILENAME = "cron-runtime-process-lease.json";
@@ -37,6 +37,7 @@ export interface CronRuntimeStatus {
37
37
  workspaces: CronRuntimeWorkspaceStatus[];
38
38
  workspace?: CronRuntimeWorkspaceStatus;
39
39
  }
40
+ export declare function scheduledPeriodicAvailability(status: CronRuntimeStatus): AppScheduleAvailability;
40
41
  export type CronRuntimeScheduleResultStatus = ExecuteScheduleOutcome['status'] | 'error' | 'skipped';
41
42
  export interface CronRuntimeScheduleResult {
42
43
  scheduleId: string;
@@ -1 +1 @@
1
- "use strict";var p=exports&&exports.__createBinding||(Object.create?(function(r,e,s,i){if(i===void 0)i=s;var t=Object.getOwnPropertyDescriptor(e,s);if(!t||("get"in t?!e.__esModule:t.writable||t.configurable)){t={enumerable:true,get:function(){return e[s]}}}Object.defineProperty(r,i,t)}):(function(r,e,s,i){if(i===void 0)i=s;r[i]=e[s]}));var f=exports&&exports.__setModuleDefault||(Object.create?(function(r,e){Object.defineProperty(r,"default",{enumerable:true,value:e})}):function(r,e){r["default"]=e});var k=exports&&exports.__importStar||(function(){var r=function(e){r=Object.getOwnPropertyNames||function(s){var i=[];for(var t in s)if(Object.prototype.hasOwnProperty.call(s,t))i[i.length]=t;return i};return r(e)};return function(e){if(e&&e.__esModule)return e;var s={};if(e!=null){for(var i=r(e),t=0;t<i.length;t++)if(i[t]!=="default")p(s,e,i[t])}f(s,e);return s}})();Object.defineProperty(exports,"__esModule",{value:true});exports.CRON_RUNTIME_PROCESS_LEASE_FILENAME=void 0;exports.createCronRuntime=T;const w=require("node:crypto");const g=k(require("node:path"));const u=require("@crewx/sdk");const c=require("./engine");exports.CRON_RUNTIME_PROCESS_LEASE_FILENAME="cron-runtime-process-lease.json";const l=5e3;const d=new Map;function h(r){const e=r;return{...typeof e?.code==="string"?{code:e.code}:{},message:e?.message instanceof String?e.message.toString():e&&typeof e.message==="string"?e.message:String(r)}}function m(r){return{...r,...r.lastError?{lastError:{...r.lastError}}:{}}}function v(r,e){return`${r}\0${e}`}function b(r){try{return(0,u.resolveProcessLeasePath)(r)}catch{return g.resolve(r)}}function P(r){if(r===void 0)return l;if(!Number.isFinite(r))return l;return Math.max(0,r)}class R{constructor(e={}){this.runtimeToken=Symbol("cron-runtime");this.enabled=false;this.draining=false;this.stopped=false;this.role="standby";this.ownerId=null;this.leaseId=null;this.workspaces=new Map;this.workspaceRevisions=new Map;this.workspaceFences=new Map;this.operations=new Set;this.reconcileQueue=Promise.resolve();this.requestedLeasePath=e.leasePath??exports.CRON_RUNTIME_PROCESS_LEASE_FILENAME;this.resolvedLeasePath=b(this.requestedLeasePath);this.configuredOwnerId=e.ownerId;this.leaseProvider=e.processLease??e.leaseProvider??{acquire:u.acquireProcessLease};this.storeFactory=e.storeFactory??(s=>(0,c.createScheduleStore)(s.path));this.executor=e.executeSchedule??e.executor??c.executeSchedule;this.runPredicate=e.shouldRunNow??c.shouldRunNow;this.testHooks=e.testHooks}nextWorkspaceRevision(e){const s=(this.workspaceRevisions.get(e)??0)+1;this.workspaceRevisions.set(e,s);return s}isWorkspaceFenced(e){return(this.workspaceFences.get(e)?.size??0)>0}setWorkspaceFenceStatus(e,s){const i=this.workspaces.get(e);if(!i)return;i.status={...i.status,fenced:s}}register(e){if(this.stopped||this.draining)return this.status();const s=this.workspaces.get(e.id);const i=s&&s.workspace.path===e.path?s.revision:this.nextWorkspaceRevision(e.id);this.workspaces.set(e.id,{workspace:{...e},revision:i,status:{id:e.id,path:e.path,state:"registered",scheduleCount:0,revision:i,fenced:this.isWorkspaceFenced(e.id)}});return this.status()}unregister(e){if(this.workspaces.delete(e))this.nextWorkspaceRevision(e);this.workspaceFences.delete(e);return this.status()}fence(e){const s=(0,w.randomUUID)();const i=this.workspaceFences.get(e)??new Set;i.add(s);this.workspaceFences.set(e,i);this.setWorkspaceFenceStatus(e,true);return{token:s,status:this.status(e)}}releaseFence(e,s){const i=this.workspaceFences.get(e);if(i?.delete(s)){if(i.size===0)this.workspaceFences.delete(e);this.setWorkspaceFenceStatus(e,this.isWorkspaceFenced(e))}return this.status(e)}reconcile(e){const s=this.reconcileQueue.then(()=>this.applyReconcile(e));this.reconcileQueue=s.then(()=>void 0,()=>void 0);return this.track(s)}async tick(e=new Date){if(this.activeTickPromise){return this.skippedTick("reentrant",e,true)}const s=this.track(this.performTick(new Date(e.getTime())));this.activeTickPromise=s;void s.then(()=>this.clearActiveTick(s),()=>this.clearActiveTick(s));return s}beginDrain(){if(this.stopped)return;this.draining=true;this.role="draining"}stop(e={}){if(this.stopped&&this.stopPromise)return this.stopPromise;if(this.stopPromise)return this.stopPromise;this.beginDrain();const s=this.waitForDrain(P(e.deadlineMs)).then(i=>{if(!i){return{status:"timeout",timedOut:true,drained:false,leaseReleased:false,role:this.publicRole(),activeTick:this.activeTickPromise!==void 0}}this.stopped=true;const t=this.releaseLease();this.role="stopped";return{status:"stopped",timedOut:false,drained:true,leaseReleased:t,role:this.publicRole(),activeTick:this.activeTickPromise!==void 0}});this.stopPromise=s;void s.then(i=>{if(i.status==="timeout")this.stopPromise=void 0});return s}status(e){const s=Array.from(this.workspaces.values(),({status:t})=>m(t));const i=e===void 0?void 0:s.find(t=>t.id===e);return{enabled:this.enabled,role:this.publicRole(),activeTick:this.activeTickPromise!==void 0,draining:this.draining,stopped:this.stopped,ownerId:this.ownerId,leaseId:this.leaseId,leasePath:this.resolvedLeasePath,...this.standbyReason?{standbyReason:this.standbyReason}:{},workspaces:s,...i?{workspace:i}:{}}}async applyReconcile(e){if(this.stopped||this.draining)return this.status();this.enabled=e.enabled;const s=new Set(e.workspaces.map(t=>t.id));for(const t of this.workspaces.keys()){if(!s.has(t))this.nextWorkspaceRevision(t)}const i=new Map;for(const t of e.workspaces){const a=this.workspaces.get(t.id);const n=a&&a.workspace.path===t.path?a.revision:this.nextWorkspaceRevision(t.id);i.set(t.id,{workspace:{...t},revision:n,status:a&&a.workspace.path===t.path?{...a.status,path:t.path,revision:n,fenced:this.isWorkspaceFenced(t.id)}:{id:t.id,path:t.path,state:"registered",scheduleCount:0,revision:n,fenced:this.isWorkspaceFenced(t.id)}})}this.workspaces.clear();for(const[t,a]of i)this.workspaces.set(t,a);await Promise.all(Array.from(this.workspaces.values(),t=>this.inspectWorkspace(t)));if(this.enabled&&!this.draining&&!this.stopped){this.ensureOwner()}else if(!this.enabled){this.role="disabled"}return this.status()}inspectWorkspace(e){try{const s=this.storeFactory(e.workspace).list();e.status={id:e.workspace.id,path:e.workspace.path,state:"ready",scheduleCount:s.length,revision:e.revision,fenced:this.isWorkspaceFenced(e.workspace.id)}}catch(s){e.status={id:e.workspace.id,path:e.workspace.path,state:"degraded",scheduleCount:0,revision:e.revision,fenced:this.isWorkspaceFenced(e.workspace.id),lastError:h(s)}}}async performTick(e){if(this.stopped)return this.skippedTick("stopped",e,false);if(this.draining)return this.skippedTick("draining",e,false);if(!this.enabled)return this.skippedTick("disabled",e,false);if(!this.ensureOwner())return this.skippedTick("standby",e,false);const s=Array.from(this.workspaces.values());const i=await Promise.all(s.map(t=>this.tickWorkspace(t,e)));return{status:"completed",skipped:false,role:this.publicRole(),now:e.toISOString(),activeTick:true,dispatched:i.reduce((t,a)=>t+a.dispatched,0),workspaces:i}}async tickWorkspace(e,s){if(this.draining||this.stopped){return{id:e.workspace.id,path:e.workspace.path,status:"skipped",scheduleCount:e.status.scheduleCount,dueCount:0,dispatched:0,schedules:[]}}let i;try{i=this.storeFactory(e.workspace).list();e.status={id:e.workspace.id,path:e.workspace.path,state:"ready",scheduleCount:i.length,revision:e.revision,fenced:this.isWorkspaceFenced(e.workspace.id)}}catch(n){const o=h(n);e.status={id:e.workspace.id,path:e.workspace.path,state:"degraded",scheduleCount:0,revision:e.revision,fenced:this.isWorkspaceFenced(e.workspace.id),lastError:o};return{id:e.workspace.id,path:e.workspace.path,status:"degraded",scheduleCount:0,dueCount:0,dispatched:0,schedules:[],error:o}}const t=[];for(const n of i){if(!n.enabled)continue;try{if(!this.runPredicate(n.cron,s,n.timezone))continue;const o=(0,c.getLocalMinuteKey)(s,n.timezone);t.push({schedule:n,occurrenceKey:(0,c.buildOccurrenceKey)(n.cron,o)})}catch{}}const a=await Promise.all(t.map(n=>this.admitSchedule(e.workspace,e.revision,n.schedule,n.occurrenceKey)));return{id:e.workspace.id,path:e.workspace.path,status:"completed",scheduleCount:i.length,dueCount:t.length,dispatched:a.filter(n=>n.accepted).length,schedules:a}}async admitSchedule(e,s,i,t){if(this.draining||this.stopped){return{scheduleId:i.id,occurrenceKey:t,status:"skipped",accepted:false,reason:this.stopped?"stopped":"draining"}}const a=this.testHooks?.beforeExecutorAdmission;if(a){await a({workspace:e,schedule:i,occurrenceKey:t,revision:s})}if(this.draining||this.stopped){return{scheduleId:i.id,occurrenceKey:t,status:"skipped",accepted:false,reason:this.stopped?"stopped":"draining"}}const n=this.workspaces.get(e.id);if(!n||n.workspace.path!==e.path||n.revision!==s){return{scheduleId:i.id,occurrenceKey:t,status:"skipped",accepted:false,reason:"workspace-unregistered"}}if(this.isWorkspaceFenced(e.id)){return{scheduleId:i.id,occurrenceKey:t,status:"skipped",accepted:false,reason:"workspace-fenced"}}try{const o=await this.executor(i,{dir:e.path,trigger:"cron",occurrenceKey:t});return{scheduleId:i.id,occurrenceKey:t,status:o.status,accepted:o.status==="running",..."taskId"in o?{taskId:o.taskId}:{},..."reason"in o&&o.reason?{reason:o.reason}:{}}}catch(o){return{scheduleId:i.id,occurrenceKey:t,status:"error",accepted:false,error:h(o).message}}}ensureOwner(){if(this.lease){try{if(this.lease.renew&&!this.lease.renew()){this.forgetLease()}else{this.role="owner";this.standbyReason=void 0;return true}}catch{this.forgetLease()}}if(this.stopped||this.draining||!this.enabled)return false;let e;try{const t={leasePath:this.requestedLeasePath,...this.configuredOwnerId?{ownerId:this.configuredOwnerId}:{}};e=this.leaseProvider.acquire(t)}catch(t){this.role="standby";this.standbyReason=`lease-error:${h(t).message}`;return false}if(!e.acquired){this.role="standby";this.standbyReason=e.reason;this.ownerId=e.record?.ownerId??null;this.leaseId=e.record?.leaseId??null;return false}const s=v(this.resolvedLeasePath,e.ownerId);const i=d.get(s);if(i&&i.runtimeToken!==this.runtimeToken){this.role="standby";this.standbyReason="process-local-owner";this.ownerId=e.ownerId;this.leaseId=e.leaseId;return false}this.lease=e.lease;this.leaseKey=s;this.ownerId=e.ownerId;this.leaseId=e.leaseId;d.set(s,{runtimeToken:this.runtimeToken,ownerId:e.ownerId,lease:e.lease});this.role="owner";this.standbyReason=void 0;return true}forgetLease(){if(this.leaseKey){const e=d.get(this.leaseKey);if(e?.runtimeToken===this.runtimeToken)d.delete(this.leaseKey)}this.lease=void 0;this.leaseKey=void 0;this.ownerId=null;this.leaseId=null;this.role="standby";this.standbyReason="lease-lost"}releaseLease(){if(!this.lease)return true;let e=false;try{e=this.lease.release()}catch{e=false}if(e)this.forgetLease();return e}publicRole(){if(this.stopped)return"stopped";if(this.draining)return"draining";if(!this.enabled)return"disabled";return this.role}skippedTick(e,s,i){return{status:"skipped",skipped:true,reason:e,role:this.publicRole(),now:s.toISOString(),activeTick:i||this.activeTickPromise!==void 0,dispatched:0,workspaces:[]}}clearActiveTick(e){if(this.activeTickPromise===e)this.activeTickPromise=void 0}track(e){let s;s=e.finally(()=>this.operations.delete(s));this.operations.add(s);return s}async waitForDrain(e){const s=Array.from(this.operations);if(s.length===0)return true;const i=Promise.allSettled(s).then(()=>true);if(e<=0)return false;let t;const a=new Promise(o=>{t=setTimeout(()=>o(false),e)});const n=await Promise.race([i,a]);if(t!==void 0)clearTimeout(t);return n}}function T(r={}){return new R(r)}
1
+ "use strict";var p=exports&&exports.__createBinding||(Object.create?(function(r,e,s,i){if(i===void 0)i=s;var t=Object.getOwnPropertyDescriptor(e,s);if(!t||("get"in t?!e.__esModule:t.writable||t.configurable)){t={enumerable:true,get:function(){return e[s]}}}Object.defineProperty(r,i,t)}):(function(r,e,s,i){if(i===void 0)i=s;r[i]=e[s]}));var f=exports&&exports.__setModuleDefault||(Object.create?(function(r,e){Object.defineProperty(r,"default",{enumerable:true,value:e})}):function(r,e){r["default"]=e});var k=exports&&exports.__importStar||(function(){var r=function(e){r=Object.getOwnPropertyNames||function(s){var i=[];for(var t in s)if(Object.prototype.hasOwnProperty.call(s,t))i[i.length]=t;return i};return r(e)};return function(e){if(e&&e.__esModule)return e;var s={};if(e!=null){for(var i=r(e),t=0;t<i.length;t++)if(i[t]!=="default")p(s,e,i[t])}f(s,e);return s}})();Object.defineProperty(exports,"__esModule",{value:true});exports.CRON_RUNTIME_PROCESS_LEASE_FILENAME=void 0;exports.scheduledPeriodicAvailability=v;exports.createCronRuntime=y;const w=require("node:crypto");const g=k(require("node:path"));const h=require("@crewx/sdk");const d=require("./engine");exports.CRON_RUNTIME_PROCESS_LEASE_FILENAME="cron-runtime-process-lease.json";const l=5e3;function v(r){if(r.draining||r.role==="draining")return{periodic:"unavailable",reason:"draining"};if(!r.enabled||r.stopped||r.role==="disabled"||r.role==="stopped"){return{periodic:"unavailable",reason:"disabled"}}if(r.role!=="owner")return{periodic:"unavailable",reason:"standby"};const e=r.workspace;if(e===void 0||e.state!=="ready"||e.fenced){return{periodic:"unavailable",reason:"degraded"}}return{periodic:"available"}}const c=new Map;function u(r){const e=r;return{...typeof e?.code==="string"?{code:e.code}:{},message:e?.message instanceof String?e.message.toString():e&&typeof e.message==="string"?e.message:String(r)}}function m(r){return{...r,...r.lastError?{lastError:{...r.lastError}}:{}}}function b(r,e){return`${r}\0${e}`}function P(r){try{return(0,h.resolveProcessLeasePath)(r)}catch{return g.resolve(r)}}function R(r){if(r===void 0)return l;if(!Number.isFinite(r))return l;return Math.max(0,r)}class T{constructor(e={}){this.runtimeToken=Symbol("cron-runtime");this.enabled=false;this.draining=false;this.stopped=false;this.role="standby";this.ownerId=null;this.leaseId=null;this.workspaces=new Map;this.workspaceRevisions=new Map;this.workspaceFences=new Map;this.operations=new Set;this.reconcileQueue=Promise.resolve();this.requestedLeasePath=e.leasePath??exports.CRON_RUNTIME_PROCESS_LEASE_FILENAME;this.resolvedLeasePath=P(this.requestedLeasePath);this.configuredOwnerId=e.ownerId;this.leaseProvider=e.processLease??e.leaseProvider??{acquire:h.acquireProcessLease};this.storeFactory=e.storeFactory??(s=>(0,d.createScheduleStore)(s.path));this.executor=e.executeSchedule??e.executor??d.executeSchedule;this.runPredicate=e.shouldRunNow??d.shouldRunNow;this.testHooks=e.testHooks}nextWorkspaceRevision(e){const s=(this.workspaceRevisions.get(e)??0)+1;this.workspaceRevisions.set(e,s);return s}isWorkspaceFenced(e){return(this.workspaceFences.get(e)?.size??0)>0}setWorkspaceFenceStatus(e,s){const i=this.workspaces.get(e);if(!i)return;i.status={...i.status,fenced:s}}register(e){if(this.stopped||this.draining)return this.status();const s=this.workspaces.get(e.id);const i=s&&s.workspace.path===e.path?s.revision:this.nextWorkspaceRevision(e.id);this.workspaces.set(e.id,{workspace:{...e},revision:i,status:{id:e.id,path:e.path,state:"registered",scheduleCount:0,revision:i,fenced:this.isWorkspaceFenced(e.id)}});return this.status()}unregister(e){if(this.workspaces.delete(e))this.nextWorkspaceRevision(e);this.workspaceFences.delete(e);return this.status()}fence(e){const s=(0,w.randomUUID)();const i=this.workspaceFences.get(e)??new Set;i.add(s);this.workspaceFences.set(e,i);this.setWorkspaceFenceStatus(e,true);return{token:s,status:this.status(e)}}releaseFence(e,s){const i=this.workspaceFences.get(e);if(i?.delete(s)){if(i.size===0)this.workspaceFences.delete(e);this.setWorkspaceFenceStatus(e,this.isWorkspaceFenced(e))}return this.status(e)}reconcile(e){const s=this.reconcileQueue.then(()=>this.applyReconcile(e));this.reconcileQueue=s.then(()=>void 0,()=>void 0);return this.track(s)}async tick(e=new Date){if(this.activeTickPromise){return this.skippedTick("reentrant",e,true)}const s=this.track(this.performTick(new Date(e.getTime())));this.activeTickPromise=s;void s.then(()=>this.clearActiveTick(s),()=>this.clearActiveTick(s));return s}beginDrain(){if(this.stopped)return;this.draining=true;this.role="draining"}stop(e={}){if(this.stopped&&this.stopPromise)return this.stopPromise;if(this.stopPromise)return this.stopPromise;this.beginDrain();const s=this.waitForDrain(R(e.deadlineMs)).then(i=>{if(!i){return{status:"timeout",timedOut:true,drained:false,leaseReleased:false,role:this.publicRole(),activeTick:this.activeTickPromise!==void 0}}this.stopped=true;const t=this.releaseLease();this.role="stopped";return{status:"stopped",timedOut:false,drained:true,leaseReleased:t,role:this.publicRole(),activeTick:this.activeTickPromise!==void 0}});this.stopPromise=s;void s.then(i=>{if(i.status==="timeout")this.stopPromise=void 0});return s}status(e){const s=Array.from(this.workspaces.values(),({status:t})=>m(t));const i=e===void 0?void 0:s.find(t=>t.id===e);return{enabled:this.enabled,role:this.publicRole(),activeTick:this.activeTickPromise!==void 0,draining:this.draining,stopped:this.stopped,ownerId:this.ownerId,leaseId:this.leaseId,leasePath:this.resolvedLeasePath,...this.standbyReason?{standbyReason:this.standbyReason}:{},workspaces:s,...i?{workspace:i}:{}}}async applyReconcile(e){if(this.stopped||this.draining)return this.status();this.enabled=e.enabled;const s=new Set(e.workspaces.map(t=>t.id));for(const t of this.workspaces.keys()){if(!s.has(t))this.nextWorkspaceRevision(t)}const i=new Map;for(const t of e.workspaces){const a=this.workspaces.get(t.id);const n=a&&a.workspace.path===t.path?a.revision:this.nextWorkspaceRevision(t.id);i.set(t.id,{workspace:{...t},revision:n,status:a&&a.workspace.path===t.path?{...a.status,path:t.path,revision:n,fenced:this.isWorkspaceFenced(t.id)}:{id:t.id,path:t.path,state:"registered",scheduleCount:0,revision:n,fenced:this.isWorkspaceFenced(t.id)}})}this.workspaces.clear();for(const[t,a]of i)this.workspaces.set(t,a);await Promise.all(Array.from(this.workspaces.values(),t=>this.inspectWorkspace(t)));if(this.enabled&&!this.draining&&!this.stopped){this.ensureOwner()}else if(!this.enabled){this.role="disabled"}return this.status()}inspectWorkspace(e){try{const s=this.storeFactory(e.workspace).list();e.status={id:e.workspace.id,path:e.workspace.path,state:"ready",scheduleCount:s.length,revision:e.revision,fenced:this.isWorkspaceFenced(e.workspace.id)}}catch(s){e.status={id:e.workspace.id,path:e.workspace.path,state:"degraded",scheduleCount:0,revision:e.revision,fenced:this.isWorkspaceFenced(e.workspace.id),lastError:u(s)}}}async performTick(e){if(this.stopped)return this.skippedTick("stopped",e,false);if(this.draining)return this.skippedTick("draining",e,false);if(!this.enabled)return this.skippedTick("disabled",e,false);if(!this.ensureOwner())return this.skippedTick("standby",e,false);const s=Array.from(this.workspaces.values());const i=await Promise.all(s.map(t=>this.tickWorkspace(t,e)));return{status:"completed",skipped:false,role:this.publicRole(),now:e.toISOString(),activeTick:true,dispatched:i.reduce((t,a)=>t+a.dispatched,0),workspaces:i}}async tickWorkspace(e,s){if(this.draining||this.stopped){return{id:e.workspace.id,path:e.workspace.path,status:"skipped",scheduleCount:e.status.scheduleCount,dueCount:0,dispatched:0,schedules:[]}}let i;try{i=this.storeFactory(e.workspace).list();e.status={id:e.workspace.id,path:e.workspace.path,state:"ready",scheduleCount:i.length,revision:e.revision,fenced:this.isWorkspaceFenced(e.workspace.id)}}catch(n){const o=u(n);e.status={id:e.workspace.id,path:e.workspace.path,state:"degraded",scheduleCount:0,revision:e.revision,fenced:this.isWorkspaceFenced(e.workspace.id),lastError:o};return{id:e.workspace.id,path:e.workspace.path,status:"degraded",scheduleCount:0,dueCount:0,dispatched:0,schedules:[],error:o}}const t=[];for(const n of i){if(!(0,d.effectiveEnabled)(n))continue;try{if(!this.runPredicate(n.cron,s,n.timezone))continue;const o=(0,d.getLocalMinuteKey)(s,n.timezone);t.push({schedule:n,occurrenceKey:(0,d.buildOccurrenceKey)(n.cron,o)})}catch{}}const a=await Promise.all(t.map(n=>this.admitSchedule(e.workspace,e.revision,n.schedule,n.occurrenceKey)));return{id:e.workspace.id,path:e.workspace.path,status:"completed",scheduleCount:i.length,dueCount:t.length,dispatched:a.filter(n=>n.accepted).length,schedules:a}}async admitSchedule(e,s,i,t){if(this.draining||this.stopped){return{scheduleId:i.id,occurrenceKey:t,status:"skipped",accepted:false,reason:this.stopped?"stopped":"draining"}}const a=this.testHooks?.beforeExecutorAdmission;if(a){await a({workspace:e,schedule:i,occurrenceKey:t,revision:s})}if(this.draining||this.stopped){return{scheduleId:i.id,occurrenceKey:t,status:"skipped",accepted:false,reason:this.stopped?"stopped":"draining"}}const n=this.workspaces.get(e.id);if(!n||n.workspace.path!==e.path||n.revision!==s){return{scheduleId:i.id,occurrenceKey:t,status:"skipped",accepted:false,reason:"workspace-unregistered"}}if(this.isWorkspaceFenced(e.id)){return{scheduleId:i.id,occurrenceKey:t,status:"skipped",accepted:false,reason:"workspace-fenced"}}try{const o=await this.executor(i,{dir:e.path,trigger:"cron",occurrenceKey:t});return{scheduleId:i.id,occurrenceKey:t,status:o.status,accepted:o.status==="running",..."taskId"in o?{taskId:o.taskId}:{},..."reason"in o&&o.reason?{reason:o.reason}:{}}}catch(o){return{scheduleId:i.id,occurrenceKey:t,status:"error",accepted:false,error:u(o).message}}}ensureOwner(){if(this.lease){try{if(this.lease.renew&&!this.lease.renew()){this.forgetLease()}else{this.role="owner";this.standbyReason=void 0;return true}}catch{this.forgetLease()}}if(this.stopped||this.draining||!this.enabled)return false;let e;try{const t={leasePath:this.requestedLeasePath,...this.configuredOwnerId?{ownerId:this.configuredOwnerId}:{}};e=this.leaseProvider.acquire(t)}catch(t){this.role="standby";this.standbyReason=`lease-error:${u(t).message}`;return false}if(!e.acquired){this.role="standby";this.standbyReason=e.reason;this.ownerId=e.record?.ownerId??null;this.leaseId=e.record?.leaseId??null;return false}const s=b(this.resolvedLeasePath,e.ownerId);const i=c.get(s);if(i&&i.runtimeToken!==this.runtimeToken){this.role="standby";this.standbyReason="process-local-owner";this.ownerId=e.ownerId;this.leaseId=e.leaseId;return false}this.lease=e.lease;this.leaseKey=s;this.ownerId=e.ownerId;this.leaseId=e.leaseId;c.set(s,{runtimeToken:this.runtimeToken,ownerId:e.ownerId,lease:e.lease});this.role="owner";this.standbyReason=void 0;return true}forgetLease(){if(this.leaseKey){const e=c.get(this.leaseKey);if(e?.runtimeToken===this.runtimeToken)c.delete(this.leaseKey)}this.lease=void 0;this.leaseKey=void 0;this.ownerId=null;this.leaseId=null;this.role="standby";this.standbyReason="lease-lost"}releaseLease(){if(!this.lease)return true;let e=false;try{e=this.lease.release()}catch{e=false}if(e)this.forgetLease();return e}publicRole(){if(this.stopped)return"stopped";if(this.draining)return"draining";if(!this.enabled)return"disabled";return this.role}skippedTick(e,s,i){return{status:"skipped",skipped:true,reason:e,role:this.publicRole(),now:s.toISOString(),activeTick:i||this.activeTickPromise!==void 0,dispatched:0,workspaces:[]}}clearActiveTick(e){if(this.activeTickPromise===e)this.activeTickPromise=void 0}track(e){let s;s=e.finally(()=>this.operations.delete(s));this.operations.add(s);return s}async waitForDrain(e){const s=Array.from(this.operations);if(s.length===0)return true;const i=Promise.allSettled(s).then(()=>true);if(e<=0)return false;let t;const a=new Promise(o=>{t=setTimeout(()=>o(false),e)});const n=await Promise.race([i,a]);if(t!==void 0)clearTimeout(t);return n}}function y(r={}){return new T(r)}
@@ -1,3 +1,6 @@
1
+ import type { ChildProcess } from 'child_process';
2
+ import type { AppScheduleBinding, AppScheduleOwner, AppScheduleRunVerdict, AppScheduleTemplate, ScheduleTrigger } from '@crewx/sdk';
3
+ export type { AppScheduleBinding, AppScheduleOwner, AppScheduleRunVerdict, AppScheduleTemplate, ScheduleTrigger };
1
4
  export type ExecutionMode = 'query' | 'execute' | 'command';
2
5
  export interface Schedule {
3
6
  id: string;
@@ -13,6 +16,7 @@ export interface Schedule {
13
16
  env?: Record<string, string>;
14
17
  model?: string;
15
18
  provider?: string;
19
+ app?: AppScheduleBinding;
16
20
  created_at: string;
17
21
  updated_at: string;
18
22
  run_count: number;
@@ -20,9 +24,10 @@ export interface Schedule {
20
24
  last_started_at?: string;
21
25
  last_occurrence_key?: string;
22
26
  last_outcome?: string;
27
+ last_error_code?: string;
23
28
  next_run?: string | null;
24
29
  }
25
- export type CronStoreErrorCode = 'CRON_STORE_CORRUPT' | 'CRON_STORE_LOCK_TIMEOUT' | 'CRON_SCHEDULE_NOT_FOUND' | 'CRON_SCHEDULE_EXISTS';
30
+ export type CronStoreErrorCode = 'CRON_STORE_CORRUPT' | 'CRON_STORE_LOCK_TIMEOUT' | 'CRON_SCHEDULE_NOT_FOUND' | 'CRON_SCHEDULE_EXISTS' | 'CRON_SCHEDULE_MANAGED';
26
31
  export declare class CronStoreError extends Error {
27
32
  readonly code: CronStoreErrorCode;
28
33
  readonly filePath?: string;
@@ -64,7 +69,13 @@ export interface RecordFinishedOptions {
64
69
  nextRun?: string | null;
65
70
  outcome?: string;
66
71
  success?: boolean;
72
+ errorCode?: string;
67
73
  }
74
+ export interface AppScheduleChildExit {
75
+ readonly code: number | null;
76
+ readonly signal: NodeJS.Signals | null;
77
+ }
78
+ export type AppScheduleSettle = (exit: AppScheduleChildExit) => AppScheduleRunVerdict;
68
79
  export interface ScheduleStore {
69
80
  readonly workspacePath: string;
70
81
  readonly dataDir: string;
@@ -79,7 +90,32 @@ export interface ScheduleStore {
79
90
  claimOccurrence(id: string | Schedule, options: ClaimOccurrenceOptions): ClaimOccurrenceResult;
80
91
  recordStarted(id: string | Schedule, options?: RecordStartedOptions | string): Schedule;
81
92
  recordFinished(id: string | Schedule, options?: RecordFinishedOptions): Schedule;
82
- }
93
+ setAppSchedule(owner: AppScheduleOwner, template: AppScheduleTemplate, enabled?: boolean): AppScheduleWrite;
94
+ recordSkipped(id: string, record: AppScheduleSkipRecord): Schedule;
95
+ removeAppSchedule(appId: string): Schedule | undefined;
96
+ }
97
+ export interface AppScheduleWrite {
98
+ readonly schedule: Schedule;
99
+ readonly started: boolean;
100
+ }
101
+ export interface AppScheduleSkipRecord {
102
+ readonly outcome: string;
103
+ readonly errorCode: string | null;
104
+ readonly finishedAt?: string;
105
+ }
106
+ export type AppScheduleLaunchDecision = {
107
+ readonly kind: 'spawn';
108
+ readonly child: ChildProcess;
109
+ readonly settle: AppScheduleSettle;
110
+ } | {
111
+ readonly kind: 'skip' | 'disable' | 'remove';
112
+ readonly code: string;
113
+ } | {
114
+ readonly kind: 'refresh';
115
+ readonly owner: AppScheduleOwner;
116
+ readonly template: AppScheduleTemplate;
117
+ };
118
+ export type AppScheduleLauncher = (schedule: Schedule) => AppScheduleLaunchDecision | Promise<AppScheduleLaunchDecision>;
83
119
  export interface DaemonStatus {
84
120
  running: boolean;
85
121
  pid: number | null;
@@ -95,18 +131,25 @@ export interface ExecuteResult {
95
131
  }
96
132
  export interface ExecuteScheduleOptions {
97
133
  dir?: string;
98
- trigger?: string;
134
+ trigger?: ScheduleTrigger;
99
135
  occurrenceKey?: string;
100
136
  overrides?: {
101
137
  model?: string;
102
138
  provider?: string;
103
139
  };
140
+ launchApp?: AppScheduleLauncher;
104
141
  }
105
142
  export interface ExecuteScheduleRunning {
106
143
  status: 'running';
107
144
  taskId: string;
108
145
  done: Promise<ExecuteResult>;
109
146
  }
147
+ export interface ExecuteScheduleSkipped {
148
+ status: 'skipped';
149
+ taskId?: undefined;
150
+ reason: string;
151
+ lifecycle: 'skip' | 'disable' | 'remove' | 'refresh';
152
+ }
110
153
  export interface ExecuteScheduleConflict {
111
154
  status: 'conflict';
112
155
  runningTaskId: string;
@@ -114,9 +157,9 @@ export interface ExecuteScheduleConflict {
114
157
  }
115
158
  export interface ExecuteScheduleBlocked {
116
159
  status: 'blocked';
117
- reason: 'UPDATE_QUIESCING' | 'ADMISSION_UNKNOWN';
160
+ reason: 'UPDATE_QUIESCING' | 'ADMISSION_UNKNOWN' | 'APP_LAUNCHER_UNAVAILABLE' | 'APP_ROW_INVALID' | 'MODE_UNSUPPORTED' | 'TRIGGER_UNSUPPORTED';
118
161
  }
119
- export type ExecuteScheduleOutcome = ExecuteScheduleRunning | ExecuteScheduleConflict | ExecuteScheduleBlocked;
162
+ export type ExecuteScheduleOutcome = ExecuteScheduleRunning | ExecuteScheduleConflict | ExecuteScheduleBlocked | ExecuteScheduleSkipped;
120
163
  export interface StartDaemonResult {
121
164
  started: boolean;
122
165
  pid?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewx/cron",
3
- "version": "0.1.10-rc.195",
3
+ "version": "0.1.10-rc.196",
4
4
  "description": "Cron Scheduler for CrewX - Schedule and execute crewx commands automatically",
5
5
  "type": "commonjs",
6
6
  "main": "dist/src/engine.js",
@@ -33,8 +33,8 @@
33
33
  ],
34
34
  "license": "MIT",
35
35
  "dependencies": {
36
- "@crewx/sdk": "0.9.0-rc.160",
37
- "@crewx/shared": "0.0.6-rc.75"
36
+ "@crewx/sdk": "0.9.0-rc.161",
37
+ "@crewx/shared": "0.0.6-rc.76"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^20.0.0",