fix(ci): restore persisted state guards

This commit is contained in:
Vincent Koc
2026-05-16 18:05:59 +08:00
parent b05fcad7a7
commit 46a67d30af
4 changed files with 21 additions and 9 deletions

View File

@@ -38,6 +38,7 @@ Docs: https://docs.openclaw.ai
- Commitments: strip malformed optional reminder scope metadata from persisted commitments before matching pending follow-ups.
- Config persistence: normalize malformed auth profile credential fields/state, skip JSON-valid garbage transcript checkpoint rows, and let `openclaw doctor --fix` remove unrepairable cron job rows.
- Cron: skip persisted job rows with malformed schedule or payload shapes in memory, leaving the store for `openclaw doctor --fix` instead of hydrating them into runtime state.
- Cron: keep legacy string schedules and blank system-event jobs available for runtime repair/skip handling instead of dropping them as malformed persisted rows.
- Task persistence: drop malformed array/scalar requester-origin JSON from task and task-flow SQLite sidecars instead of restoring it as delivery metadata.
- Agents/timeouts: clarify model idle-timeout errors and docs so provider `timeoutSeconds` is shown as bounded by the whole agent/run timeout ceiling.
- Release tooling: align the published launcher Node floor, `npm start`, package script checks, sharded lint locking, Vitest root project coverage, and plugin-SDK declaration build cache metadata so release/package validation does not silently skip or ship stale surfaces.

View File

@@ -370,12 +370,17 @@ function buildModelRows(params: {
modelIndex: params.pendingModelIndex,
userId: params.userId,
}),
options: runtimeChoices.map((choice) => ({
label: choice.label,
value: choice.id,
default: choice.id === selectedRuntime,
...(choice.description ? { description: choice.description } : {}),
})),
options: runtimeChoices.map((choice) => {
const option: APISelectMenuOption = {
label: choice.label,
value: choice.id,
default: choice.id === selectedRuntime,
};
if (choice.description) {
option.description = choice.description;
}
return option;
}),
placeholder: "Select runtime",
}),
]),

View File

@@ -15,7 +15,13 @@ export function getInvalidPersistedCronJobReason(
return "missing-id";
}
const schedule = candidate.schedule;
if (!schedule || typeof schedule !== "object" || Array.isArray(schedule)) {
if (!schedule || Array.isArray(schedule)) {
return "missing-schedule";
}
if (typeof schedule === "string") {
return null;
}
if (typeof schedule !== "object") {
return "missing-schedule";
}
const scheduleRecord = schedule as Record<string, unknown>;
@@ -52,7 +58,7 @@ export function getInvalidPersistedCronJobReason(
}
if (payloadKind === "systemEvent") {
const text = payloadRecord.text;
if (typeof text !== "string" || text.trim().length === 0) {
if (typeof text !== "string") {
return "invalid-payload";
}
}

View File

@@ -301,7 +301,7 @@ async function expectPendingPairingRequestsIsolatedByAccount(params: {
describe("pairing store", () => {
it("skips malformed persisted pairing requests while approving valid codes", async () => {
await withTempStateDir(async (stateDir) => {
const now = new Date("2026-05-16T05:20:00.000Z").toISOString();
const now = new Date().toISOString();
writeJsonFixture(resolvePairingFilePath(stateDir, "telegram"), {
version: 1,
requests: [