refactor: extract isolated cron execution seams

This commit is contained in:
Peter Steinberger
2026-04-04 14:41:37 +01:00
parent 083b882052
commit 91d20781ed
4 changed files with 137 additions and 20 deletions

View File

@@ -0,0 +1,17 @@
export { resolveEffectiveModelFallbacks } from "../../agents/agent-scope.js";
export { resolveBootstrapWarningSignaturesSeen } from "../../agents/bootstrap-budget.js";
export { getCliSessionId, runCliAgent } from "../../agents/cli-runner.runtime.js";
export { resolveFastModeState } from "../../agents/fast-mode.js";
export { resolveNestedAgentLane } from "../../agents/lanes.js";
export { LiveSessionModelSwitchError } from "../../agents/live-model-switch.js";
export { runWithModelFallback } from "../../agents/model-fallback.js";
export { isCliProvider } from "../../agents/model-selection.js";
export { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
export {
countActiveDescendantRuns,
listDescendantRunsForRequester,
} from "../../agents/subagent-registry.js";
export { normalizeVerboseLevel } from "../../auto-reply/thinking.js";
export { resolveSessionTranscriptPath } from "../../config/sessions.js";
export { registerAgentRunContext } from "../../infra/agent-events.js";
export { logWarn } from "../../logger.js";

View File

@@ -0,0 +1,22 @@
import type { OpenClawConfig } from "../../config/config.js";
import type { CronJob } from "../types.js";
import { resolveEffectiveModelFallbacks } from "./run-execution.runtime.js";
export function resolveCronFallbacksOverride(params: {
cfg: OpenClawConfig;
job: CronJob;
agentId: string;
}): string[] | undefined {
const payload = params.job.payload.kind === "agentTurn" ? params.job.payload : undefined;
const payloadFallbacks = Array.isArray(payload?.fallbacks) ? payload.fallbacks : undefined;
const hasCronPayloadModelOverride =
typeof payload?.model === "string" && payload.model.trim().length > 0;
return (
payloadFallbacks ??
resolveEffectiveModelFallbacks({
cfg: params.cfg,
agentId: params.agentId,
hasSessionModelOverride: hasCronPayloadModelOverride,
})
);
}

View File

@@ -0,0 +1,96 @@
import type { LiveSessionModelSelection } from "../../agents/live-model-switch.js";
import type { SkillSnapshot } from "../../agents/skills.js";
import type { SessionEntry } from "../../config/sessions.js";
import type { resolveCronSession } from "./session.js";
type MutableSessionStore = Record<string, SessionEntry>;
export type MutableCronSessionEntry = SessionEntry;
export type MutableCronSession = ReturnType<typeof resolveCronSession> & {
store: MutableSessionStore;
sessionEntry: MutableCronSessionEntry;
};
export type CronLiveSelection = LiveSessionModelSelection;
type UpdateSessionStore = (
storePath: string,
update: (store: MutableSessionStore) => void,
) => Promise<void>;
export type PersistCronSessionEntry = () => Promise<void>;
export function createPersistCronSessionEntry(params: {
isFastTestEnv: boolean;
cronSession: MutableCronSession;
agentSessionKey: string;
runSessionKey: string;
updateSessionStore: UpdateSessionStore;
}): PersistCronSessionEntry {
return async () => {
if (params.isFastTestEnv) {
return;
}
params.cronSession.store[params.agentSessionKey] = params.cronSession.sessionEntry;
if (params.runSessionKey !== params.agentSessionKey) {
params.cronSession.store[params.runSessionKey] = params.cronSession.sessionEntry;
}
await params.updateSessionStore(params.cronSession.storePath, (store) => {
store[params.agentSessionKey] = params.cronSession.sessionEntry;
if (params.runSessionKey !== params.agentSessionKey) {
store[params.runSessionKey] = params.cronSession.sessionEntry;
}
});
};
}
export async function persistCronSkillsSnapshotIfChanged(params: {
isFastTestEnv: boolean;
cronSession: MutableCronSession;
skillsSnapshot: SkillSnapshot;
nowMs: number;
persistSessionEntry: PersistCronSessionEntry;
}) {
if (
params.isFastTestEnv ||
params.skillsSnapshot === params.cronSession.sessionEntry.skillsSnapshot
) {
return;
}
params.cronSession.sessionEntry = {
...params.cronSession.sessionEntry,
updatedAt: params.nowMs,
skillsSnapshot: params.skillsSnapshot,
};
await params.persistSessionEntry();
}
export function markCronSessionPreRun(params: {
entry: MutableCronSessionEntry;
provider: string;
model: string;
}) {
params.entry.modelProvider = params.provider;
params.entry.model = params.model;
params.entry.systemSent = true;
}
export function syncCronSessionLiveSelection(params: {
entry: MutableCronSessionEntry;
liveSelection: CronLiveSelection;
}) {
params.entry.modelProvider = params.liveSelection.provider;
params.entry.model = params.liveSelection.model;
if (params.liveSelection.authProfileId) {
params.entry.authProfileOverride = params.liveSelection.authProfileId;
params.entry.authProfileOverrideSource = params.liveSelection.authProfileIdSource;
if (params.liveSelection.authProfileIdSource === "auto") {
params.entry.authProfileOverrideCompactionCount = params.entry.compactionCount ?? 0;
} else {
delete params.entry.authProfileOverrideCompactionCount;
}
return;
}
delete params.entry.authProfileOverride;
delete params.entry.authProfileOverrideSource;
delete params.entry.authProfileOverrideCompactionCount;
}

View File

@@ -1,24 +1,17 @@
export {
resolveAgentConfig,
resolveAgentDir,
resolveEffectiveModelFallbacks,
resolveAgentModelFallbacksOverride,
resolveAgentWorkspaceDir,
resolveDefaultAgentId,
resolveAgentSkillsFilter,
} from "../../agents/agent-scope.js";
export { resolveSessionAuthProfileOverride } from "../../agents/auth-profiles/session-override.js";
export { resolveBootstrapWarningSignaturesSeen } from "../../agents/bootstrap-budget.js";
export { runCliAgent } from "../../agents/cli-runner.js";
export { getCliSessionId, setCliSessionId } from "../../agents/cli-session.js";
export { setCliSessionId } from "../../agents/cli-session.js";
export { lookupContextTokens } from "../../agents/context.js";
export { resolveCronStyleNow } from "../../agents/current-time.js";
export { DEFAULT_CONTEXT_TOKENS, DEFAULT_MODEL, DEFAULT_PROVIDER } from "../../agents/defaults.js";
export { resolveFastModeState } from "../../agents/fast-mode.js";
export { resolveNestedAgentLane } from "../../agents/lanes.js";
export { LiveSessionModelSwitchError } from "../../agents/live-model-switch.js";
export { loadModelCatalog } from "../../agents/model-catalog.js";
export { runWithModelFallback } from "../../agents/model-fallback.js";
export {
getModelRefStatus,
isCliProvider,
@@ -28,30 +21,19 @@ export {
resolveHooksGmailModel,
resolveThinkingDefault,
} from "../../agents/model-selection.js";
export { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
export { buildWorkspaceSkillSnapshot } from "../../agents/skills.js";
export { getSkillsSnapshotVersion } from "../../agents/skills/refresh.js";
export {
countActiveDescendantRuns,
listDescendantRunsForRequester,
} from "../../agents/subagent-registry.js";
export { runSubagentAnnounceFlow } from "../../agents/subagent-announce.js";
export { resolveAgentTimeoutMs } from "../../agents/timeout.js";
export { deriveSessionTotalTokens, hasNonzeroUsage } from "../../agents/usage.js";
export { DEFAULT_IDENTITY_FILENAME, ensureAgentWorkspace } from "../../agents/workspace.js";
export {
normalizeThinkLevel,
normalizeVerboseLevel,
supportsXHighThinking,
} from "../../auto-reply/thinking.js";
export { normalizeThinkLevel, supportsXHighThinking } from "../../auto-reply/thinking.js";
export { createOutboundSendDeps } from "../../cli/outbound-send-deps.js";
export {
resolveAgentMainSessionKey,
resolveSessionTranscriptPath,
setSessionRuntimeModel,
updateSessionStore,
} from "../../config/sessions.js";
export { registerAgentRunContext } from "../../infra/agent-events.js";
export { deliverOutboundPayloads } from "../../infra/outbound/deliver.js";
export { getRemoteSkillEligibility } from "../../infra/skills-remote.js";
export { logWarn } from "../../logger.js";