@dexto/tools-scheduler 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/LICENSE +44 -0
  2. package/dist/error-codes.cjs +44 -0
  3. package/dist/error-codes.d.cts +21 -0
  4. package/dist/error-codes.d.ts +21 -0
  5. package/dist/error-codes.js +20 -0
  6. package/dist/errors.cjs +163 -0
  7. package/dist/errors.d.cts +64 -0
  8. package/dist/errors.d.ts +64 -0
  9. package/dist/errors.js +138 -0
  10. package/dist/executor.cjs +161 -0
  11. package/dist/executor.d.cts +46 -0
  12. package/dist/executor.d.ts +46 -0
  13. package/dist/executor.js +137 -0
  14. package/dist/index.cjs +89 -0
  15. package/dist/index.d.cts +19 -0
  16. package/dist/index.d.ts +19 -0
  17. package/dist/index.js +56 -0
  18. package/dist/manager.cjs +461 -0
  19. package/dist/manager.d.cts +113 -0
  20. package/dist/manager.d.ts +113 -0
  21. package/dist/manager.js +430 -0
  22. package/dist/schemas.cjs +138 -0
  23. package/dist/schemas.d.cts +263 -0
  24. package/dist/schemas.d.ts +263 -0
  25. package/dist/schemas.js +105 -0
  26. package/dist/storage.cjs +249 -0
  27. package/dist/storage.d.cts +62 -0
  28. package/dist/storage.d.ts +62 -0
  29. package/dist/storage.js +225 -0
  30. package/dist/tool-provider.cjs +239 -0
  31. package/dist/tool-provider.d.cts +34 -0
  32. package/dist/tool-provider.d.ts +34 -0
  33. package/dist/tool-provider.js +212 -0
  34. package/dist/tool-types.cjs +16 -0
  35. package/dist/tool-types.d.cts +9 -0
  36. package/dist/tool-types.d.ts +9 -0
  37. package/dist/tool-types.js +0 -0
  38. package/dist/tools/create-schedule.cjs +75 -0
  39. package/dist/tools/create-schedule.d.cts +14 -0
  40. package/dist/tools/create-schedule.d.ts +14 -0
  41. package/dist/tools/create-schedule.js +51 -0
  42. package/dist/tools/delete-schedule.cjs +45 -0
  43. package/dist/tools/delete-schedule.d.cts +14 -0
  44. package/dist/tools/delete-schedule.d.ts +14 -0
  45. package/dist/tools/delete-schedule.js +21 -0
  46. package/dist/tools/get-history.cjs +63 -0
  47. package/dist/tools/get-history.d.cts +14 -0
  48. package/dist/tools/get-history.d.ts +14 -0
  49. package/dist/tools/get-history.js +39 -0
  50. package/dist/tools/get-schedule.cjs +68 -0
  51. package/dist/tools/get-schedule.d.cts +14 -0
  52. package/dist/tools/get-schedule.d.ts +14 -0
  53. package/dist/tools/get-schedule.js +44 -0
  54. package/dist/tools/list-schedules.cjs +67 -0
  55. package/dist/tools/list-schedules.d.cts +14 -0
  56. package/dist/tools/list-schedules.d.ts +14 -0
  57. package/dist/tools/list-schedules.js +43 -0
  58. package/dist/tools/trigger-schedule.cjs +56 -0
  59. package/dist/tools/trigger-schedule.d.cts +14 -0
  60. package/dist/tools/trigger-schedule.d.ts +14 -0
  61. package/dist/tools/trigger-schedule.js +32 -0
  62. package/dist/tools/update-schedule.cjs +53 -0
  63. package/dist/tools/update-schedule.d.cts +14 -0
  64. package/dist/tools/update-schedule.d.ts +14 -0
  65. package/dist/tools/update-schedule.js +29 -0
  66. package/dist/types.cjs +16 -0
  67. package/dist/types.d.cts +72 -0
  68. package/dist/types.d.ts +72 -0
  69. package/dist/types.js +0 -0
  70. package/package.json +41 -0
@@ -0,0 +1,461 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var manager_exports = {};
30
+ __export(manager_exports, {
31
+ SchedulerManager: () => SchedulerManager
32
+ });
33
+ module.exports = __toCommonJS(manager_exports);
34
+ var import_node_cron = __toESM(require("node-cron"), 1);
35
+ var cronParser = __toESM(require("cron-parser"), 1);
36
+ var import_crypto = require("crypto");
37
+ var import_core = require("@dexto/core");
38
+ var import_schemas = require("./schemas.js");
39
+ var import_storage = require("./storage.js");
40
+ var import_executor = require("./executor.js");
41
+ var import_errors = require("./errors.js");
42
+ class SchedulerManager {
43
+ constructor(storageManager, config, logger) {
44
+ this.config = config;
45
+ this.logger = logger;
46
+ this.storage = new import_storage.ScheduleStorage(storageManager, config.maxExecutionHistory, logger);
47
+ this.executor = new import_executor.ScheduleExecutor(config.executionTimeout, logger);
48
+ }
49
+ cronTasks = /* @__PURE__ */ new Map();
50
+ storage;
51
+ executor;
52
+ executionChain = Promise.resolve();
53
+ initialized = false;
54
+ started = false;
55
+ cachedSchedules;
56
+ /**
57
+ * Set the executor function (called to run the agent with a prompt)
58
+ */
59
+ setExecutor(fn) {
60
+ this.executor.setExecutor(fn);
61
+ }
62
+ /**
63
+ * Initialize the scheduler (load schedules from storage)
64
+ */
65
+ async init() {
66
+ if (this.initialized) {
67
+ return;
68
+ }
69
+ try {
70
+ const storedSchedules = await this.storage.listSchedules();
71
+ this.cachedSchedules = storedSchedules;
72
+ this.logger.info(`Loaded ${storedSchedules.length} schedules from storage`);
73
+ this.initialized = true;
74
+ } catch (error) {
75
+ throw import_errors.SchedulerError.invalidConfig(
76
+ `Failed to initialize scheduler: ${error instanceof Error ? error.message : String(error)}`
77
+ );
78
+ }
79
+ }
80
+ /**
81
+ * Start the scheduler (begin executing schedules)
82
+ */
83
+ async start() {
84
+ if (!this.initialized) {
85
+ await this.init();
86
+ }
87
+ if (this.started) {
88
+ return;
89
+ }
90
+ try {
91
+ const schedules = this.cachedSchedules ?? await this.storage.listSchedules();
92
+ this.cachedSchedules = void 0;
93
+ for (const schedule of schedules) {
94
+ if (schedule.enabled) {
95
+ await this.scheduleTask(schedule);
96
+ }
97
+ }
98
+ this.started = true;
99
+ this.logger.info(`Scheduler started with ${this.cronTasks.size} active schedules`);
100
+ } catch (error) {
101
+ throw import_errors.SchedulerError.invalidConfig(
102
+ `Failed to start scheduler: ${error instanceof Error ? error.message : String(error)}`
103
+ );
104
+ }
105
+ }
106
+ /**
107
+ * Stop the scheduler (stop all running tasks)
108
+ */
109
+ async stop() {
110
+ if (!this.started) {
111
+ return;
112
+ }
113
+ for (const task of this.cronTasks.values()) {
114
+ task.stop();
115
+ }
116
+ this.cronTasks.clear();
117
+ this.started = false;
118
+ this.logger.info("Scheduler stopped");
119
+ }
120
+ /**
121
+ * Create a new schedule
122
+ *
123
+ * @param input - Schedule creation input
124
+ * @param currentSessionId - The current session ID (used for 'inherit' mode)
125
+ */
126
+ async createSchedule(input, currentSessionId) {
127
+ const validated = import_schemas.CreateScheduleInputSchema.parse(input);
128
+ const existingSchedules = await this.storage.listSchedules();
129
+ if (existingSchedules.length >= this.config.maxSchedules) {
130
+ throw import_errors.SchedulerError.limitReached(existingSchedules.length, this.config.maxSchedules);
131
+ }
132
+ if (!import_node_cron.default.validate(validated.cronExpression)) {
133
+ throw import_errors.SchedulerError.invalidCron(validated.cronExpression, "Invalid cron format");
134
+ }
135
+ let resolvedSessionId;
136
+ const sessionMode = validated.sessionMode ?? "ephemeral";
137
+ if (sessionMode === "inherit") {
138
+ if (!currentSessionId) {
139
+ throw import_errors.SchedulerError.invalidInput(
140
+ 'sessionMode "inherit" requires a current session context'
141
+ );
142
+ }
143
+ resolvedSessionId = currentSessionId;
144
+ } else if (sessionMode === "fixed") {
145
+ resolvedSessionId = validated.sessionId;
146
+ }
147
+ const now = Date.now();
148
+ const taskMetadata = {
149
+ ...validated.metadata
150
+ };
151
+ if (validated.targetAgentId) {
152
+ taskMetadata.__os_targetAgentId = validated.targetAgentId;
153
+ }
154
+ const workspacePath = validated.workspacePath && validated.workspacePath.trim().length > 0 ? validated.workspacePath : void 0;
155
+ const schedule = {
156
+ id: (0, import_crypto.randomUUID)(),
157
+ name: validated.name,
158
+ cronExpression: validated.cronExpression,
159
+ timezone: validated.timezone || this.config.timezone,
160
+ enabled: validated.enabled,
161
+ task: {
162
+ instruction: validated.instruction,
163
+ ...Object.keys(taskMetadata).length > 0 && { metadata: taskMetadata }
164
+ },
165
+ sessionMode,
166
+ ...resolvedSessionId && { sessionId: resolvedSessionId },
167
+ ...workspacePath ? { workspacePath } : {},
168
+ createdAt: now,
169
+ updatedAt: now,
170
+ runCount: 0,
171
+ successCount: 0,
172
+ failureCount: 0
173
+ };
174
+ const nextRun = this.calculateNextRun(schedule);
175
+ if (nextRun !== void 0) {
176
+ schedule.nextRunAt = nextRun;
177
+ }
178
+ await this.storage.saveSchedule(schedule);
179
+ if (schedule.enabled && this.started) {
180
+ await this.scheduleTask(schedule);
181
+ }
182
+ this.logger.info(`Schedule created: ${schedule.name}`, {
183
+ scheduleId: schedule.id,
184
+ sessionMode,
185
+ cronExpression: schedule.cronExpression
186
+ });
187
+ return schedule;
188
+ }
189
+ /**
190
+ * Update an existing schedule
191
+ *
192
+ * @param scheduleId - The schedule ID to update
193
+ * @param updates - The updates to apply
194
+ * @param currentSessionId - The current session ID (used if changing to 'inherit' mode)
195
+ */
196
+ async updateSchedule(scheduleId, updates, currentSessionId) {
197
+ const validated = import_schemas.UpdateScheduleFieldsOnlySchema.parse(updates);
198
+ const existing = await this.storage.loadSchedule(scheduleId);
199
+ if (!existing) {
200
+ throw import_errors.SchedulerError.notFound(scheduleId);
201
+ }
202
+ if (validated.cronExpression && !import_node_cron.default.validate(validated.cronExpression)) {
203
+ throw import_errors.SchedulerError.invalidCron(validated.cronExpression, "Invalid cron format");
204
+ }
205
+ let updatedSessionId = existing.sessionId;
206
+ const newSessionMode = validated.sessionMode ?? existing.sessionMode;
207
+ if (validated.sessionMode !== void 0) {
208
+ if (newSessionMode === "inherit") {
209
+ if (!currentSessionId) {
210
+ throw import_errors.SchedulerError.invalidInput(
211
+ 'sessionMode "inherit" requires a current session context'
212
+ );
213
+ }
214
+ updatedSessionId = currentSessionId;
215
+ } else if (newSessionMode === "fixed") {
216
+ updatedSessionId = validated.sessionId;
217
+ } else {
218
+ updatedSessionId = void 0;
219
+ }
220
+ } else if (validated.sessionId !== void 0) {
221
+ updatedSessionId = validated.sessionId;
222
+ }
223
+ const existingTaskMetadata = existing.task.metadata ?? {};
224
+ const updatedTaskMetadata = validated.metadata !== void 0 ? { ...validated.metadata } : { ...existingTaskMetadata };
225
+ for (const [key, value] of Object.entries(existingTaskMetadata)) {
226
+ if (key.startsWith("__os_")) {
227
+ updatedTaskMetadata[key] = value;
228
+ }
229
+ }
230
+ if (validated.targetAgentId !== void 0) {
231
+ if (validated.targetAgentId) {
232
+ updatedTaskMetadata.__os_targetAgentId = validated.targetAgentId;
233
+ } else {
234
+ delete updatedTaskMetadata.__os_targetAgentId;
235
+ }
236
+ }
237
+ const resolvedWorkspacePath = validated.workspacePath === void 0 ? existing.workspacePath : validated.workspacePath && validated.workspacePath.trim().length > 0 ? validated.workspacePath : void 0;
238
+ const updated = {
239
+ ...existing,
240
+ ...validated.name !== void 0 && { name: validated.name },
241
+ ...validated.cronExpression !== void 0 && {
242
+ cronExpression: validated.cronExpression
243
+ },
244
+ ...validated.timezone !== void 0 && { timezone: validated.timezone },
245
+ ...validated.enabled !== void 0 && { enabled: validated.enabled },
246
+ task: {
247
+ ...existing.task,
248
+ ...validated.instruction !== void 0 && { instruction: validated.instruction },
249
+ ...Object.keys(updatedTaskMetadata).length > 0 ? { metadata: updatedTaskMetadata } : {}
250
+ },
251
+ sessionMode: newSessionMode,
252
+ ...updatedSessionId !== void 0 ? { sessionId: updatedSessionId } : {},
253
+ updatedAt: Date.now()
254
+ };
255
+ if (resolvedWorkspacePath) {
256
+ updated.workspacePath = resolvedWorkspacePath;
257
+ } else {
258
+ delete updated.workspacePath;
259
+ }
260
+ if (newSessionMode === "ephemeral" || newSessionMode === "dedicated") {
261
+ delete updated.sessionId;
262
+ }
263
+ const nextRunTime = this.calculateNextRun(updated);
264
+ if (nextRunTime !== void 0) {
265
+ updated.nextRunAt = nextRunTime;
266
+ }
267
+ await this.storage.saveSchedule(updated);
268
+ if (this.started) {
269
+ this.unscheduleTask(scheduleId);
270
+ if (updated.enabled) {
271
+ await this.scheduleTask(updated);
272
+ }
273
+ }
274
+ this.logger.info(`Schedule updated: ${updated.name}`, {
275
+ scheduleId,
276
+ sessionMode: newSessionMode
277
+ });
278
+ return updated;
279
+ }
280
+ /**
281
+ * Delete a schedule
282
+ */
283
+ async deleteSchedule(scheduleId) {
284
+ const schedule = await this.storage.loadSchedule(scheduleId);
285
+ if (!schedule) {
286
+ throw import_errors.SchedulerError.notFound(scheduleId);
287
+ }
288
+ if (this.started) {
289
+ this.unscheduleTask(scheduleId);
290
+ }
291
+ await this.storage.deleteSchedule(scheduleId);
292
+ this.logger.info(`Schedule deleted: ${schedule.name}`, { scheduleId });
293
+ }
294
+ /**
295
+ * Get a schedule by ID
296
+ */
297
+ async getSchedule(scheduleId) {
298
+ return this.storage.loadSchedule(scheduleId);
299
+ }
300
+ /**
301
+ * List schedules with optional filters
302
+ */
303
+ async listSchedules(filters) {
304
+ const schedules = await this.storage.listSchedules();
305
+ if (!filters) {
306
+ return schedules;
307
+ }
308
+ return schedules.filter((schedule) => {
309
+ if (filters.enabled !== void 0 && schedule.enabled !== filters.enabled) {
310
+ return false;
311
+ }
312
+ return true;
313
+ });
314
+ }
315
+ /**
316
+ * Trigger a schedule immediately (manual execution)
317
+ */
318
+ async triggerScheduleNow(scheduleId) {
319
+ const schedule = await this.storage.loadSchedule(scheduleId);
320
+ if (!schedule) {
321
+ throw import_errors.SchedulerError.notFound(scheduleId);
322
+ }
323
+ this.logger.info(`Manually triggering schedule: ${schedule.name}`, { scheduleId });
324
+ return this.executeSchedule(schedule);
325
+ }
326
+ /**
327
+ * Get execution history for a schedule
328
+ */
329
+ async getExecutionHistory(scheduleId, limit) {
330
+ return this.storage.getExecutionLogs(scheduleId, limit);
331
+ }
332
+ /**
333
+ * Get scheduler status
334
+ */
335
+ getStatus() {
336
+ return {
337
+ initialized: this.initialized,
338
+ started: this.started,
339
+ activeSchedules: this.cronTasks.size
340
+ };
341
+ }
342
+ /**
343
+ * Schedule a task using cron
344
+ */
345
+ async scheduleTask(schedule) {
346
+ this.unscheduleTask(schedule.id);
347
+ if (!schedule.enabled) {
348
+ return;
349
+ }
350
+ try {
351
+ const task = import_node_cron.default.schedule(
352
+ schedule.cronExpression,
353
+ () => {
354
+ this.executeSchedule(schedule).catch((error) => {
355
+ this.logger.error(
356
+ `Failed to execute schedule ${schedule.id}: ${error instanceof Error ? error.message : String(error)}`
357
+ );
358
+ });
359
+ },
360
+ {
361
+ timezone: schedule.timezone,
362
+ name: schedule.id
363
+ }
364
+ );
365
+ task.start();
366
+ this.cronTasks.set(schedule.id, task);
367
+ this.logger.debug(`Schedule task registered: ${schedule.name}`, {
368
+ scheduleId: schedule.id,
369
+ cronExpression: schedule.cronExpression
370
+ });
371
+ } catch (error) {
372
+ throw import_errors.SchedulerError.createFailed(
373
+ `Failed to schedule task: ${error instanceof Error ? error.message : String(error)}`
374
+ );
375
+ }
376
+ }
377
+ /**
378
+ * Unschedule a task
379
+ */
380
+ unscheduleTask(scheduleId) {
381
+ const task = this.cronTasks.get(scheduleId);
382
+ if (task) {
383
+ task.stop();
384
+ this.cronTasks.delete(scheduleId);
385
+ this.logger.debug(`Schedule task unregistered: ${scheduleId}`);
386
+ }
387
+ }
388
+ /**
389
+ * Execute a schedule
390
+ */
391
+ async executeSchedule(schedule) {
392
+ return await this.queueExecution(() => this.executeScheduleInternal(schedule));
393
+ }
394
+ async executeScheduleInternal(schedule) {
395
+ try {
396
+ const current = await this.storage.loadSchedule(schedule.id);
397
+ if (!current) {
398
+ throw import_errors.SchedulerError.notFound(schedule.id);
399
+ }
400
+ const log = await this.executor.execute(current);
401
+ await this.storage.saveExecutionLog(log);
402
+ const updates = {
403
+ lastRunAt: log.triggeredAt,
404
+ runCount: current.runCount + 1,
405
+ updatedAt: Date.now()
406
+ };
407
+ if (log.status === "success") {
408
+ updates.successCount = current.successCount + 1;
409
+ } else if (log.status === "failed" || log.status === "timeout") {
410
+ updates.failureCount = current.failureCount + 1;
411
+ if (log.error) {
412
+ updates.lastError = log.error;
413
+ }
414
+ }
415
+ const nextRun = this.calculateNextRun(current);
416
+ if (nextRun !== void 0) {
417
+ updates.nextRunAt = nextRun;
418
+ }
419
+ const updated = { ...current, ...updates };
420
+ await this.storage.saveSchedule(updated);
421
+ return log;
422
+ } catch (error) {
423
+ if (error instanceof import_core.DextoRuntimeError) {
424
+ throw error;
425
+ }
426
+ throw import_errors.SchedulerError.executionFailed(
427
+ schedule.id,
428
+ error instanceof Error ? error.message : String(error)
429
+ );
430
+ }
431
+ }
432
+ queueExecution(fn) {
433
+ const run = this.executionChain.then(fn);
434
+ this.executionChain = run.then(
435
+ () => void 0,
436
+ () => void 0
437
+ );
438
+ return run;
439
+ }
440
+ /**
441
+ * Calculate next run time for a schedule
442
+ */
443
+ calculateNextRun(schedule) {
444
+ try {
445
+ const interval = cronParser.parseExpression(schedule.cronExpression, {
446
+ tz: schedule.timezone
447
+ });
448
+ const next = interval.next();
449
+ return next.toDate().getTime();
450
+ } catch (error) {
451
+ this.logger.error(
452
+ `Failed to calculate next run: ${error instanceof Error ? error.message : String(error)}`
453
+ );
454
+ return void 0;
455
+ }
456
+ }
457
+ }
458
+ // Annotate the CommonJS export names for ESM import in node:
459
+ 0 && (module.exports = {
460
+ SchedulerManager
461
+ });
@@ -0,0 +1,113 @@
1
+ import { StorageManager, Logger } from '@dexto/core';
2
+ import { SchedulerToolsConfig, CreateScheduleInput, UpdateScheduleInput } from './schemas.cjs';
3
+ import { ScheduleExecutorFn, Schedule, ScheduleFilters, ExecutionLog } from './types.cjs';
4
+ import 'zod';
5
+
6
+ /**
7
+ * Scheduler Manager - Core service for internal task scheduling
8
+ */
9
+
10
+ /**
11
+ * Scheduler Manager
12
+ *
13
+ * Core service for internal task scheduling. Manages cron-based schedules
14
+ * that execute tasks via the agent.
15
+ *
16
+ * Key features:
17
+ * - Cron-based scheduling with timezone support
18
+ * - Persistent schedules (survive agent restarts)
19
+ * - Direct agent execution (zero HTTP overhead)
20
+ * - Logging-based observability
21
+ * - Self-configurable via tools
22
+ */
23
+ declare class SchedulerManager {
24
+ private config;
25
+ private logger;
26
+ private cronTasks;
27
+ private storage;
28
+ private executor;
29
+ private executionChain;
30
+ private initialized;
31
+ private started;
32
+ private cachedSchedules;
33
+ constructor(storageManager: StorageManager, config: SchedulerToolsConfig, logger: Logger);
34
+ /**
35
+ * Set the executor function (called to run the agent with a prompt)
36
+ */
37
+ setExecutor(fn: ScheduleExecutorFn): void;
38
+ /**
39
+ * Initialize the scheduler (load schedules from storage)
40
+ */
41
+ init(): Promise<void>;
42
+ /**
43
+ * Start the scheduler (begin executing schedules)
44
+ */
45
+ start(): Promise<void>;
46
+ /**
47
+ * Stop the scheduler (stop all running tasks)
48
+ */
49
+ stop(): Promise<void>;
50
+ /**
51
+ * Create a new schedule
52
+ *
53
+ * @param input - Schedule creation input
54
+ * @param currentSessionId - The current session ID (used for 'inherit' mode)
55
+ */
56
+ createSchedule(input: CreateScheduleInput, currentSessionId?: string): Promise<Schedule>;
57
+ /**
58
+ * Update an existing schedule
59
+ *
60
+ * @param scheduleId - The schedule ID to update
61
+ * @param updates - The updates to apply
62
+ * @param currentSessionId - The current session ID (used if changing to 'inherit' mode)
63
+ */
64
+ updateSchedule(scheduleId: string, updates: Omit<UpdateScheduleInput, 'scheduleId'>, currentSessionId?: string): Promise<Schedule>;
65
+ /**
66
+ * Delete a schedule
67
+ */
68
+ deleteSchedule(scheduleId: string): Promise<void>;
69
+ /**
70
+ * Get a schedule by ID
71
+ */
72
+ getSchedule(scheduleId: string): Promise<Schedule | null>;
73
+ /**
74
+ * List schedules with optional filters
75
+ */
76
+ listSchedules(filters?: ScheduleFilters): Promise<Schedule[]>;
77
+ /**
78
+ * Trigger a schedule immediately (manual execution)
79
+ */
80
+ triggerScheduleNow(scheduleId: string): Promise<ExecutionLog>;
81
+ /**
82
+ * Get execution history for a schedule
83
+ */
84
+ getExecutionHistory(scheduleId: string, limit?: number): Promise<ExecutionLog[]>;
85
+ /**
86
+ * Get scheduler status
87
+ */
88
+ getStatus(): {
89
+ initialized: boolean;
90
+ started: boolean;
91
+ activeSchedules: number;
92
+ };
93
+ /**
94
+ * Schedule a task using cron
95
+ */
96
+ private scheduleTask;
97
+ /**
98
+ * Unschedule a task
99
+ */
100
+ private unscheduleTask;
101
+ /**
102
+ * Execute a schedule
103
+ */
104
+ private executeSchedule;
105
+ private executeScheduleInternal;
106
+ private queueExecution;
107
+ /**
108
+ * Calculate next run time for a schedule
109
+ */
110
+ private calculateNextRun;
111
+ }
112
+
113
+ export { SchedulerManager };
@@ -0,0 +1,113 @@
1
+ import { StorageManager, Logger } from '@dexto/core';
2
+ import { SchedulerToolsConfig, CreateScheduleInput, UpdateScheduleInput } from './schemas.js';
3
+ import { ScheduleExecutorFn, Schedule, ScheduleFilters, ExecutionLog } from './types.js';
4
+ import 'zod';
5
+
6
+ /**
7
+ * Scheduler Manager - Core service for internal task scheduling
8
+ */
9
+
10
+ /**
11
+ * Scheduler Manager
12
+ *
13
+ * Core service for internal task scheduling. Manages cron-based schedules
14
+ * that execute tasks via the agent.
15
+ *
16
+ * Key features:
17
+ * - Cron-based scheduling with timezone support
18
+ * - Persistent schedules (survive agent restarts)
19
+ * - Direct agent execution (zero HTTP overhead)
20
+ * - Logging-based observability
21
+ * - Self-configurable via tools
22
+ */
23
+ declare class SchedulerManager {
24
+ private config;
25
+ private logger;
26
+ private cronTasks;
27
+ private storage;
28
+ private executor;
29
+ private executionChain;
30
+ private initialized;
31
+ private started;
32
+ private cachedSchedules;
33
+ constructor(storageManager: StorageManager, config: SchedulerToolsConfig, logger: Logger);
34
+ /**
35
+ * Set the executor function (called to run the agent with a prompt)
36
+ */
37
+ setExecutor(fn: ScheduleExecutorFn): void;
38
+ /**
39
+ * Initialize the scheduler (load schedules from storage)
40
+ */
41
+ init(): Promise<void>;
42
+ /**
43
+ * Start the scheduler (begin executing schedules)
44
+ */
45
+ start(): Promise<void>;
46
+ /**
47
+ * Stop the scheduler (stop all running tasks)
48
+ */
49
+ stop(): Promise<void>;
50
+ /**
51
+ * Create a new schedule
52
+ *
53
+ * @param input - Schedule creation input
54
+ * @param currentSessionId - The current session ID (used for 'inherit' mode)
55
+ */
56
+ createSchedule(input: CreateScheduleInput, currentSessionId?: string): Promise<Schedule>;
57
+ /**
58
+ * Update an existing schedule
59
+ *
60
+ * @param scheduleId - The schedule ID to update
61
+ * @param updates - The updates to apply
62
+ * @param currentSessionId - The current session ID (used if changing to 'inherit' mode)
63
+ */
64
+ updateSchedule(scheduleId: string, updates: Omit<UpdateScheduleInput, 'scheduleId'>, currentSessionId?: string): Promise<Schedule>;
65
+ /**
66
+ * Delete a schedule
67
+ */
68
+ deleteSchedule(scheduleId: string): Promise<void>;
69
+ /**
70
+ * Get a schedule by ID
71
+ */
72
+ getSchedule(scheduleId: string): Promise<Schedule | null>;
73
+ /**
74
+ * List schedules with optional filters
75
+ */
76
+ listSchedules(filters?: ScheduleFilters): Promise<Schedule[]>;
77
+ /**
78
+ * Trigger a schedule immediately (manual execution)
79
+ */
80
+ triggerScheduleNow(scheduleId: string): Promise<ExecutionLog>;
81
+ /**
82
+ * Get execution history for a schedule
83
+ */
84
+ getExecutionHistory(scheduleId: string, limit?: number): Promise<ExecutionLog[]>;
85
+ /**
86
+ * Get scheduler status
87
+ */
88
+ getStatus(): {
89
+ initialized: boolean;
90
+ started: boolean;
91
+ activeSchedules: number;
92
+ };
93
+ /**
94
+ * Schedule a task using cron
95
+ */
96
+ private scheduleTask;
97
+ /**
98
+ * Unschedule a task
99
+ */
100
+ private unscheduleTask;
101
+ /**
102
+ * Execute a schedule
103
+ */
104
+ private executeSchedule;
105
+ private executeScheduleInternal;
106
+ private queueExecution;
107
+ /**
108
+ * Calculate next run time for a schedule
109
+ */
110
+ private calculateNextRun;
111
+ }
112
+
113
+ export { SchedulerManager };