Cron: normalize cron.add inputs + align channels (#256)

* fix: harden cron add and align channels

* fix: keep cron tool id params

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
Marcus Neves
2026-01-05 23:09:48 -03:00
committed by GitHub
parent 00061b2fd3
commit 67e1452f4a
21 changed files with 457 additions and 48 deletions

View File

@@ -35,14 +35,31 @@ describe("cron tool", () => {
expect(call.params).toEqual(expectedParams);
});
it("rejects jobId params", async () => {
it("normalizes cron.add job payloads", async () => {
const tool = createCronTool();
await expect(
tool.execute("call2", {
action: "update",
jobId: "job-1",
patch: { foo: "bar" },
}),
).rejects.toThrow("id required");
await tool.execute("call2", {
action: "add",
job: {
data: {
name: "wake-up",
schedule: { atMs: 123 },
payload: { text: "hello" },
},
},
});
expect(callGatewayMock).toHaveBeenCalledTimes(1);
const call = callGatewayMock.mock.calls[0]?.[0] as {
method?: string;
params?: unknown;
};
expect(call.method).toBe("cron.add");
expect(call.params).toEqual({
name: "wake-up",
schedule: { kind: "at", atMs: 123 },
sessionTarget: "main",
wakeMode: "next-heartbeat",
payload: { kind: "systemEvent", text: "hello" },
});
});
});

View File

@@ -2,6 +2,13 @@ import { Type } from "@sinclair/typebox";
import { type AnyAgentTool, jsonResult, readStringParam } from "./common.js";
import { callGatewayTool, type GatewayCallOptions } from "./gateway.js";
import { CronAddParamsSchema } from "../../gateway/protocol/schema.js";
import {
normalizeCronJobCreate,
normalizeCronJobPatch,
} from "../../cron/normalize.js";
const CronJobPatchSchema = Type.Partial(CronAddParamsSchema);
const CronToolSchema = Type.Union([
Type.Object({
@@ -22,7 +29,7 @@ const CronToolSchema = Type.Union([
gatewayUrl: Type.Optional(Type.String()),
gatewayToken: Type.Optional(Type.String()),
timeoutMs: Type.Optional(Type.Number()),
job: Type.Object({}, { additionalProperties: true }),
job: CronAddParamsSchema,
}),
Type.Object({
action: Type.Literal("update"),
@@ -30,7 +37,7 @@ const CronToolSchema = Type.Union([
gatewayToken: Type.Optional(Type.String()),
timeoutMs: Type.Optional(Type.Number()),
id: Type.String(),
patch: Type.Object({}, { additionalProperties: true }),
patch: CronJobPatchSchema,
}),
Type.Object({
action: Type.Literal("remove"),
@@ -97,8 +104,9 @@ export function createCronTool(): AnyAgentTool {
if (!params.job || typeof params.job !== "object") {
throw new Error("job required");
}
const job = normalizeCronJobCreate(params.job) ?? params.job;
return jsonResult(
await callGatewayTool("cron.add", gatewayOpts, params.job),
await callGatewayTool("cron.add", gatewayOpts, job),
);
}
case "update": {
@@ -106,10 +114,11 @@ export function createCronTool(): AnyAgentTool {
if (!params.patch || typeof params.patch !== "object") {
throw new Error("patch required");
}
const patch = normalizeCronJobPatch(params.patch) ?? params.patch;
return jsonResult(
await callGatewayTool("cron.update", gatewayOpts, {
id,
patch: params.patch,
patch,
}),
);
}