mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-12 19:46:04 +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.
62 lines
2.3 KiB
TypeScript
62 lines
2.3 KiB
TypeScript
import fs from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
import { openOpenClawStateDatabase } from "../../state/openclaw-state-db.js";
|
|
import type { CronJob } from "../types.js";
|
|
import {
|
|
loadedCronStoreFromRows,
|
|
loadCronRows,
|
|
replaceCronRows,
|
|
updateCronRuntimeRows,
|
|
} from "./row-codec.js";
|
|
import type { CronJobRow } from "./schema.js";
|
|
import { bindTriggerColumns, triggerFromRow } from "./trigger-codec.js";
|
|
|
|
describe("cron trigger SQLite codec", () => {
|
|
it("round-trips trigger columns", () => {
|
|
const columns = bindTriggerColumns({ script: "json({ fire: true })", once: true });
|
|
expect(columns).toEqual({ trigger_script: "json({ fire: true })", trigger_once: 1 });
|
|
expect(triggerFromRow(columns as CronJobRow)).toEqual({
|
|
script: "json({ fire: true })",
|
|
once: true,
|
|
});
|
|
expect(triggerFromRow(bindTriggerColumns(undefined) as CronJobRow)).toBeUndefined();
|
|
});
|
|
|
|
it("round-trips trigger state through updateCronRuntimeRows", async () => {
|
|
const job = {
|
|
id: "job-1",
|
|
name: "watcher",
|
|
enabled: true,
|
|
createdAtMs: 1,
|
|
updatedAtMs: 2,
|
|
schedule: { kind: "every", everyMs: 30_000 },
|
|
trigger: { script: "json({ fire: false })", once: false },
|
|
sessionTarget: "main",
|
|
wakeMode: "now",
|
|
payload: { kind: "systemEvent", text: "changed" },
|
|
state: {
|
|
lastTriggerEvalAtMs: 10,
|
|
triggerEvalCount: 3,
|
|
lastTriggerFireAtMs: 8,
|
|
triggerState: { status: "green" },
|
|
},
|
|
} satisfies CronJob;
|
|
|
|
const fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "cron-trigger-codec-"));
|
|
const handle = openOpenClawStateDatabase({ path: path.join(fixtureRoot, "state.sqlite") });
|
|
try {
|
|
replaceCronRows(handle.db, "test", { version: 1, jobs: [{ ...job, state: {} }] });
|
|
updateCronRuntimeRows(handle.db, "test", { version: 1, jobs: [job] });
|
|
const [decoded] = loadedCronStoreFromRows(loadCronRows(handle.db, "test")).store.jobs;
|
|
expect(decoded?.trigger).toEqual(job.trigger);
|
|
expect(decoded?.state).toEqual(job.state);
|
|
} finally {
|
|
handle.walMaintenance.close();
|
|
handle.db.close();
|
|
await fs.rm(fixtureRoot, { recursive: true, force: true });
|
|
}
|
|
});
|
|
});
|