mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-14 14:12:44 +00:00
123 lines
3.1 KiB
TypeScript
123 lines
3.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
buildCronJobPayload,
|
|
cronJobHasExecutionContent,
|
|
cronJobFormFromJob,
|
|
splitCronList,
|
|
type CronJobFormState,
|
|
} from "./cron-job";
|
|
import type { CronJob } from "./api";
|
|
|
|
function form(overrides: Partial<CronJobFormState> = {}): CronJobFormState {
|
|
return {
|
|
name: "",
|
|
prompt: "prompt",
|
|
schedule: "every 1h",
|
|
deliver: "local",
|
|
skills: [],
|
|
provider: "",
|
|
model: "",
|
|
base_url: "",
|
|
script: "",
|
|
no_agent: false,
|
|
context_from: "",
|
|
enabled_toolsets: [],
|
|
workdir: "",
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("splitCronList", () => {
|
|
it("normalizes comma and newline separated cron list fields", () => {
|
|
expect(splitCronList(" web, terminal\nfile ,, ")).toEqual([
|
|
"web",
|
|
"terminal",
|
|
"file",
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("buildCronJobPayload", () => {
|
|
it("normalizes list fields and base URLs", () => {
|
|
const payload = buildCronJobPayload(
|
|
form({
|
|
base_url: "https://example.invalid/v1/",
|
|
enabled_toolsets: ["web", ""],
|
|
context_from: "upstream-a\nupstream-b",
|
|
}),
|
|
);
|
|
|
|
expect(payload).toMatchObject({
|
|
base_url: "https://example.invalid/v1",
|
|
context_from: ["upstream-a", "upstream-b"],
|
|
enabled_toolsets: ["web"],
|
|
});
|
|
});
|
|
|
|
it("keeps clear operations explicit for update payloads", () => {
|
|
const payload = buildCronJobPayload(form({ schedule: "every 2h" }));
|
|
|
|
expect(payload).toMatchObject({
|
|
schedule: "every 2h",
|
|
provider: null,
|
|
model: null,
|
|
base_url: null,
|
|
script: null,
|
|
no_agent: false,
|
|
context_from: null,
|
|
enabled_toolsets: null,
|
|
workdir: null,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("cronJobHasExecutionContent", () => {
|
|
it("treats a script as execution content for agent-backed cron jobs", () => {
|
|
const payload = buildCronJobPayload(
|
|
form({ prompt: "", skills: [], script: "collect-status.py" }),
|
|
);
|
|
|
|
expect(cronJobHasExecutionContent(payload)).toBe(true);
|
|
});
|
|
|
|
it("rejects payloads with no prompt, skills, or script", () => {
|
|
const payload = buildCronJobPayload(form({ prompt: "", skills: [], script: "" }));
|
|
|
|
expect(cronJobHasExecutionContent(payload)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("cronJobFormFromJob", () => {
|
|
it("preserves schedule fallback and editable list fields", () => {
|
|
const job: CronJob = {
|
|
id: "abc",
|
|
enabled: true,
|
|
schedule_display: "every 1h",
|
|
context_from: ["upstream-a", "upstream-b"],
|
|
enabled_toolsets: ["web"],
|
|
};
|
|
|
|
expect(cronJobFormFromJob(job)).toMatchObject({
|
|
schedule: "every 1h",
|
|
context_from: "upstream-a\nupstream-b",
|
|
enabled_toolsets: ["web"],
|
|
});
|
|
});
|
|
|
|
it("prefers one-shot run_at over the human display string", () => {
|
|
const job: CronJob = {
|
|
id: "once-job",
|
|
enabled: true,
|
|
schedule: {
|
|
kind: "once",
|
|
run_at: "2026-02-03T14:00:00+08:00",
|
|
},
|
|
schedule_display: "once at 2026-02-03 14:00",
|
|
};
|
|
|
|
expect(cronJobFormFromJob(job)).toMatchObject({
|
|
schedule: "2026-02-03T14:00:00+08:00",
|
|
});
|
|
});
|
|
});
|