@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.
- package/LICENSE +44 -0
- package/dist/error-codes.cjs +44 -0
- package/dist/error-codes.d.cts +21 -0
- package/dist/error-codes.d.ts +21 -0
- package/dist/error-codes.js +20 -0
- package/dist/errors.cjs +163 -0
- package/dist/errors.d.cts +64 -0
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +138 -0
- package/dist/executor.cjs +161 -0
- package/dist/executor.d.cts +46 -0
- package/dist/executor.d.ts +46 -0
- package/dist/executor.js +137 -0
- package/dist/index.cjs +89 -0
- package/dist/index.d.cts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +56 -0
- package/dist/manager.cjs +461 -0
- package/dist/manager.d.cts +113 -0
- package/dist/manager.d.ts +113 -0
- package/dist/manager.js +430 -0
- package/dist/schemas.cjs +138 -0
- package/dist/schemas.d.cts +263 -0
- package/dist/schemas.d.ts +263 -0
- package/dist/schemas.js +105 -0
- package/dist/storage.cjs +249 -0
- package/dist/storage.d.cts +62 -0
- package/dist/storage.d.ts +62 -0
- package/dist/storage.js +225 -0
- package/dist/tool-provider.cjs +239 -0
- package/dist/tool-provider.d.cts +34 -0
- package/dist/tool-provider.d.ts +34 -0
- package/dist/tool-provider.js +212 -0
- package/dist/tool-types.cjs +16 -0
- package/dist/tool-types.d.cts +9 -0
- package/dist/tool-types.d.ts +9 -0
- package/dist/tool-types.js +0 -0
- package/dist/tools/create-schedule.cjs +75 -0
- package/dist/tools/create-schedule.d.cts +14 -0
- package/dist/tools/create-schedule.d.ts +14 -0
- package/dist/tools/create-schedule.js +51 -0
- package/dist/tools/delete-schedule.cjs +45 -0
- package/dist/tools/delete-schedule.d.cts +14 -0
- package/dist/tools/delete-schedule.d.ts +14 -0
- package/dist/tools/delete-schedule.js +21 -0
- package/dist/tools/get-history.cjs +63 -0
- package/dist/tools/get-history.d.cts +14 -0
- package/dist/tools/get-history.d.ts +14 -0
- package/dist/tools/get-history.js +39 -0
- package/dist/tools/get-schedule.cjs +68 -0
- package/dist/tools/get-schedule.d.cts +14 -0
- package/dist/tools/get-schedule.d.ts +14 -0
- package/dist/tools/get-schedule.js +44 -0
- package/dist/tools/list-schedules.cjs +67 -0
- package/dist/tools/list-schedules.d.cts +14 -0
- package/dist/tools/list-schedules.d.ts +14 -0
- package/dist/tools/list-schedules.js +43 -0
- package/dist/tools/trigger-schedule.cjs +56 -0
- package/dist/tools/trigger-schedule.d.cts +14 -0
- package/dist/tools/trigger-schedule.d.ts +14 -0
- package/dist/tools/trigger-schedule.js +32 -0
- package/dist/tools/update-schedule.cjs +53 -0
- package/dist/tools/update-schedule.d.cts +14 -0
- package/dist/tools/update-schedule.d.ts +14 -0
- package/dist/tools/update-schedule.js +29 -0
- package/dist/types.cjs +16 -0
- package/dist/types.d.cts +72 -0
- package/dist/types.d.ts +72 -0
- package/dist/types.js +0 -0
- package/package.json +41 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var tool_provider_exports = {};
|
|
20
|
+
__export(tool_provider_exports, {
|
|
21
|
+
createSchedulerTools: () => createSchedulerTools,
|
|
22
|
+
ensureSchedulerManagerForAgent: () => ensureSchedulerManagerForAgent,
|
|
23
|
+
getSchedulerManager: () => getSchedulerManager,
|
|
24
|
+
schedulerToolsFactory: () => schedulerToolsFactory
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(tool_provider_exports);
|
|
27
|
+
var import_core = require("@dexto/core");
|
|
28
|
+
var import_schemas = require("./schemas.js");
|
|
29
|
+
var import_manager = require("./manager.js");
|
|
30
|
+
var import_errors = require("./errors.js");
|
|
31
|
+
var import_create_schedule = require("./tools/create-schedule.js");
|
|
32
|
+
var import_list_schedules = require("./tools/list-schedules.js");
|
|
33
|
+
var import_get_schedule = require("./tools/get-schedule.js");
|
|
34
|
+
var import_update_schedule = require("./tools/update-schedule.js");
|
|
35
|
+
var import_delete_schedule = require("./tools/delete-schedule.js");
|
|
36
|
+
var import_trigger_schedule = require("./tools/trigger-schedule.js");
|
|
37
|
+
var import_get_history = require("./tools/get-history.js");
|
|
38
|
+
const schedulerManagerRegistry = /* @__PURE__ */ new Map();
|
|
39
|
+
const schedulerConfigRegistry = /* @__PURE__ */ new Map();
|
|
40
|
+
const schedulerManagerInitPromises = /* @__PURE__ */ new Map();
|
|
41
|
+
let defaultSchedulerConfig;
|
|
42
|
+
function getSchedulerManager(agentId) {
|
|
43
|
+
return schedulerManagerRegistry.get(agentId);
|
|
44
|
+
}
|
|
45
|
+
async function ensureSchedulerManagerForAgent(agent, config, loggerOverride) {
|
|
46
|
+
if (!agent) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const agentId = agent.config?.agentId ?? "default";
|
|
50
|
+
const existing = schedulerManagerRegistry.get(agentId);
|
|
51
|
+
if (existing) {
|
|
52
|
+
return existing;
|
|
53
|
+
}
|
|
54
|
+
const inflight = schedulerManagerInitPromises.get(agentId);
|
|
55
|
+
if (inflight) {
|
|
56
|
+
return inflight;
|
|
57
|
+
}
|
|
58
|
+
const agentConfig = schedulerConfigRegistry.get(agentId);
|
|
59
|
+
const resolvedConfig = config ?? agentConfig ?? defaultSchedulerConfig;
|
|
60
|
+
if (!resolvedConfig) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
if (!config && !agentConfig && defaultSchedulerConfig) {
|
|
64
|
+
const logger = loggerOverride ?? agent.logger;
|
|
65
|
+
logger.debug("Using default scheduler config", { agentId });
|
|
66
|
+
}
|
|
67
|
+
const initPromise = (async () => {
|
|
68
|
+
const storageManager = agent.services?.storageManager;
|
|
69
|
+
if (!storageManager) {
|
|
70
|
+
throw import_errors.SchedulerError.missingStorage();
|
|
71
|
+
}
|
|
72
|
+
const logger = loggerOverride ?? agent.logger;
|
|
73
|
+
const manager = new import_manager.SchedulerManager(storageManager, resolvedConfig, logger);
|
|
74
|
+
const waitForAgentStart = async () => {
|
|
75
|
+
if (!agent || typeof agent.isStarted !== "function") {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
if (agent.isStarted()) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
const timeoutMs = 15e3;
|
|
82
|
+
const startAt = Date.now();
|
|
83
|
+
while (!agent.isStarted()) {
|
|
84
|
+
if (typeof agent.isStopped === "function" && agent.isStopped()) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
if (Date.now() - startAt > timeoutMs) {
|
|
88
|
+
logger.warn("Scheduler start delayed: agent did not finish starting in time.");
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
};
|
|
95
|
+
const withWorkspaceContext = async (workspacePath, handler) => {
|
|
96
|
+
if (!agent || typeof agent.getWorkspace !== "function") {
|
|
97
|
+
return await handler();
|
|
98
|
+
}
|
|
99
|
+
const previous = await agent.getWorkspace();
|
|
100
|
+
const needsChange = workspacePath ? previous?.path !== workspacePath : Boolean(previous);
|
|
101
|
+
if (needsChange) {
|
|
102
|
+
if (workspacePath) {
|
|
103
|
+
await agent.setWorkspace({ path: workspacePath });
|
|
104
|
+
} else {
|
|
105
|
+
await agent.clearWorkspace();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
return await handler();
|
|
110
|
+
} finally {
|
|
111
|
+
if (needsChange) {
|
|
112
|
+
try {
|
|
113
|
+
if (!previous) {
|
|
114
|
+
await agent.clearWorkspace();
|
|
115
|
+
} else {
|
|
116
|
+
await agent.setWorkspace({
|
|
117
|
+
path: previous.path,
|
|
118
|
+
...previous.name ? { name: previous.name } : {}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
} catch (restoreError) {
|
|
122
|
+
logger.error("Failed to restore workspace after scheduled execution", {
|
|
123
|
+
error: restoreError instanceof Error ? restoreError.message : String(restoreError)
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
manager.setExecutor(async ({ prompt, sessionId, schedule }) => {
|
|
130
|
+
const ready2 = await waitForAgentStart();
|
|
131
|
+
if (!ready2) {
|
|
132
|
+
throw import_errors.SchedulerError.executionFailed(
|
|
133
|
+
schedule.id,
|
|
134
|
+
"Agent is not started. Scheduled execution skipped."
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
agent.emit("run:invoke", {
|
|
138
|
+
sessionId,
|
|
139
|
+
content: [{ type: "text", text: prompt }],
|
|
140
|
+
source: "scheduler",
|
|
141
|
+
metadata: {
|
|
142
|
+
trigger: "cron",
|
|
143
|
+
scheduleId: schedule.id,
|
|
144
|
+
scheduleName: schedule.name
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
const workspacePath = schedule.workspacePath;
|
|
148
|
+
const response = await withWorkspaceContext(
|
|
149
|
+
workspacePath,
|
|
150
|
+
() => agent.generate(prompt, sessionId)
|
|
151
|
+
);
|
|
152
|
+
return response.content;
|
|
153
|
+
});
|
|
154
|
+
await manager.init();
|
|
155
|
+
const ready = await waitForAgentStart();
|
|
156
|
+
if (ready) {
|
|
157
|
+
try {
|
|
158
|
+
await manager.start();
|
|
159
|
+
logger.info("Scheduler started successfully");
|
|
160
|
+
} catch (error) {
|
|
161
|
+
await manager.stop().catch(() => void 0);
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
logger.warn("Scheduler start skipped because agent is not ready.");
|
|
166
|
+
}
|
|
167
|
+
schedulerManagerRegistry.set(agentId, manager);
|
|
168
|
+
schedulerConfigRegistry.set(agentId, resolvedConfig);
|
|
169
|
+
agent.services?.toolManager?.registerCleanup(async () => {
|
|
170
|
+
await manager.stop();
|
|
171
|
+
schedulerManagerRegistry.delete(agentId);
|
|
172
|
+
schedulerConfigRegistry.delete(agentId);
|
|
173
|
+
});
|
|
174
|
+
return manager;
|
|
175
|
+
})();
|
|
176
|
+
schedulerManagerInitPromises.set(agentId, initPromise);
|
|
177
|
+
try {
|
|
178
|
+
return await initPromise;
|
|
179
|
+
} finally {
|
|
180
|
+
schedulerManagerInitPromises.delete(agentId);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function createSchedulerTools(manager) {
|
|
184
|
+
return [
|
|
185
|
+
(0, import_create_schedule.createCreateScheduleTool)(async (_context) => manager),
|
|
186
|
+
(0, import_list_schedules.createListSchedulesTool)(async (_context) => manager),
|
|
187
|
+
(0, import_get_schedule.createGetScheduleTool)(async (_context) => manager),
|
|
188
|
+
(0, import_update_schedule.createUpdateScheduleTool)(async (_context) => manager),
|
|
189
|
+
(0, import_delete_schedule.createDeleteScheduleTool)(async (_context) => manager),
|
|
190
|
+
(0, import_trigger_schedule.createTriggerScheduleTool)(async (_context) => manager),
|
|
191
|
+
(0, import_get_history.createGetScheduleHistoryTool)(async (_context) => manager)
|
|
192
|
+
];
|
|
193
|
+
}
|
|
194
|
+
const schedulerToolsFactory = {
|
|
195
|
+
configSchema: import_schemas.SchedulerToolsConfigSchema,
|
|
196
|
+
metadata: {
|
|
197
|
+
displayName: "Scheduler Tools",
|
|
198
|
+
description: "Cron-based scheduling and automations",
|
|
199
|
+
category: "workflow"
|
|
200
|
+
},
|
|
201
|
+
create: (config) => {
|
|
202
|
+
if (!defaultSchedulerConfig) {
|
|
203
|
+
defaultSchedulerConfig = config;
|
|
204
|
+
}
|
|
205
|
+
const getManager = async (context) => {
|
|
206
|
+
if (context.agent) {
|
|
207
|
+
const agentId = context.agent.config?.agentId ?? "default";
|
|
208
|
+
schedulerConfigRegistry.set(agentId, config);
|
|
209
|
+
}
|
|
210
|
+
const manager = await ensureSchedulerManagerForAgent(
|
|
211
|
+
context.agent,
|
|
212
|
+
config,
|
|
213
|
+
context.logger
|
|
214
|
+
);
|
|
215
|
+
if (!manager) {
|
|
216
|
+
throw import_core.ToolError.configInvalid(
|
|
217
|
+
"scheduler-tools requires ToolExecutionContext.agent"
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
return manager;
|
|
221
|
+
};
|
|
222
|
+
return [
|
|
223
|
+
(0, import_create_schedule.createCreateScheduleTool)(getManager),
|
|
224
|
+
(0, import_list_schedules.createListSchedulesTool)(getManager),
|
|
225
|
+
(0, import_get_schedule.createGetScheduleTool)(getManager),
|
|
226
|
+
(0, import_update_schedule.createUpdateScheduleTool)(getManager),
|
|
227
|
+
(0, import_delete_schedule.createDeleteScheduleTool)(getManager),
|
|
228
|
+
(0, import_trigger_schedule.createTriggerScheduleTool)(getManager),
|
|
229
|
+
(0, import_get_history.createGetScheduleHistoryTool)(getManager)
|
|
230
|
+
];
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
234
|
+
0 && (module.exports = {
|
|
235
|
+
createSchedulerTools,
|
|
236
|
+
ensureSchedulerManagerForAgent,
|
|
237
|
+
getSchedulerManager,
|
|
238
|
+
schedulerToolsFactory
|
|
239
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ToolFactory } from '@dexto/agent-config';
|
|
2
|
+
import { ToolExecutionContext, Logger, Tool } from '@dexto/core';
|
|
3
|
+
import { SchedulerToolsConfig } from './schemas.cjs';
|
|
4
|
+
import { SchedulerManager } from './manager.cjs';
|
|
5
|
+
import 'zod';
|
|
6
|
+
import './types.cjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Scheduler Tools Factory
|
|
10
|
+
*
|
|
11
|
+
* Provides cron-based scheduling capabilities for proactive agent behavior.
|
|
12
|
+
* When a scheduled task triggers, it invokes the agent with the task instruction.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get a scheduler manager instance by agent ID.
|
|
17
|
+
* Returns undefined if no scheduler is registered for the agent.
|
|
18
|
+
*/
|
|
19
|
+
declare function getSchedulerManager(agentId: string): SchedulerManager | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Ensure a scheduler manager is available for the given agent.
|
|
22
|
+
* Returns null if scheduler tools are not enabled in this process.
|
|
23
|
+
*/
|
|
24
|
+
declare function ensureSchedulerManagerForAgent(agent: ToolExecutionContext['agent'], config?: SchedulerToolsConfig, loggerOverride?: Logger): Promise<SchedulerManager | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Create scheduler tools from an existing manager instance.
|
|
27
|
+
*/
|
|
28
|
+
declare function createSchedulerTools(manager: SchedulerManager): Tool[];
|
|
29
|
+
/**
|
|
30
|
+
* Scheduler tools factory for Dexto agents.
|
|
31
|
+
*/
|
|
32
|
+
declare const schedulerToolsFactory: ToolFactory<SchedulerToolsConfig>;
|
|
33
|
+
|
|
34
|
+
export { createSchedulerTools, ensureSchedulerManagerForAgent, getSchedulerManager, schedulerToolsFactory };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ToolFactory } from '@dexto/agent-config';
|
|
2
|
+
import { ToolExecutionContext, Logger, Tool } from '@dexto/core';
|
|
3
|
+
import { SchedulerToolsConfig } from './schemas.js';
|
|
4
|
+
import { SchedulerManager } from './manager.js';
|
|
5
|
+
import 'zod';
|
|
6
|
+
import './types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Scheduler Tools Factory
|
|
10
|
+
*
|
|
11
|
+
* Provides cron-based scheduling capabilities for proactive agent behavior.
|
|
12
|
+
* When a scheduled task triggers, it invokes the agent with the task instruction.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get a scheduler manager instance by agent ID.
|
|
17
|
+
* Returns undefined if no scheduler is registered for the agent.
|
|
18
|
+
*/
|
|
19
|
+
declare function getSchedulerManager(agentId: string): SchedulerManager | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Ensure a scheduler manager is available for the given agent.
|
|
22
|
+
* Returns null if scheduler tools are not enabled in this process.
|
|
23
|
+
*/
|
|
24
|
+
declare function ensureSchedulerManagerForAgent(agent: ToolExecutionContext['agent'], config?: SchedulerToolsConfig, loggerOverride?: Logger): Promise<SchedulerManager | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Create scheduler tools from an existing manager instance.
|
|
27
|
+
*/
|
|
28
|
+
declare function createSchedulerTools(manager: SchedulerManager): Tool[];
|
|
29
|
+
/**
|
|
30
|
+
* Scheduler tools factory for Dexto agents.
|
|
31
|
+
*/
|
|
32
|
+
declare const schedulerToolsFactory: ToolFactory<SchedulerToolsConfig>;
|
|
33
|
+
|
|
34
|
+
export { createSchedulerTools, ensureSchedulerManagerForAgent, getSchedulerManager, schedulerToolsFactory };
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { ToolError } from "@dexto/core";
|
|
2
|
+
import { SchedulerToolsConfigSchema } from "./schemas.js";
|
|
3
|
+
import { SchedulerManager } from "./manager.js";
|
|
4
|
+
import { SchedulerError } from "./errors.js";
|
|
5
|
+
import { createCreateScheduleTool } from "./tools/create-schedule.js";
|
|
6
|
+
import { createListSchedulesTool } from "./tools/list-schedules.js";
|
|
7
|
+
import { createGetScheduleTool } from "./tools/get-schedule.js";
|
|
8
|
+
import { createUpdateScheduleTool } from "./tools/update-schedule.js";
|
|
9
|
+
import { createDeleteScheduleTool } from "./tools/delete-schedule.js";
|
|
10
|
+
import { createTriggerScheduleTool } from "./tools/trigger-schedule.js";
|
|
11
|
+
import { createGetScheduleHistoryTool } from "./tools/get-history.js";
|
|
12
|
+
const schedulerManagerRegistry = /* @__PURE__ */ new Map();
|
|
13
|
+
const schedulerConfigRegistry = /* @__PURE__ */ new Map();
|
|
14
|
+
const schedulerManagerInitPromises = /* @__PURE__ */ new Map();
|
|
15
|
+
let defaultSchedulerConfig;
|
|
16
|
+
function getSchedulerManager(agentId) {
|
|
17
|
+
return schedulerManagerRegistry.get(agentId);
|
|
18
|
+
}
|
|
19
|
+
async function ensureSchedulerManagerForAgent(agent, config, loggerOverride) {
|
|
20
|
+
if (!agent) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const agentId = agent.config?.agentId ?? "default";
|
|
24
|
+
const existing = schedulerManagerRegistry.get(agentId);
|
|
25
|
+
if (existing) {
|
|
26
|
+
return existing;
|
|
27
|
+
}
|
|
28
|
+
const inflight = schedulerManagerInitPromises.get(agentId);
|
|
29
|
+
if (inflight) {
|
|
30
|
+
return inflight;
|
|
31
|
+
}
|
|
32
|
+
const agentConfig = schedulerConfigRegistry.get(agentId);
|
|
33
|
+
const resolvedConfig = config ?? agentConfig ?? defaultSchedulerConfig;
|
|
34
|
+
if (!resolvedConfig) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (!config && !agentConfig && defaultSchedulerConfig) {
|
|
38
|
+
const logger = loggerOverride ?? agent.logger;
|
|
39
|
+
logger.debug("Using default scheduler config", { agentId });
|
|
40
|
+
}
|
|
41
|
+
const initPromise = (async () => {
|
|
42
|
+
const storageManager = agent.services?.storageManager;
|
|
43
|
+
if (!storageManager) {
|
|
44
|
+
throw SchedulerError.missingStorage();
|
|
45
|
+
}
|
|
46
|
+
const logger = loggerOverride ?? agent.logger;
|
|
47
|
+
const manager = new SchedulerManager(storageManager, resolvedConfig, logger);
|
|
48
|
+
const waitForAgentStart = async () => {
|
|
49
|
+
if (!agent || typeof agent.isStarted !== "function") {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
if (agent.isStarted()) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
const timeoutMs = 15e3;
|
|
56
|
+
const startAt = Date.now();
|
|
57
|
+
while (!agent.isStarted()) {
|
|
58
|
+
if (typeof agent.isStopped === "function" && agent.isStopped()) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (Date.now() - startAt > timeoutMs) {
|
|
62
|
+
logger.warn("Scheduler start delayed: agent did not finish starting in time.");
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
};
|
|
69
|
+
const withWorkspaceContext = async (workspacePath, handler) => {
|
|
70
|
+
if (!agent || typeof agent.getWorkspace !== "function") {
|
|
71
|
+
return await handler();
|
|
72
|
+
}
|
|
73
|
+
const previous = await agent.getWorkspace();
|
|
74
|
+
const needsChange = workspacePath ? previous?.path !== workspacePath : Boolean(previous);
|
|
75
|
+
if (needsChange) {
|
|
76
|
+
if (workspacePath) {
|
|
77
|
+
await agent.setWorkspace({ path: workspacePath });
|
|
78
|
+
} else {
|
|
79
|
+
await agent.clearWorkspace();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
return await handler();
|
|
84
|
+
} finally {
|
|
85
|
+
if (needsChange) {
|
|
86
|
+
try {
|
|
87
|
+
if (!previous) {
|
|
88
|
+
await agent.clearWorkspace();
|
|
89
|
+
} else {
|
|
90
|
+
await agent.setWorkspace({
|
|
91
|
+
path: previous.path,
|
|
92
|
+
...previous.name ? { name: previous.name } : {}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
} catch (restoreError) {
|
|
96
|
+
logger.error("Failed to restore workspace after scheduled execution", {
|
|
97
|
+
error: restoreError instanceof Error ? restoreError.message : String(restoreError)
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
manager.setExecutor(async ({ prompt, sessionId, schedule }) => {
|
|
104
|
+
const ready2 = await waitForAgentStart();
|
|
105
|
+
if (!ready2) {
|
|
106
|
+
throw SchedulerError.executionFailed(
|
|
107
|
+
schedule.id,
|
|
108
|
+
"Agent is not started. Scheduled execution skipped."
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
agent.emit("run:invoke", {
|
|
112
|
+
sessionId,
|
|
113
|
+
content: [{ type: "text", text: prompt }],
|
|
114
|
+
source: "scheduler",
|
|
115
|
+
metadata: {
|
|
116
|
+
trigger: "cron",
|
|
117
|
+
scheduleId: schedule.id,
|
|
118
|
+
scheduleName: schedule.name
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
const workspacePath = schedule.workspacePath;
|
|
122
|
+
const response = await withWorkspaceContext(
|
|
123
|
+
workspacePath,
|
|
124
|
+
() => agent.generate(prompt, sessionId)
|
|
125
|
+
);
|
|
126
|
+
return response.content;
|
|
127
|
+
});
|
|
128
|
+
await manager.init();
|
|
129
|
+
const ready = await waitForAgentStart();
|
|
130
|
+
if (ready) {
|
|
131
|
+
try {
|
|
132
|
+
await manager.start();
|
|
133
|
+
logger.info("Scheduler started successfully");
|
|
134
|
+
} catch (error) {
|
|
135
|
+
await manager.stop().catch(() => void 0);
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
logger.warn("Scheduler start skipped because agent is not ready.");
|
|
140
|
+
}
|
|
141
|
+
schedulerManagerRegistry.set(agentId, manager);
|
|
142
|
+
schedulerConfigRegistry.set(agentId, resolvedConfig);
|
|
143
|
+
agent.services?.toolManager?.registerCleanup(async () => {
|
|
144
|
+
await manager.stop();
|
|
145
|
+
schedulerManagerRegistry.delete(agentId);
|
|
146
|
+
schedulerConfigRegistry.delete(agentId);
|
|
147
|
+
});
|
|
148
|
+
return manager;
|
|
149
|
+
})();
|
|
150
|
+
schedulerManagerInitPromises.set(agentId, initPromise);
|
|
151
|
+
try {
|
|
152
|
+
return await initPromise;
|
|
153
|
+
} finally {
|
|
154
|
+
schedulerManagerInitPromises.delete(agentId);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function createSchedulerTools(manager) {
|
|
158
|
+
return [
|
|
159
|
+
createCreateScheduleTool(async (_context) => manager),
|
|
160
|
+
createListSchedulesTool(async (_context) => manager),
|
|
161
|
+
createGetScheduleTool(async (_context) => manager),
|
|
162
|
+
createUpdateScheduleTool(async (_context) => manager),
|
|
163
|
+
createDeleteScheduleTool(async (_context) => manager),
|
|
164
|
+
createTriggerScheduleTool(async (_context) => manager),
|
|
165
|
+
createGetScheduleHistoryTool(async (_context) => manager)
|
|
166
|
+
];
|
|
167
|
+
}
|
|
168
|
+
const schedulerToolsFactory = {
|
|
169
|
+
configSchema: SchedulerToolsConfigSchema,
|
|
170
|
+
metadata: {
|
|
171
|
+
displayName: "Scheduler Tools",
|
|
172
|
+
description: "Cron-based scheduling and automations",
|
|
173
|
+
category: "workflow"
|
|
174
|
+
},
|
|
175
|
+
create: (config) => {
|
|
176
|
+
if (!defaultSchedulerConfig) {
|
|
177
|
+
defaultSchedulerConfig = config;
|
|
178
|
+
}
|
|
179
|
+
const getManager = async (context) => {
|
|
180
|
+
if (context.agent) {
|
|
181
|
+
const agentId = context.agent.config?.agentId ?? "default";
|
|
182
|
+
schedulerConfigRegistry.set(agentId, config);
|
|
183
|
+
}
|
|
184
|
+
const manager = await ensureSchedulerManagerForAgent(
|
|
185
|
+
context.agent,
|
|
186
|
+
config,
|
|
187
|
+
context.logger
|
|
188
|
+
);
|
|
189
|
+
if (!manager) {
|
|
190
|
+
throw ToolError.configInvalid(
|
|
191
|
+
"scheduler-tools requires ToolExecutionContext.agent"
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
return manager;
|
|
195
|
+
};
|
|
196
|
+
return [
|
|
197
|
+
createCreateScheduleTool(getManager),
|
|
198
|
+
createListSchedulesTool(getManager),
|
|
199
|
+
createGetScheduleTool(getManager),
|
|
200
|
+
createUpdateScheduleTool(getManager),
|
|
201
|
+
createDeleteScheduleTool(getManager),
|
|
202
|
+
createTriggerScheduleTool(getManager),
|
|
203
|
+
createGetScheduleHistoryTool(getManager)
|
|
204
|
+
];
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
export {
|
|
208
|
+
createSchedulerTools,
|
|
209
|
+
ensureSchedulerManagerForAgent,
|
|
210
|
+
getSchedulerManager,
|
|
211
|
+
schedulerToolsFactory
|
|
212
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
var tool_types_exports = {};
|
|
16
|
+
module.exports = __toCommonJS(tool_types_exports);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ToolExecutionContext } from '@dexto/core';
|
|
2
|
+
import { SchedulerManager } from './manager.cjs';
|
|
3
|
+
import './schemas.cjs';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import './types.cjs';
|
|
6
|
+
|
|
7
|
+
type SchedulerManagerGetter = (context: ToolExecutionContext) => Promise<SchedulerManager>;
|
|
8
|
+
|
|
9
|
+
export type { SchedulerManagerGetter };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ToolExecutionContext } from '@dexto/core';
|
|
2
|
+
import { SchedulerManager } from './manager.js';
|
|
3
|
+
import './schemas.js';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import './types.js';
|
|
6
|
+
|
|
7
|
+
type SchedulerManagerGetter = (context: ToolExecutionContext) => Promise<SchedulerManager>;
|
|
8
|
+
|
|
9
|
+
export type { SchedulerManagerGetter };
|
|
File without changes
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var create_schedule_exports = {};
|
|
20
|
+
__export(create_schedule_exports, {
|
|
21
|
+
createCreateScheduleTool: () => createCreateScheduleTool
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(create_schedule_exports);
|
|
24
|
+
var import_schemas = require("../schemas.js");
|
|
25
|
+
function createCreateScheduleTool(getManager) {
|
|
26
|
+
return {
|
|
27
|
+
id: "create_schedule",
|
|
28
|
+
description: `Create a scheduled task that executes automatically at specified times.
|
|
29
|
+
|
|
30
|
+
Session Modes (sessionMode parameter):
|
|
31
|
+
\u2022 "ephemeral" (default) - Fresh isolated session each run. Use for: daily reports, monitoring, standalone tasks
|
|
32
|
+
\u2022 "dedicated" - Persistent session for this schedule. Use for: tracking progress over time, building context across runs
|
|
33
|
+
\u2022 "inherit" - Continue in THIS conversation. Use for: "remind me in 1 hour", "check back on this later"
|
|
34
|
+
\u2022 "fixed" - Use specific sessionId. Use for: posting to a known thread, cross-session orchestration
|
|
35
|
+
|
|
36
|
+
Agent Targeting (targetAgentId parameter):
|
|
37
|
+
\u2022 Specifies which agent should execute the scheduled task
|
|
38
|
+
\u2022 Examples: "notes" for notes agent, "filesystem" for file operations, "coding" for code tasks
|
|
39
|
+
\u2022 If not specified, executes in the orchestrator's context
|
|
40
|
+
\u2022 Use this to delegate specialized tasks to the appropriate app agent
|
|
41
|
+
|
|
42
|
+
Examples:
|
|
43
|
+
- Daily standup reminder: sessionMode="ephemeral", cronExpression="0 9 * * 1-5"
|
|
44
|
+
- Track project daily: sessionMode="dedicated", cronExpression="0 18 * * *"
|
|
45
|
+
- Remind me in 2 hours: sessionMode="inherit", cronExpression="0 14 * * *" (one-time)
|
|
46
|
+
- Notes backup at midnight: targetAgentId="notes", cronExpression="0 0 * * *"
|
|
47
|
+
- Daily code review: targetAgentId="coding", cronExpression="0 17 * * 1-5"`,
|
|
48
|
+
inputSchema: import_schemas.CreateScheduleInputSchema,
|
|
49
|
+
execute: async (input, context) => {
|
|
50
|
+
const typedInput = input;
|
|
51
|
+
const manager = await getManager(context);
|
|
52
|
+
const schedule = await manager.createSchedule(typedInput, context.sessionId);
|
|
53
|
+
const sessionInfo = schedule.sessionMode === "inherit" ? `Session: Inheriting current conversation (${schedule.sessionId})` : schedule.sessionMode === "fixed" ? `Session: Fixed to ${schedule.sessionId}` : schedule.sessionMode === "dedicated" ? `Session: Dedicated thread for this schedule` : `Session: New isolated session each run`;
|
|
54
|
+
const targetAgent = schedule.task.metadata?.__os_targetAgentId;
|
|
55
|
+
const targetInfo = targetAgent ? `Target Agent: ${targetAgent}` : `Target Agent: orchestrator (default)`;
|
|
56
|
+
const message = `Schedule created successfully
|
|
57
|
+
|
|
58
|
+
ID: ${schedule.id}
|
|
59
|
+
Name: ${schedule.name}
|
|
60
|
+
Cron: ${schedule.cronExpression}
|
|
61
|
+
Timezone: ${schedule.timezone}
|
|
62
|
+
Mode: ${schedule.sessionMode}
|
|
63
|
+
${sessionInfo}
|
|
64
|
+
${targetInfo}
|
|
65
|
+
Next run: ${schedule.nextRunAt ? new Date(schedule.nextRunAt).toISOString() : "calculating..."}
|
|
66
|
+
|
|
67
|
+
The schedule is now active and will execute automatically.`;
|
|
68
|
+
return { message, schedule };
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
73
|
+
0 && (module.exports = {
|
|
74
|
+
createCreateScheduleTool
|
|
75
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Tool } from '@dexto/core';
|
|
2
|
+
import { SchedulerManagerGetter } from '../tool-types.cjs';
|
|
3
|
+
import '../manager.cjs';
|
|
4
|
+
import '../schemas.cjs';
|
|
5
|
+
import 'zod';
|
|
6
|
+
import '../types.cjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Tool for creating schedules
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
declare function createCreateScheduleTool(getManager: SchedulerManagerGetter): Tool;
|
|
13
|
+
|
|
14
|
+
export { createCreateScheduleTool };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Tool } from '@dexto/core';
|
|
2
|
+
import { SchedulerManagerGetter } from '../tool-types.js';
|
|
3
|
+
import '../manager.js';
|
|
4
|
+
import '../schemas.js';
|
|
5
|
+
import 'zod';
|
|
6
|
+
import '../types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Tool for creating schedules
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
declare function createCreateScheduleTool(getManager: SchedulerManagerGetter): Tool;
|
|
13
|
+
|
|
14
|
+
export { createCreateScheduleTool };
|