mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-28 07:51:14 +00:00
* feat(cron): add headless code-mode driver and trigger-script evaluator Part A of cron event triggers: runCodeModeScriptHeadless runs a script to completion (exec/settle/resume, no snapshots, no session), plus the cron-facing evaluator with per-job tool catalog cache, semaphore, 16KB state cap, and closed failure taxonomy. * fix(cron): correct trigger-script bootstrap flags and cache narrowing * feat(cron): add event triggers (polled condition-watcher scripts) Part B: trigger field on cron jobs gated by cron.triggers.enabled; timer evaluates the script each due tick, quiet ticks leave no run history, fired runs append the script message to the payload; once semantics, min-interval floor, SQLite columns, RPC/CLI/agent-tool surfaces, and docs. * fix(cron): propagate triggerEval through startup catch-up outcomes * fix(cron): honor cron staggering on quiet trigger ticks; fix trigger test types * fix(cron): reject with Error reason in trigger-script abort test * fix(cron): regenerate protocol/docs/snapshot artifacts and break madge cycle for trigger types CI fixes for #101195: trigger evaluator result types move to the cron types leaf (madge cycle), cron tool schema inventory gains trigger, Swift protocol bindings + docs map + Linux prompt snapshots regenerated. * fix(cron): drop underscore-dangle names in trigger code sync assert * fix(cron): adopt registerHeadlessToolSearchCatalog after tool-search symbol localization Upstream #101831 made registerToolSearchCatalog module-private; fold the headless ref-only catalog registration into one public seam.
47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { getInvalidPersistedCronJobReason } from "./persisted-shape.js";
|
|
|
|
function candidate(overrides: Record<string, unknown> = {}) {
|
|
return {
|
|
id: "job-1",
|
|
schedule: { kind: "every", everyMs: 30_000 },
|
|
trigger: { script: "json({ fire: true })" },
|
|
payload: { kind: "systemEvent", text: "changed" },
|
|
sessionTarget: "main",
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("persisted cron trigger shape", () => {
|
|
it("accepts a non-empty trigger on recurring schedules", () => {
|
|
expect(getInvalidPersistedCronJobReason(candidate())).toBeNull();
|
|
expect(
|
|
getInvalidPersistedCronJobReason(
|
|
candidate({ schedule: { kind: "cron", expr: "* * * * *" } }),
|
|
),
|
|
).toBeNull();
|
|
});
|
|
|
|
it("rejects empty scripts and non-object triggers", () => {
|
|
expect(getInvalidPersistedCronJobReason(candidate({ trigger: { script: " " } }))).toBe(
|
|
"invalid-trigger",
|
|
);
|
|
expect(getInvalidPersistedCronJobReason(candidate({ trigger: "script" }))).toBe(
|
|
"invalid-trigger",
|
|
);
|
|
});
|
|
|
|
it("rejects triggers on at and on-exit schedules", () => {
|
|
expect(
|
|
getInvalidPersistedCronJobReason(
|
|
candidate({ schedule: { kind: "at", at: "2026-08-01T00:00:00.000Z" } }),
|
|
),
|
|
).toBe("invalid-trigger");
|
|
expect(
|
|
getInvalidPersistedCronJobReason(
|
|
candidate({ schedule: { kind: "on-exit", command: "make build" } }),
|
|
),
|
|
).toBe("invalid-trigger");
|
|
});
|
|
});
|