MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / ScheduleStore

Class ScheduleStore

src/schedule/store.ts:87–263  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

85}
86
87export class ScheduleStore {
88 private db: Database.Database;
89
90 constructor(dbPath: string = QODEX_SESSION_DB) {
91 this.db = openDatabase(dbPath);
92 this.db.exec(SCHEMA);
93 // Migrate DBs created before deliver/recipe existed. ADD COLUMN throws on an existing
94 // column, so each is guarded — idempotent and safe to run every startup.
95 for (const col of ['deliver TEXT', 'recipe TEXT']) {
96 try { this.db.exec(`ALTER TABLE schedules ADD COLUMN ${col}`); } catch { /* already present */ }
97 }
98 try { this.db.exec(`ALTER TABLE schedule_runs ADD COLUMN receipt TEXT`); } catch { /* already present */ }
99 }
100
101 add(input: {
102 name: string;
103 cron: string;
104 prompt: string;
105 cwd: string;
106 model?: string;
107 allowedTools?: string[];
108 deliver?: string;
109 recipe?: string;
110 }): ScheduleEntry {
111 const parsed = parseCron(input.cron); // throws on invalid
112 const next = nextAfter(parsed, new Date());
113 const id = uuidv4();
114 const allowed = input.allowedTools && input.allowedTools.length > 0 ? JSON.stringify(input.allowedTools) : null;
115 this.db.prepare(`
116 INSERT INTO schedules (id, name, cron, prompt, cwd, model, allowed_tools, next_run_at, deliver, recipe)
117 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
118 `).run(id, input.name, input.cron, input.prompt, input.cwd, input.model ?? null, allowed, next?.toISOString() ?? null,
119 input.deliver ?? null, input.recipe ?? null);
120 return this.get(id)!;
121 }
122
123 remove(idOrName: string): boolean {
124 const e = this.resolve(idOrName);
125 if (!e) return false;
126 this.db.prepare(`DELETE FROM schedules WHERE id = ?`).run(e.id);
127 return true;
128 }
129
130 setEnabled(idOrName: string, enabled: boolean): ScheduleEntry | null {
131 const e = this.resolve(idOrName);
132 if (!e) return null;
133 this.db.prepare(`UPDATE schedules SET enabled = ? WHERE id = ?`).run(enabled ? 1 : 0, e.id);
134 if (enabled) this.recomputeNext(e.id);
135 return this.get(e.id) ?? null;
136 }
137
138 get(id: string): ScheduleEntry | undefined {
139 return this.db.prepare(`SELECT * FROM schedules WHERE id = ?`).get(id) as ScheduleEntry | undefined;
140 }
141
142 /** Find by exact id, id prefix (>=4 chars), or exact name. */
143 resolve(idOrName: string): ScheduleEntry | undefined {
144 const exact = this.get(idOrName);

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected