@dexto/server 1.5.8 → 1.6.1
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/events/a2a-sse-subscriber.d.ts +1 -1
- package/dist/hono/__tests__/test-fixtures.cjs +27 -6
- package/dist/hono/__tests__/test-fixtures.d.ts +2 -1
- package/dist/hono/__tests__/test-fixtures.d.ts.map +1 -1
- package/dist/hono/__tests__/test-fixtures.js +31 -6
- package/dist/hono/index.cjs +17 -2
- package/dist/hono/index.d.ts +874 -58
- package/dist/hono/index.d.ts.map +1 -1
- package/dist/hono/index.js +17 -2
- package/dist/hono/routes/a2a-tasks.d.ts +6 -6
- package/dist/hono/routes/agents.cjs +38 -27
- package/dist/hono/routes/agents.d.ts +2 -1
- package/dist/hono/routes/agents.d.ts.map +1 -1
- package/dist/hono/routes/agents.js +37 -31
- package/dist/hono/routes/discovery.cjs +99 -22
- package/dist/hono/routes/discovery.d.ts +14 -12
- package/dist/hono/routes/discovery.d.ts.map +1 -1
- package/dist/hono/routes/discovery.js +89 -22
- package/dist/hono/routes/llm.d.ts +2 -2
- package/dist/hono/routes/mcp.cjs +96 -14
- package/dist/hono/routes/mcp.d.ts +139 -4
- package/dist/hono/routes/mcp.d.ts.map +1 -1
- package/dist/hono/routes/mcp.js +97 -15
- package/dist/hono/routes/memory.d.ts +1 -1
- package/dist/hono/routes/models.d.ts +1 -1
- package/dist/hono/routes/resources.d.ts +1 -1
- package/dist/hono/routes/schedules.cjs +456 -0
- package/dist/hono/routes/schedules.d.ts +472 -0
- package/dist/hono/routes/schedules.d.ts.map +1 -0
- package/dist/hono/routes/schedules.js +439 -0
- package/dist/hono/routes/search.d.ts +1 -1
- package/dist/hono/routes/sessions.cjs +10 -4
- package/dist/hono/routes/sessions.d.ts +135 -5
- package/dist/hono/routes/sessions.d.ts.map +1 -1
- package/dist/hono/routes/sessions.js +10 -4
- package/dist/hono/routes/tools.cjs +12 -19
- package/dist/hono/routes/tools.d.ts +5 -3
- package/dist/hono/routes/tools.d.ts.map +1 -1
- package/dist/hono/routes/tools.js +12 -19
- package/dist/hono/routes/workspaces.cjs +136 -0
- package/dist/hono/routes/workspaces.d.ts +77 -0
- package/dist/hono/routes/workspaces.d.ts.map +1 -0
- package/dist/hono/routes/workspaces.js +112 -0
- package/dist/hono/schemas/responses.cjs +82 -7
- package/dist/hono/schemas/responses.d.ts +366 -16
- package/dist/hono/schemas/responses.d.ts.map +1 -1
- package/dist/hono/schemas/responses.js +75 -6
- package/dist/hono/start-server.cjs +3 -3
- package/dist/hono/start-server.d.ts +15 -6
- package/dist/hono/start-server.d.ts.map +1 -1
- package/dist/hono/start-server.js +3 -3
- package/dist/index.cjs +9 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/mcp/mcp-handler.d.ts +2 -2
- package/dist/mcp/mcp-handler.d.ts.map +1 -1
- package/package.json +8 -5
package/dist/hono/routes/mcp.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
|
|
2
|
-
import { logger, McpServerConfigSchema, MCP_CONNECTION_STATUSES } from "@dexto/core";
|
|
2
|
+
import { AgentError, logger, McpServerConfigSchema, MCP_CONNECTION_STATUSES } from "@dexto/core";
|
|
3
3
|
import { updateAgentConfigFile } from "@dexto/agent-management";
|
|
4
4
|
import { ResourceSchema } from "../schemas/responses.js";
|
|
5
5
|
const McpServerRequestSchema = z.object({
|
|
6
6
|
name: z.string().min(1, "Server name is required").describe("A unique name for the server"),
|
|
7
7
|
config: McpServerConfigSchema.describe("The server configuration object"),
|
|
8
8
|
persistToAgent: z.boolean().optional().describe("If true, saves the server to agent configuration file")
|
|
9
|
-
}).describe("Request body for adding or updating an MCP server");
|
|
9
|
+
}).strict().describe("Request body for adding or updating an MCP server");
|
|
10
|
+
const McpServerUpdateSchema = z.object({
|
|
11
|
+
config: McpServerConfigSchema.describe("The updated server configuration object"),
|
|
12
|
+
persistToAgent: z.boolean().optional().describe("If true, saves the server to agent configuration file")
|
|
13
|
+
}).strict().describe("Request body for updating an MCP server");
|
|
10
14
|
const ExecuteToolBodySchema = z.record(z.unknown()).describe(
|
|
11
15
|
"Tool execution parameters as JSON object. The specific fields depend on the tool being executed and are defined by the tool's inputSchema."
|
|
12
16
|
);
|
|
@@ -37,7 +41,8 @@ const ToolInfoSchema = z.object({
|
|
|
37
41
|
id: z.string().describe("Tool identifier"),
|
|
38
42
|
name: z.string().describe("Tool name"),
|
|
39
43
|
description: z.string().describe("Tool description"),
|
|
40
|
-
inputSchema: ToolInputSchema.optional().describe("JSON Schema for tool input parameters")
|
|
44
|
+
inputSchema: ToolInputSchema.optional().describe("JSON Schema for tool input parameters"),
|
|
45
|
+
_meta: z.record(z.unknown()).optional().describe("Optional tool metadata (e.g., MCP Apps UI resource info)")
|
|
41
46
|
}).strict().describe("Tool information");
|
|
42
47
|
const ToolsListResponseSchema = z.object({
|
|
43
48
|
tools: z.array(ToolInfoSchema).describe("Array of available tools")
|
|
@@ -55,6 +60,10 @@ const ToolExecutionResponseSchema = z.object({
|
|
|
55
60
|
data: z.any().optional().describe("Tool execution result data"),
|
|
56
61
|
error: z.string().optional().describe("Error message if execution failed")
|
|
57
62
|
}).strict().describe("Tool execution response");
|
|
63
|
+
const ServerConfigResponseSchema = z.object({
|
|
64
|
+
name: z.string().describe("Server name"),
|
|
65
|
+
config: McpServerConfigSchema.describe("Server configuration")
|
|
66
|
+
}).strict().describe("MCP server configuration response");
|
|
58
67
|
const ResourcesListResponseSchema = z.object({
|
|
59
68
|
success: z.boolean().describe("Success indicator"),
|
|
60
69
|
resources: z.array(ResourceSchema).describe("Array of available resources")
|
|
@@ -66,7 +75,7 @@ const ResourceContentResponseSchema = z.object({
|
|
|
66
75
|
success: z.boolean().describe("Success indicator"),
|
|
67
76
|
data: ResourceContentSchema.describe("Resource content")
|
|
68
77
|
}).strict().describe("Resource content response");
|
|
69
|
-
function createMcpRouter(getAgent) {
|
|
78
|
+
function createMcpRouter(getAgent, getAgentConfigPath) {
|
|
70
79
|
const app = new OpenAPIHono();
|
|
71
80
|
const addServerRoute = createRoute({
|
|
72
81
|
method: "post",
|
|
@@ -95,6 +104,41 @@ function createMcpRouter(getAgent) {
|
|
|
95
104
|
}
|
|
96
105
|
}
|
|
97
106
|
});
|
|
107
|
+
const getServerConfigRoute = createRoute({
|
|
108
|
+
method: "get",
|
|
109
|
+
path: "/mcp/servers/{serverId}/config",
|
|
110
|
+
summary: "Get MCP Server Config",
|
|
111
|
+
description: "Retrieves the configuration for a specific MCP server",
|
|
112
|
+
tags: ["mcp"],
|
|
113
|
+
request: {
|
|
114
|
+
params: z.object({ serverId: z.string().describe("The ID of the MCP server") })
|
|
115
|
+
},
|
|
116
|
+
responses: {
|
|
117
|
+
200: {
|
|
118
|
+
description: "Server configuration",
|
|
119
|
+
content: { "application/json": { schema: ServerConfigResponseSchema } }
|
|
120
|
+
},
|
|
121
|
+
404: { description: "Not found" }
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
const updateServerRoute = createRoute({
|
|
125
|
+
method: "put",
|
|
126
|
+
path: "/mcp/servers/{serverId}",
|
|
127
|
+
summary: "Update MCP Server",
|
|
128
|
+
description: "Updates configuration for an existing MCP server",
|
|
129
|
+
tags: ["mcp"],
|
|
130
|
+
request: {
|
|
131
|
+
params: z.object({ serverId: z.string().describe("The ID of the MCP server") }),
|
|
132
|
+
body: { content: { "application/json": { schema: McpServerUpdateSchema } } }
|
|
133
|
+
},
|
|
134
|
+
responses: {
|
|
135
|
+
200: {
|
|
136
|
+
description: "Server updated",
|
|
137
|
+
content: { "application/json": { schema: ServerStatusResponseSchema } }
|
|
138
|
+
},
|
|
139
|
+
404: { description: "Not found" }
|
|
140
|
+
}
|
|
141
|
+
});
|
|
98
142
|
const toolsRoute = createRoute({
|
|
99
143
|
method: "get",
|
|
100
144
|
path: "/mcp/servers/{serverId}/tools",
|
|
@@ -214,6 +258,10 @@ function createMcpRouter(getAgent) {
|
|
|
214
258
|
);
|
|
215
259
|
if (persistToAgent === true) {
|
|
216
260
|
try {
|
|
261
|
+
const agentPath = await getAgentConfigPath(ctx);
|
|
262
|
+
if (!agentPath) {
|
|
263
|
+
throw AgentError.noConfigPath();
|
|
264
|
+
}
|
|
217
265
|
const currentConfig = agent.getEffectiveConfig();
|
|
218
266
|
const updates = {
|
|
219
267
|
mcpServers: {
|
|
@@ -221,16 +269,7 @@ function createMcpRouter(getAgent) {
|
|
|
221
269
|
[name]: config
|
|
222
270
|
}
|
|
223
271
|
};
|
|
224
|
-
|
|
225
|
-
agent.getAgentFilePath(),
|
|
226
|
-
updates
|
|
227
|
-
);
|
|
228
|
-
const reloadResult = await agent.reload(newConfig);
|
|
229
|
-
if (reloadResult.restarted) {
|
|
230
|
-
logger.info(
|
|
231
|
-
`Agent restarted to apply changes: ${reloadResult.changesApplied.join(", ")}`
|
|
232
|
-
);
|
|
233
|
-
}
|
|
272
|
+
await updateAgentConfigFile(agentPath, updates);
|
|
234
273
|
logger.info(`Saved server '${name}' to agent configuration file`);
|
|
235
274
|
} catch (saveError) {
|
|
236
275
|
const errorMessage = saveError instanceof Error ? saveError.message : String(saveError);
|
|
@@ -256,6 +295,48 @@ function createMcpRouter(getAgent) {
|
|
|
256
295
|
servers.push({ id: name, name, status: "error" });
|
|
257
296
|
}
|
|
258
297
|
return ctx.json({ servers });
|
|
298
|
+
}).openapi(getServerConfigRoute, async (ctx) => {
|
|
299
|
+
const agent = await getAgent(ctx);
|
|
300
|
+
const { serverId } = ctx.req.valid("param");
|
|
301
|
+
const config = agent.getMcpServerConfig(serverId);
|
|
302
|
+
if (!config) {
|
|
303
|
+
return ctx.json({ error: `Server '${serverId}' not found.` }, 404);
|
|
304
|
+
}
|
|
305
|
+
return ctx.json({ name: serverId, config }, 200);
|
|
306
|
+
}).openapi(updateServerRoute, async (ctx) => {
|
|
307
|
+
const agent = await getAgent(ctx);
|
|
308
|
+
const { serverId } = ctx.req.valid("param");
|
|
309
|
+
const { config, persistToAgent } = ctx.req.valid("json");
|
|
310
|
+
const existingConfig = agent.getMcpServerConfig(serverId);
|
|
311
|
+
if (!existingConfig) {
|
|
312
|
+
return ctx.json({ error: `Server '${serverId}' not found.` }, 404);
|
|
313
|
+
}
|
|
314
|
+
await agent.updateMcpServer(serverId, config);
|
|
315
|
+
if (persistToAgent === true) {
|
|
316
|
+
try {
|
|
317
|
+
const agentPath = await getAgentConfigPath(ctx);
|
|
318
|
+
if (!agentPath) {
|
|
319
|
+
throw AgentError.noConfigPath();
|
|
320
|
+
}
|
|
321
|
+
const currentConfig = agent.getEffectiveConfig();
|
|
322
|
+
const updates = {
|
|
323
|
+
mcpServers: {
|
|
324
|
+
...currentConfig.mcpServers || {},
|
|
325
|
+
[serverId]: config
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
await updateAgentConfigFile(agentPath, updates);
|
|
329
|
+
logger.info(`Saved server '${serverId}' to agent configuration file`);
|
|
330
|
+
} catch (saveError) {
|
|
331
|
+
const errorMessage = saveError instanceof Error ? saveError.message : String(saveError);
|
|
332
|
+
logger.warn(
|
|
333
|
+
`Failed to persist MCP server '${serverId}' update: ${errorMessage}`,
|
|
334
|
+
{ error: saveError }
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
const status = config.enabled === false ? "registered" : "connected";
|
|
339
|
+
return ctx.json({ status, name: serverId }, 200);
|
|
259
340
|
}).openapi(toolsRoute, async (ctx) => {
|
|
260
341
|
const agent = await getAgent(ctx);
|
|
261
342
|
const { serverId } = ctx.req.valid("param");
|
|
@@ -268,7 +349,8 @@ function createMcpRouter(getAgent) {
|
|
|
268
349
|
id: toolName,
|
|
269
350
|
name: toolName,
|
|
270
351
|
description: toolDef.description || "",
|
|
271
|
-
inputSchema: toolDef.parameters
|
|
352
|
+
inputSchema: toolDef.parameters,
|
|
353
|
+
_meta: toolDef._meta
|
|
272
354
|
}));
|
|
273
355
|
return ctx.json({ tools });
|
|
274
356
|
}).openapi(deleteServerRoute, async (ctx) => {
|
|
@@ -101,11 +101,11 @@ export declare function createMemoryRouter(getAgent: GetAgentFn): OpenAPIHono<im
|
|
|
101
101
|
};
|
|
102
102
|
} & {
|
|
103
103
|
json: {
|
|
104
|
-
content?: string | undefined;
|
|
105
104
|
metadata?: z.objectInputType<{
|
|
106
105
|
source: z.ZodOptional<z.ZodEnum<["user", "system"]>>;
|
|
107
106
|
pinned: z.ZodOptional<z.ZodBoolean>;
|
|
108
107
|
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
108
|
+
content?: string | undefined;
|
|
109
109
|
tags?: string[] | undefined;
|
|
110
110
|
};
|
|
111
111
|
};
|
|
@@ -15,7 +15,7 @@ export declare function createModelsRouter(): OpenAPIHono<import("hono").Env, {
|
|
|
15
15
|
displayName: string;
|
|
16
16
|
filePath: string;
|
|
17
17
|
sizeBytes: number;
|
|
18
|
-
source?: "
|
|
18
|
+
source?: "huggingface" | "manual" | undefined;
|
|
19
19
|
contextLength?: number | undefined;
|
|
20
20
|
}[];
|
|
21
21
|
};
|
|
@@ -5,7 +5,6 @@ export declare function createResourcesRouter(getAgent: GetAgentFn): OpenAPIHono
|
|
|
5
5
|
$get: {
|
|
6
6
|
input: {};
|
|
7
7
|
output: {
|
|
8
|
-
ok: true;
|
|
9
8
|
resources: {
|
|
10
9
|
uri: string;
|
|
11
10
|
source: "mcp" | "internal";
|
|
@@ -19,6 +18,7 @@ export declare function createResourcesRouter(getAgent: GetAgentFn): OpenAPIHono
|
|
|
19
18
|
size?: number | undefined;
|
|
20
19
|
lastModified?: string | undefined;
|
|
21
20
|
}[];
|
|
21
|
+
ok: true;
|
|
22
22
|
};
|
|
23
23
|
outputFormat: "json";
|
|
24
24
|
status: 200;
|
|
@@ -0,0 +1,456 @@
|
|
|
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 schedules_exports = {};
|
|
20
|
+
__export(schedules_exports, {
|
|
21
|
+
createSchedulesRouter: () => createSchedulesRouter
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(schedules_exports);
|
|
24
|
+
var import_zod_openapi = require("@hono/zod-openapi");
|
|
25
|
+
var import_responses = require("../schemas/responses.js");
|
|
26
|
+
var import_tools_scheduler = require("@dexto/tools-scheduler");
|
|
27
|
+
var import_service = require("@dexto/tools-scheduler/service");
|
|
28
|
+
var import_core = require("@dexto/core");
|
|
29
|
+
const CreateScheduleSchema = import_zod_openapi.z.object({
|
|
30
|
+
name: import_zod_openapi.z.string().min(1).describe("Schedule name"),
|
|
31
|
+
instruction: import_zod_openapi.z.string().min(1).describe("Instruction to run on schedule"),
|
|
32
|
+
cronExpression: import_zod_openapi.z.string().min(1).describe("Cron expression"),
|
|
33
|
+
timezone: import_zod_openapi.z.string().optional().describe("Timezone for schedule"),
|
|
34
|
+
enabled: import_zod_openapi.z.boolean().optional().describe("Whether the schedule is enabled"),
|
|
35
|
+
workspacePath: import_zod_openapi.z.string().optional().nullable().describe("Optional workspace path for scheduled runs")
|
|
36
|
+
}).strict().describe("Request body for creating a schedule");
|
|
37
|
+
const UpdateScheduleSchema = CreateScheduleSchema.partial().strict().describe("Request body for updating a schedule");
|
|
38
|
+
const isScheduleNotFoundError = (error) => error instanceof import_core.DextoRuntimeError && error.type === import_core.ErrorType.NOT_FOUND && error.code === import_tools_scheduler.SchedulerErrorCode.SCHEDULE_NOT_FOUND;
|
|
39
|
+
const logSchedulerError = (agent, message, error) => {
|
|
40
|
+
if (!agent?.logger) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
agent.logger.error(message, {
|
|
44
|
+
error: error instanceof Error ? error.message : String(error ?? "Unknown error"),
|
|
45
|
+
stack: error instanceof Error ? error.stack : void 0,
|
|
46
|
+
code: error instanceof import_core.DextoRuntimeError ? error.code : void 0
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
const toErrorResponse = (message, code) => ({
|
|
50
|
+
ok: false,
|
|
51
|
+
error: {
|
|
52
|
+
message,
|
|
53
|
+
...code ? { code } : {}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
function createSchedulesRouter(getAgent) {
|
|
57
|
+
const app = new import_zod_openapi.OpenAPIHono();
|
|
58
|
+
const resolveScheduler = async (ctx) => {
|
|
59
|
+
const agent = await getAgent(ctx);
|
|
60
|
+
const agentId = agent.config?.agentId ?? "default";
|
|
61
|
+
let scheduler = (0, import_service.getSchedulerManager)(agentId) ?? null;
|
|
62
|
+
if (!scheduler) {
|
|
63
|
+
scheduler = await (0, import_service.ensureSchedulerManagerForAgent)(agent);
|
|
64
|
+
}
|
|
65
|
+
return { scheduler, agent };
|
|
66
|
+
};
|
|
67
|
+
const listRoute = (0, import_zod_openapi.createRoute)({
|
|
68
|
+
method: "get",
|
|
69
|
+
path: "/schedules",
|
|
70
|
+
summary: "List Schedules",
|
|
71
|
+
description: "Retrieves all automation schedules",
|
|
72
|
+
tags: ["schedules"],
|
|
73
|
+
responses: {
|
|
74
|
+
200: {
|
|
75
|
+
description: "List of schedules",
|
|
76
|
+
content: {
|
|
77
|
+
"application/json": {
|
|
78
|
+
schema: import_zod_openapi.z.object({
|
|
79
|
+
schedules: import_zod_openapi.z.array(import_responses.ScheduleSchema).describe("Schedule list")
|
|
80
|
+
}).strict()
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
500: {
|
|
85
|
+
description: "Failed to list schedules",
|
|
86
|
+
content: {
|
|
87
|
+
"application/json": {
|
|
88
|
+
schema: import_responses.ErrorResponseSchema
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
503: {
|
|
93
|
+
description: "Scheduler tools are not enabled",
|
|
94
|
+
content: {
|
|
95
|
+
"application/json": {
|
|
96
|
+
schema: import_responses.ErrorResponseSchema
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
const createRouteDef = (0, import_zod_openapi.createRoute)({
|
|
103
|
+
method: "post",
|
|
104
|
+
path: "/schedules",
|
|
105
|
+
summary: "Create Schedule",
|
|
106
|
+
description: "Creates a new automation schedule",
|
|
107
|
+
tags: ["schedules"],
|
|
108
|
+
request: { body: { content: { "application/json": { schema: CreateScheduleSchema } } } },
|
|
109
|
+
responses: {
|
|
110
|
+
201: {
|
|
111
|
+
description: "Created schedule",
|
|
112
|
+
content: {
|
|
113
|
+
"application/json": {
|
|
114
|
+
schema: import_zod_openapi.z.object({ schedule: import_responses.ScheduleSchema }).strict()
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
400: {
|
|
119
|
+
description: "Validation error",
|
|
120
|
+
content: {
|
|
121
|
+
"application/json": {
|
|
122
|
+
schema: import_responses.ErrorResponseSchema
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
429: {
|
|
127
|
+
description: "Schedule limit reached",
|
|
128
|
+
content: {
|
|
129
|
+
"application/json": {
|
|
130
|
+
schema: import_responses.ErrorResponseSchema
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
500: {
|
|
135
|
+
description: "Failed to create schedule",
|
|
136
|
+
content: {
|
|
137
|
+
"application/json": {
|
|
138
|
+
schema: import_responses.ErrorResponseSchema
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
503: {
|
|
143
|
+
description: "Scheduler tools are not enabled",
|
|
144
|
+
content: {
|
|
145
|
+
"application/json": {
|
|
146
|
+
schema: import_responses.ErrorResponseSchema
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
const updateRoute = (0, import_zod_openapi.createRoute)({
|
|
153
|
+
method: "patch",
|
|
154
|
+
path: "/schedules/{scheduleId}",
|
|
155
|
+
summary: "Update Schedule",
|
|
156
|
+
description: "Updates an existing schedule",
|
|
157
|
+
tags: ["schedules"],
|
|
158
|
+
request: {
|
|
159
|
+
params: import_zod_openapi.z.object({
|
|
160
|
+
scheduleId: import_zod_openapi.z.string().min(1).describe("Schedule ID")
|
|
161
|
+
}).strict().describe("Schedule identifier params"),
|
|
162
|
+
body: { content: { "application/json": { schema: UpdateScheduleSchema } } }
|
|
163
|
+
},
|
|
164
|
+
responses: {
|
|
165
|
+
200: {
|
|
166
|
+
description: "Updated schedule",
|
|
167
|
+
content: {
|
|
168
|
+
"application/json": {
|
|
169
|
+
schema: import_zod_openapi.z.object({ schedule: import_responses.ScheduleSchema }).strict()
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
400: {
|
|
174
|
+
description: "Validation error",
|
|
175
|
+
content: {
|
|
176
|
+
"application/json": {
|
|
177
|
+
schema: import_responses.ErrorResponseSchema
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
404: {
|
|
182
|
+
description: "Schedule not found",
|
|
183
|
+
content: {
|
|
184
|
+
"application/json": {
|
|
185
|
+
schema: import_responses.ErrorResponseSchema
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
500: {
|
|
190
|
+
description: "Failed to update schedule",
|
|
191
|
+
content: {
|
|
192
|
+
"application/json": {
|
|
193
|
+
schema: import_responses.ErrorResponseSchema
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
503: {
|
|
198
|
+
description: "Scheduler tools are not enabled",
|
|
199
|
+
content: {
|
|
200
|
+
"application/json": {
|
|
201
|
+
schema: import_responses.ErrorResponseSchema
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
const deleteRoute = (0, import_zod_openapi.createRoute)({
|
|
208
|
+
method: "delete",
|
|
209
|
+
path: "/schedules/{scheduleId}",
|
|
210
|
+
summary: "Delete Schedule",
|
|
211
|
+
description: "Deletes an automation schedule",
|
|
212
|
+
tags: ["schedules"],
|
|
213
|
+
request: {
|
|
214
|
+
params: import_zod_openapi.z.object({
|
|
215
|
+
scheduleId: import_zod_openapi.z.string().min(1).describe("Schedule ID")
|
|
216
|
+
}).strict().describe("Schedule identifier params")
|
|
217
|
+
},
|
|
218
|
+
responses: {
|
|
219
|
+
200: {
|
|
220
|
+
description: "Schedule deleted",
|
|
221
|
+
content: {
|
|
222
|
+
"application/json": {
|
|
223
|
+
schema: import_zod_openapi.z.object({
|
|
224
|
+
deleted: import_zod_openapi.z.boolean().describe("Whether the schedule was deleted")
|
|
225
|
+
}).strict().describe("Delete schedule response")
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
404: {
|
|
230
|
+
description: "Schedule not found",
|
|
231
|
+
content: {
|
|
232
|
+
"application/json": {
|
|
233
|
+
schema: import_responses.ErrorResponseSchema
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
500: {
|
|
238
|
+
description: "Failed to delete schedule",
|
|
239
|
+
content: {
|
|
240
|
+
"application/json": {
|
|
241
|
+
schema: import_responses.ErrorResponseSchema
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
503: {
|
|
246
|
+
description: "Scheduler tools are not enabled",
|
|
247
|
+
content: {
|
|
248
|
+
"application/json": {
|
|
249
|
+
schema: import_responses.ErrorResponseSchema
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
const triggerRoute = (0, import_zod_openapi.createRoute)({
|
|
256
|
+
method: "post",
|
|
257
|
+
path: "/schedules/{scheduleId}/trigger",
|
|
258
|
+
summary: "Trigger Schedule",
|
|
259
|
+
description: "Runs a schedule immediately and waits for execution to complete (bounded by executionTimeout, default 5 minutes). Clients should set timeouts accordingly.",
|
|
260
|
+
tags: ["schedules"],
|
|
261
|
+
request: {
|
|
262
|
+
params: import_zod_openapi.z.object({
|
|
263
|
+
scheduleId: import_zod_openapi.z.string().min(1).describe("Schedule ID")
|
|
264
|
+
}).strict().describe("Schedule identifier params")
|
|
265
|
+
},
|
|
266
|
+
responses: {
|
|
267
|
+
200: {
|
|
268
|
+
description: "Schedule triggered",
|
|
269
|
+
content: {
|
|
270
|
+
"application/json": {
|
|
271
|
+
schema: import_zod_openapi.z.object({
|
|
272
|
+
scheduled: import_zod_openapi.z.boolean().describe(
|
|
273
|
+
"Whether the schedule was queued. Execution is omitted when false."
|
|
274
|
+
),
|
|
275
|
+
execution: import_responses.ExecutionLogSchema.optional().describe(
|
|
276
|
+
"Execution log (present when scheduled is true)"
|
|
277
|
+
)
|
|
278
|
+
}).strict().describe("Trigger schedule response")
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
404: {
|
|
283
|
+
description: "Schedule not found",
|
|
284
|
+
content: {
|
|
285
|
+
"application/json": {
|
|
286
|
+
schema: import_responses.ErrorResponseSchema
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
500: {
|
|
291
|
+
description: "Failed to trigger schedule",
|
|
292
|
+
content: {
|
|
293
|
+
"application/json": {
|
|
294
|
+
schema: import_responses.ErrorResponseSchema
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
503: {
|
|
299
|
+
description: "Scheduler tools are not enabled",
|
|
300
|
+
content: {
|
|
301
|
+
"application/json": {
|
|
302
|
+
schema: import_responses.ErrorResponseSchema
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
return app.openapi(listRoute, async (ctx) => {
|
|
309
|
+
const { scheduler, agent } = await resolveScheduler(ctx);
|
|
310
|
+
if (!scheduler) {
|
|
311
|
+
return ctx.json(
|
|
312
|
+
toErrorResponse("Scheduler tools are not enabled for this agent."),
|
|
313
|
+
503
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
const schedules = await scheduler.listSchedules();
|
|
318
|
+
return ctx.json({ schedules }, 200);
|
|
319
|
+
} catch (error) {
|
|
320
|
+
const message = error instanceof Error ? error.message : String(error ?? "Unknown error");
|
|
321
|
+
logSchedulerError(agent, "Failed to list schedules", error);
|
|
322
|
+
if (error instanceof import_core.DextoRuntimeError) {
|
|
323
|
+
return ctx.json(toErrorResponse(message, String(error.code)), 500);
|
|
324
|
+
}
|
|
325
|
+
return ctx.json(toErrorResponse("Failed to list schedules"), 500);
|
|
326
|
+
}
|
|
327
|
+
}).openapi(createRouteDef, async (ctx) => {
|
|
328
|
+
const { scheduler, agent } = await resolveScheduler(ctx);
|
|
329
|
+
if (!scheduler) {
|
|
330
|
+
return ctx.json(
|
|
331
|
+
toErrorResponse("Scheduler tools are not enabled for this agent."),
|
|
332
|
+
503
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
const input = ctx.req.valid("json");
|
|
336
|
+
const createPayload = {
|
|
337
|
+
name: input.name,
|
|
338
|
+
instruction: input.instruction,
|
|
339
|
+
cronExpression: input.cronExpression,
|
|
340
|
+
...input.timezone !== void 0 ? { timezone: input.timezone } : {},
|
|
341
|
+
enabled: input.enabled ?? true,
|
|
342
|
+
...input.workspacePath !== void 0 ? { workspacePath: input.workspacePath } : {},
|
|
343
|
+
sessionMode: "dedicated"
|
|
344
|
+
};
|
|
345
|
+
try {
|
|
346
|
+
const schedule = await scheduler.createSchedule(createPayload);
|
|
347
|
+
return ctx.json({ schedule }, 201);
|
|
348
|
+
} catch (error) {
|
|
349
|
+
if (error instanceof import_core.DextoRuntimeError && error.code === import_tools_scheduler.SchedulerErrorCode.SCHEDULE_INVALID_CRON) {
|
|
350
|
+
return ctx.json(toErrorResponse(error.message, String(error.code)), 400);
|
|
351
|
+
}
|
|
352
|
+
if (error instanceof import_core.DextoRuntimeError && error.code === import_tools_scheduler.SchedulerErrorCode.SCHEDULE_INVALID_INPUT) {
|
|
353
|
+
return ctx.json(toErrorResponse(error.message, String(error.code)), 400);
|
|
354
|
+
}
|
|
355
|
+
if (error instanceof import_core.DextoRuntimeError && error.code === import_tools_scheduler.SchedulerErrorCode.SCHEDULE_LIMIT_REACHED) {
|
|
356
|
+
return ctx.json(toErrorResponse(error.message, String(error.code)), 429);
|
|
357
|
+
}
|
|
358
|
+
logSchedulerError(agent, "Failed to create schedule", error);
|
|
359
|
+
return ctx.json(toErrorResponse("Failed to create schedule"), 500);
|
|
360
|
+
}
|
|
361
|
+
}).openapi(updateRoute, async (ctx) => {
|
|
362
|
+
const { scheduler, agent } = await resolveScheduler(ctx);
|
|
363
|
+
if (!scheduler) {
|
|
364
|
+
return ctx.json(
|
|
365
|
+
toErrorResponse("Scheduler tools are not enabled for this agent."),
|
|
366
|
+
503
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
const { scheduleId } = ctx.req.valid("param");
|
|
370
|
+
const input = ctx.req.valid("json");
|
|
371
|
+
const updatePayload = {
|
|
372
|
+
...input.name !== void 0 ? { name: input.name } : {},
|
|
373
|
+
...input.instruction !== void 0 ? { instruction: input.instruction } : {},
|
|
374
|
+
...input.cronExpression !== void 0 ? { cronExpression: input.cronExpression } : {},
|
|
375
|
+
...input.timezone !== void 0 ? { timezone: input.timezone } : {},
|
|
376
|
+
...input.enabled !== void 0 ? { enabled: input.enabled } : {},
|
|
377
|
+
...input.workspacePath !== void 0 ? { workspacePath: input.workspacePath } : {}
|
|
378
|
+
};
|
|
379
|
+
try {
|
|
380
|
+
const schedule = await scheduler.updateSchedule(scheduleId, updatePayload);
|
|
381
|
+
return ctx.json({ schedule }, 200);
|
|
382
|
+
} catch (error) {
|
|
383
|
+
if (isScheduleNotFoundError(error)) {
|
|
384
|
+
return ctx.json(
|
|
385
|
+
toErrorResponse(
|
|
386
|
+
"Schedule not found",
|
|
387
|
+
import_tools_scheduler.SchedulerErrorCode.SCHEDULE_NOT_FOUND
|
|
388
|
+
),
|
|
389
|
+
404
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
if (error instanceof import_core.DextoRuntimeError && error.code === import_tools_scheduler.SchedulerErrorCode.SCHEDULE_INVALID_CRON) {
|
|
393
|
+
return ctx.json(toErrorResponse(error.message, String(error.code)), 400);
|
|
394
|
+
}
|
|
395
|
+
if (error instanceof import_core.DextoRuntimeError && error.code === import_tools_scheduler.SchedulerErrorCode.SCHEDULE_INVALID_INPUT) {
|
|
396
|
+
return ctx.json(toErrorResponse(error.message, String(error.code)), 400);
|
|
397
|
+
}
|
|
398
|
+
logSchedulerError(agent, "Failed to update schedule", error);
|
|
399
|
+
return ctx.json(toErrorResponse("Failed to update schedule"), 500);
|
|
400
|
+
}
|
|
401
|
+
}).openapi(deleteRoute, async (ctx) => {
|
|
402
|
+
const { scheduler, agent } = await resolveScheduler(ctx);
|
|
403
|
+
if (!scheduler) {
|
|
404
|
+
return ctx.json(
|
|
405
|
+
toErrorResponse("Scheduler tools are not enabled for this agent."),
|
|
406
|
+
503
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
const { scheduleId } = ctx.req.valid("param");
|
|
410
|
+
try {
|
|
411
|
+
await scheduler.deleteSchedule(scheduleId);
|
|
412
|
+
return ctx.json({ deleted: true }, 200);
|
|
413
|
+
} catch (error) {
|
|
414
|
+
if (isScheduleNotFoundError(error)) {
|
|
415
|
+
return ctx.json(
|
|
416
|
+
toErrorResponse(
|
|
417
|
+
"Schedule not found",
|
|
418
|
+
import_tools_scheduler.SchedulerErrorCode.SCHEDULE_NOT_FOUND
|
|
419
|
+
),
|
|
420
|
+
404
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
logSchedulerError(agent, "Failed to delete schedule", error);
|
|
424
|
+
return ctx.json(toErrorResponse("Failed to delete schedule"), 500);
|
|
425
|
+
}
|
|
426
|
+
}).openapi(triggerRoute, async (ctx) => {
|
|
427
|
+
const { scheduler, agent } = await resolveScheduler(ctx);
|
|
428
|
+
if (!scheduler) {
|
|
429
|
+
return ctx.json(
|
|
430
|
+
toErrorResponse("Scheduler tools are not enabled for this agent."),
|
|
431
|
+
503
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
const { scheduleId } = ctx.req.valid("param");
|
|
435
|
+
try {
|
|
436
|
+
const execution = await scheduler.triggerScheduleNow(scheduleId);
|
|
437
|
+
return ctx.json({ scheduled: true, execution }, 200);
|
|
438
|
+
} catch (error) {
|
|
439
|
+
if (isScheduleNotFoundError(error)) {
|
|
440
|
+
return ctx.json(
|
|
441
|
+
toErrorResponse(
|
|
442
|
+
"Schedule not found",
|
|
443
|
+
import_tools_scheduler.SchedulerErrorCode.SCHEDULE_NOT_FOUND
|
|
444
|
+
),
|
|
445
|
+
404
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
logSchedulerError(agent, "Failed to trigger schedule", error);
|
|
449
|
+
return ctx.json(toErrorResponse("Failed to trigger schedule"), 500);
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
454
|
+
0 && (module.exports = {
|
|
455
|
+
createSchedulesRouter
|
|
456
|
+
});
|