Skip to content

Commit 35176f3

Browse files
committed
perf(cron): isolate runtime-heavy seams
1 parent df27091 commit 35176f3

6 files changed

Lines changed: 50 additions & 19 deletions

File tree

src/cron/isolated-agent/model-selection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
resolveAllowedModelRef,
1010
resolveConfiguredModelRef,
1111
resolveHooksGmailModel,
12-
} from "./run.runtime.js";
12+
} from "./run-model-selection.runtime.js";
1313

1414
type CronSessionModelOverrides = {
1515
modelOverride?: string;

src/cron/isolated-agent/run-execution.runtime.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ export { LiveSessionModelSwitchError } from "../../agents/live-model-switch.js";
66
export { runWithModelFallback } from "../../agents/model-fallback.js";
77
export { isCliProvider } from "../../agents/model-selection.js";
88
export { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
9-
export {
10-
countActiveDescendantRuns,
11-
listDescendantRunsForRequester,
12-
} from "../../agents/subagent-registry.js";
139
export { normalizeVerboseLevel } from "../../auto-reply/thinking.js";
1410
export { resolveSessionTranscriptPath } from "../../config/sessions/paths.js";
1511
export { registerAgentRunContext } from "../../infra/agent-events.js";

src/cron/isolated-agent/run-executor.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ import type { OpenClawConfig } from "../../config/types.openclaw.js";
55
import type { CronJob } from "../types.js";
66
import { resolveCronPayloadOutcome } from "./helpers.js";
77
import {
8-
countActiveDescendantRuns,
98
getCliSessionId,
109
isCliProvider,
11-
listDescendantRunsForRequester,
1210
LiveSessionModelSwitchError,
1311
logWarn,
1412
normalizeVerboseLevel,
@@ -32,6 +30,14 @@ import { isLikelyInterimCronMessage } from "./subagent-followup-hints.js";
3230

3331
type AgentTurnPayload = Extract<CronJob["payload"], { kind: "agentTurn" }> | null;
3432
type CronPromptRunResult = Awaited<ReturnType<typeof runCliAgent>>;
33+
type CronSubagentRegistryRuntime = typeof import("./run-subagent-registry.runtime.js");
34+
35+
let cronSubagentRegistryRuntimePromise: Promise<CronSubagentRegistryRuntime> | undefined;
36+
37+
async function loadCronSubagentRegistryRuntime() {
38+
cronSubagentRegistryRuntimePromise ??= import("./run-subagent-registry.runtime.js");
39+
return await cronSubagentRegistryRuntimePromise;
40+
}
3541

3642
export type CronExecutionResult = {
3743
runResult: CronPromptRunResult;
@@ -321,15 +327,22 @@ export async function executeCronRun(params: {
321327
!runResult.didSendViaMessagingTool &&
322328
!interimPayloadHasStructuredContent &&
323329
!interimPayloads.some((payload) => payload?.isError === true) &&
324-
!listDescendantRunsForRequester(params.agentSessionKey).some((entry) => {
330+
isLikelyInterimCronMessage(interimText);
331+
332+
let hasFreshDescendants = false;
333+
let hasActiveDescendants = false;
334+
if (shouldRetryInterimAck) {
335+
const { countActiveDescendantRuns, listDescendantRunsForRequester } =
336+
await loadCronSubagentRegistryRuntime();
337+
hasFreshDescendants = listDescendantRunsForRequester(params.agentSessionKey).some((entry) => {
325338
const descendantStartedAt =
326339
typeof entry.startedAt === "number" ? entry.startedAt : entry.createdAt;
327340
return typeof descendantStartedAt === "number" && descendantStartedAt >= runStartedAt;
328-
}) &&
329-
countActiveDescendantRuns(params.agentSessionKey) === 0 &&
330-
isLikelyInterimCronMessage(interimText);
341+
});
342+
hasActiveDescendants = countActiveDescendantRuns(params.agentSessionKey) > 0;
343+
}
331344

332-
if (shouldRetryInterimAck) {
345+
if (shouldRetryInterimAck && !hasFreshDescendants && !hasActiveDescendants) {
333346
const continuationPrompt = [
334347
"Your previous response was only an acknowledgement and did not complete this cron task.",
335348
"Complete the original task now.",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../../agents/defaults.js";
2+
export { loadModelCatalog } from "../../agents/model-catalog.js";
3+
export {
4+
getModelRefStatus,
5+
normalizeModelSelection,
6+
resolveAllowedModelRef,
7+
resolveConfiguredModelRef,
8+
resolveHooksGmailModel,
9+
} from "../../agents/model-selection.js";
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export {
2+
countActiveDescendantRuns,
3+
listDescendantRunsForRequester,
4+
} from "../../agents/subagent-registry.js";

src/cron/isolated-agent/run.test-harness.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,8 @@ vi.mock("./run.runtime.js", () => ({
101101
lookupContextTokens: lookupContextTokensMock,
102102
resolveCronStyleNow: resolveCronStyleNowMock,
103103
DEFAULT_CONTEXT_TOKENS: 128000,
104-
DEFAULT_MODEL: "gpt-4",
105-
DEFAULT_PROVIDER: "openai",
106104
loadModelCatalog: loadModelCatalogMock,
107-
getModelRefStatus: getModelRefStatusMock,
108105
isCliProvider: isCliProviderMock,
109-
normalizeModelSelection: normalizeModelSelectionForTest,
110-
resolveAllowedModelRef: resolveAllowedModelRefMock,
111-
resolveConfiguredModelRef: resolveConfiguredModelRefMock,
112-
resolveHooksGmailModel: resolveHooksGmailModelMock,
113106
resolveThinkingDefault: resolveThinkingDefaultMock,
114107
buildWorkspaceSkillSnapshot: buildWorkspaceSkillSnapshotMock,
115108
getSkillsSnapshotVersion: getSkillsSnapshotVersionMock,
@@ -133,6 +126,17 @@ vi.mock("./run.runtime.js", () => ({
133126
getRemoteSkillEligibility: getRemoteSkillEligibilityMock,
134127
}));
135128

129+
vi.mock("./run-model-selection.runtime.js", () => ({
130+
DEFAULT_MODEL: "gpt-4",
131+
DEFAULT_PROVIDER: "openai",
132+
loadModelCatalog: loadModelCatalogMock,
133+
getModelRefStatus: getModelRefStatusMock,
134+
normalizeModelSelection: normalizeModelSelectionForTest,
135+
resolveAllowedModelRef: resolveAllowedModelRefMock,
136+
resolveConfiguredModelRef: resolveConfiguredModelRefMock,
137+
resolveHooksGmailModel: resolveHooksGmailModelMock,
138+
}));
139+
136140
vi.mock("./run-execution.runtime.js", () => ({
137141
resolveEffectiveModelFallbacks: resolveEffectiveModelFallbacksMock,
138142
resolveBootstrapWarningSignaturesSeen: resolveBootstrapWarningSignaturesSeenMock,
@@ -156,6 +160,11 @@ vi.mock("./run-auth-profile.runtime.js", () => ({
156160
resolveSessionAuthProfileOverride: resolveSessionAuthProfileOverrideMock,
157161
}));
158162

163+
vi.mock("./run-subagent-registry.runtime.js", () => ({
164+
countActiveDescendantRuns: countActiveDescendantRunsMock,
165+
listDescendantRunsForRequester: listDescendantRunsForRequesterMock,
166+
}));
167+
159168
vi.mock("../../agents/cli-runner.runtime.js", () => ({
160169
setCliSessionId: vi.fn(),
161170
}));

0 commit comments

Comments
 (0)