chore: migrate to oxlint and oxfmt

Co-authored-by: Christoph Nakazawa <christoph.pojer@gmail.com>
This commit is contained in:
Peter Steinberger
2026-01-14 14:31:43 +00:00
parent 912ebffc63
commit c379191f80
1480 changed files with 28608 additions and 43547 deletions

View File

@@ -12,9 +12,7 @@ import type { CronServiceState } from "./state.js";
const STUCK_RUN_MS = 2 * 60 * 60 * 1000;
export function assertSupportedJobSpec(
job: Pick<CronJob, "sessionTarget" | "payload">,
) {
export function assertSupportedJobSpec(job: Pick<CronJob, "sessionTarget" | "payload">) {
if (job.sessionTarget === "main" && job.payload.kind !== "systemEvent") {
throw new Error('main cron jobs require payload.kind="systemEvent"');
}
@@ -29,15 +27,11 @@ export function findJobOrThrow(state: CronServiceState, id: string) {
return job;
}
export function computeJobNextRunAtMs(
job: CronJob,
nowMs: number,
): number | undefined {
export function computeJobNextRunAtMs(job: CronJob, nowMs: number): number | undefined {
if (!job.enabled) return undefined;
if (job.schedule.kind === "at") {
// One-shot jobs stay due until they successfully finish.
if (job.state.lastStatus === "ok" && job.state.lastRunAtMs)
return undefined;
if (job.state.lastStatus === "ok" && job.state.lastRunAtMs) return undefined;
return job.schedule.atMs;
}
return computeNextRunAtMs(job.schedule, nowMs);
@@ -67,9 +61,7 @@ export function recomputeNextRuns(state: CronServiceState) {
export function nextWakeAtMs(state: CronServiceState) {
const jobs = state.store?.jobs ?? [];
const enabled = jobs.filter(
(j) => j.enabled && typeof j.state.nextRunAtMs === "number",
);
const enabled = jobs.filter((j) => j.enabled && typeof j.state.nextRunAtMs === "number");
if (enabled.length === 0) return undefined;
return enabled.reduce(
(min, j) => Math.min(min, j.state.nextRunAtMs as number),
@@ -77,10 +69,7 @@ export function nextWakeAtMs(state: CronServiceState) {
);
}
export function createJob(
state: CronServiceState,
input: CronJobCreate,
): CronJob {
export function createJob(state: CronServiceState, input: CronJobCreate): CronJob {
const now = state.deps.nowMs();
const id = crypto.randomUUID();
const job: CronJob = {
@@ -108,11 +97,9 @@ export function createJob(
export function applyJobPatch(job: CronJob, patch: CronJobPatch) {
if ("name" in patch) job.name = normalizeRequiredName(patch.name);
if ("description" in patch)
job.description = normalizeOptionalText(patch.description);
if ("description" in patch) job.description = normalizeOptionalText(patch.description);
if (typeof patch.enabled === "boolean") job.enabled = patch.enabled;
if (typeof patch.deleteAfterRun === "boolean")
job.deleteAfterRun = patch.deleteAfterRun;
if (typeof patch.deleteAfterRun === "boolean") job.deleteAfterRun = patch.deleteAfterRun;
if (patch.schedule) job.schedule = patch.schedule;
if (patch.sessionTarget) job.sessionTarget = patch.sessionTarget;
if (patch.wakeMode) job.wakeMode = patch.wakeMode;
@@ -120,24 +107,14 @@ export function applyJobPatch(job: CronJob, patch: CronJobPatch) {
if (patch.isolation) job.isolation = patch.isolation;
if (patch.state) job.state = { ...job.state, ...patch.state };
if ("agentId" in patch) {
job.agentId = normalizeOptionalAgentId(
(patch as { agentId?: unknown }).agentId,
);
job.agentId = normalizeOptionalAgentId((patch as { agentId?: unknown }).agentId);
}
assertSupportedJobSpec(job);
}
export function isJobDue(
job: CronJob,
nowMs: number,
opts: { forced: boolean },
) {
export function isJobDue(job: CronJob, nowMs: number, opts: { forced: boolean }) {
if (opts.forced) return true;
return (
job.enabled &&
typeof job.state.nextRunAtMs === "number" &&
nowMs >= job.state.nextRunAtMs
);
return job.enabled && typeof job.state.nextRunAtMs === "number" && nowMs >= job.state.nextRunAtMs;
}
export function resolveJobPayloadTextForMain(job: CronJob): string | undefined {

View File

@@ -1,9 +1,6 @@
import type { CronServiceState } from "./state.js";
export async function locked<T>(
state: CronServiceState,
fn: () => Promise<T>,
): Promise<T> {
export async function locked<T>(state: CronServiceState, fn: () => Promise<T>): Promise<T> {
const next = state.op.then(fn, fn);
// Keep the chain alive even when the operation fails.
state.op = next.then(

View File

@@ -34,8 +34,7 @@ export function inferLegacyName(job: {
const text =
job?.payload?.kind === "systemEvent" && typeof job.payload.text === "string"
? job.payload.text
: job?.payload?.kind === "agentTurn" &&
typeof job.payload.message === "string"
: job?.payload?.kind === "agentTurn" && typeof job.payload.message === "string"
? job.payload.message
: "";
const firstLine =

View File

@@ -45,25 +45,17 @@ export async function status(state: CronServiceState) {
enabled: state.deps.cronEnabled,
storePath: state.deps.storePath,
jobs: state.store?.jobs.length ?? 0,
nextWakeAtMs:
state.deps.cronEnabled === true ? (nextWakeAtMs(state) ?? null) : null,
nextWakeAtMs: state.deps.cronEnabled === true ? (nextWakeAtMs(state) ?? null) : null,
};
});
}
export async function list(
state: CronServiceState,
opts?: { includeDisabled?: boolean },
) {
export async function list(state: CronServiceState, opts?: { includeDisabled?: boolean }) {
return await locked(state, async () => {
await ensureLoaded(state);
const includeDisabled = opts?.includeDisabled === true;
const jobs = (state.store?.jobs ?? []).filter(
(j) => includeDisabled || j.enabled,
);
return jobs.sort(
(a, b) => (a.state.nextRunAtMs ?? 0) - (b.state.nextRunAtMs ?? 0),
);
const jobs = (state.store?.jobs ?? []).filter((j) => includeDisabled || j.enabled);
return jobs.sort((a, b) => (a.state.nextRunAtMs ?? 0) - (b.state.nextRunAtMs ?? 0));
});
}
@@ -84,11 +76,7 @@ export async function add(state: CronServiceState, input: CronJobCreate) {
});
}
export async function update(
state: CronServiceState,
id: string,
patch: CronJobPatch,
) {
export async function update(state: CronServiceState, id: string, patch: CronJobPatch) {
return await locked(state, async () => {
warnIfDisabled(state, "update");
await ensureLoaded(state);
@@ -129,11 +117,7 @@ export async function remove(state: CronServiceState, id: string) {
});
}
export async function run(
state: CronServiceState,
id: string,
mode?: "due" | "force",
) {
export async function run(state: CronServiceState, id: string, mode?: "due" | "force") {
return await locked(state, async () => {
warnIfDisabled(state, "run");
await ensureLoaded(state);

View File

@@ -1,10 +1,5 @@
import type { HeartbeatRunResult } from "../../infra/heartbeat-wake.js";
import type {
CronJob,
CronJobCreate,
CronJobPatch,
CronStoreFile,
} from "../types.js";
import type { CronJob, CronJobCreate, CronJobPatch, CronStoreFile } from "../types.js";
export type CronEvent = {
jobId: string;
@@ -31,9 +26,7 @@ export type CronServiceDeps = {
cronEnabled: boolean;
enqueueSystemEvent: (text: string, opts?: { agentId?: string }) => void;
requestHeartbeatNow: (opts?: { reason?: string }) => void;
runHeartbeatOnce?: (opts?: {
reason?: string;
}) => Promise<HeartbeatRunResult>;
runHeartbeatOnce?: (opts?: { reason?: string }) => Promise<HeartbeatRunResult>;
runIsolatedAgentJob: (params: { job: CronJob; message: string }) => Promise<{
status: "ok" | "error" | "skipped";
summary?: string;
@@ -55,9 +48,7 @@ export type CronServiceState = {
warnedDisabled: boolean;
};
export function createCronServiceState(
deps: CronServiceDeps,
): CronServiceState {
export function createCronServiceState(deps: CronServiceDeps): CronServiceState {
return {
deps: { ...deps, nowMs: deps.nowMs ?? (() => Date.now()) },
store: null,
@@ -83,9 +74,7 @@ export type CronRunResult =
| { ok: true; ran: false; reason: "not-due" }
| { ok: false };
export type CronRemoveResult =
| { ok: true; removed: boolean }
| { ok: false; removed: false };
export type CronRemoveResult = { ok: true; removed: boolean } | { ok: false; removed: false };
export type CronAddResult = CronJob;
export type CronUpdateResult = CronJob;

View File

@@ -1,10 +1,6 @@
import type { HeartbeatRunResult } from "../../infra/heartbeat-wake.js";
import type { CronJob } from "../types.js";
import {
computeJobNextRunAtMs,
nextWakeAtMs,
resolveJobPayloadTextForMain,
} from "./jobs.js";
import { computeJobNextRunAtMs, nextWakeAtMs, resolveJobPayloadTextForMain } from "./jobs.js";
import { locked } from "./locked.js";
import type { CronEvent, CronServiceState } from "./state.js";
import { ensureLoaded, persist } from "./store.js";
@@ -70,11 +66,7 @@ export async function executeJob(
let deleted = false;
const finish = async (
status: "ok" | "error" | "skipped",
err?: string,
summary?: string,
) => {
const finish = async (status: "ok" | "error" | "skipped", err?: string, summary?: string) => {
const endedAt = state.deps.nowMs();
job.state.runningAtMs = undefined;
job.state.lastRunAtMs = startedAt;
@@ -83,9 +75,7 @@ export async function executeJob(
job.state.lastError = err;
const shouldDelete =
job.schedule.kind === "at" &&
status === "ok" &&
job.deleteAfterRun === true;
job.schedule.kind === "at" && status === "ok" && job.deleteAfterRun === true;
if (!shouldDelete) {
if (job.schedule.kind === "at" && status === "ok") {
@@ -145,8 +135,7 @@ export async function executeJob(
state.deps.enqueueSystemEvent(text, { agentId: job.agentId });
if (job.wakeMode === "now" && state.deps.runHeartbeatOnce) {
const reason = `cron:${job.id}`;
const delay = (ms: number) =>
new Promise<void>((resolve) => setTimeout(resolve, ms));
const delay = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));
const maxWaitMs = 2 * 60_000;
const waitStartedAt = state.deps.nowMs();
@@ -194,8 +183,7 @@ export async function executeJob(
message: job.payload.message,
});
if (res.status === "ok") await finish("ok", undefined, res.summary);
else if (res.status === "skipped")
await finish("skipped", undefined, res.summary);
else if (res.status === "skipped") await finish("skipped", undefined, res.summary);
else await finish("error", res.error ?? "cron job failed", res.summary);
} catch (err) {
await finish("error", String(err));