mirror of https://github.com/openclaw/openclaw.git
refactor: trim cron session startup imports
This commit is contained in:
parent
88b1c00b39
commit
fc8ab82aab
|
|
@ -0,0 +1,22 @@
|
|||
export type LiveSessionModelSelection = {
|
||||
provider: string;
|
||||
model: string;
|
||||
authProfileId?: string;
|
||||
authProfileIdSource?: "auto" | "user";
|
||||
};
|
||||
|
||||
export class LiveSessionModelSwitchError extends Error {
|
||||
provider: string;
|
||||
model: string;
|
||||
authProfileId?: string;
|
||||
authProfileIdSource?: "auto" | "user";
|
||||
|
||||
constructor(selection: LiveSessionModelSelection) {
|
||||
super(`Live session model switch requested: ${selection.provider}/${selection.model}`);
|
||||
this.name = "LiveSessionModelSwitchError";
|
||||
this.provider = selection.provider;
|
||||
this.model = selection.model;
|
||||
this.authProfileId = selection.authProfileId;
|
||||
this.authProfileIdSource = selection.authProfileIdSource;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,7 @@
|
|||
import { loadSessionStore, resolveStorePath, type SessionEntry } from "../config/sessions.js";
|
||||
import { resolveStorePath } from "../config/sessions/paths.js";
|
||||
import { loadSessionStore } from "../config/sessions/store.js";
|
||||
import type { SessionEntry } from "../config/sessions/types.js";
|
||||
import { LiveSessionModelSwitchError } from "./live-model-switch-error.js";
|
||||
import { resolveDefaultModelForAgent, resolvePersistedModelRef } from "./model-selection.js";
|
||||
import {
|
||||
consumeEmbeddedRunModelSwitch,
|
||||
|
|
@ -6,25 +9,9 @@ import {
|
|||
type EmbeddedRunModelSwitchRequest,
|
||||
} from "./pi-embedded-runner/runs.js";
|
||||
import { abortEmbeddedPiRun } from "./pi-embedded.js";
|
||||
|
||||
export { LiveSessionModelSwitchError } from "./live-model-switch-error.js";
|
||||
export type LiveSessionModelSelection = EmbeddedRunModelSwitchRequest;
|
||||
|
||||
export class LiveSessionModelSwitchError extends Error {
|
||||
provider: string;
|
||||
model: string;
|
||||
authProfileId?: string;
|
||||
authProfileIdSource?: "auto" | "user";
|
||||
|
||||
constructor(selection: LiveSessionModelSelection) {
|
||||
super(`Live session model switch requested: ${selection.provider}/${selection.model}`);
|
||||
this.name = "LiveSessionModelSwitchError";
|
||||
this.provider = selection.provider;
|
||||
this.model = selection.model;
|
||||
this.authProfileId = selection.authProfileId;
|
||||
this.authProfileIdSource = selection.authProfileIdSource;
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveLiveSessionModelSelection(params: {
|
||||
cfg?: { session?: { store?: string } } | undefined;
|
||||
sessionKey?: string;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import type { AuthProfileStore } from "./auth-profiles.js";
|
|||
import { saveAuthProfileStore } from "./auth-profiles.js";
|
||||
import { AUTH_STORE_VERSION } from "./auth-profiles/constants.js";
|
||||
import { isAnthropicBillingError } from "./live-auth-keys.js";
|
||||
import { LiveSessionModelSwitchError } from "./live-model-switch.js";
|
||||
import { LiveSessionModelSwitchError } from "./live-model-switch-error.js";
|
||||
import { runWithImageModelFallback, runWithModelFallback } from "./model-fallback.js";
|
||||
import { makeModelFallbackCfg } from "./test-helpers/model-fallback-config-fixture.js";
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import {
|
|||
shouldPreserveTransientCooldownProbeSlot,
|
||||
shouldUseTransientCooldownProbeSlot,
|
||||
} from "./failover-policy.js";
|
||||
import { LiveSessionModelSwitchError } from "./live-model-switch.js";
|
||||
import { LiveSessionModelSwitchError } from "./live-model-switch-error.js";
|
||||
import { logModelFallbackDecision } from "./model-fallback-observation.js";
|
||||
import type { FallbackAttempt, ModelCandidate } from "./model-fallback.types.js";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ import {
|
|||
FailoverError,
|
||||
resolveFailoverStatus,
|
||||
} from "../failover-error.js";
|
||||
import { LiveSessionModelSwitchError } from "../live-model-switch-error.js";
|
||||
import {
|
||||
hasDifferentLiveSessionModelSelection,
|
||||
LiveSessionModelSwitchError,
|
||||
consumeLiveSessionModelSwitch,
|
||||
} from "../live-model-switch.js";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { LiveSessionModelSwitchError } from "../../agents/live-model-switch.js";
|
||||
import { LiveSessionModelSwitchError } from "../../agents/live-model-switch-error.js";
|
||||
import type { TemplateContext } from "../templating.js";
|
||||
import type { GetReplyOptions } from "../types.js";
|
||||
import { MAX_LIVE_SWITCH_RETRIES } from "./agent-runner-execution.js";
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
import { resolveBootstrapWarningSignaturesSeen } from "../../agents/bootstrap-budget.js";
|
||||
import { runCliAgent } from "../../agents/cli-runner.js";
|
||||
import { getCliSessionBinding } from "../../agents/cli-session.js";
|
||||
import { LiveSessionModelSwitchError } from "../../agents/live-model-switch.js";
|
||||
import { LiveSessionModelSwitchError } from "../../agents/live-model-switch-error.js";
|
||||
import { runWithModelFallback, isFallbackSummaryError } from "../../agents/model-fallback.js";
|
||||
import { isCliProvider } from "../../agents/model-selection.js";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { LiveSessionModelSwitchError } from "../../agents/live-model-switch.js";
|
||||
import { LiveSessionModelSwitchError } from "../../agents/live-model-switch-error.js";
|
||||
import {
|
||||
clearFastTestEnv,
|
||||
loadRunCronIsolatedAgentTurn,
|
||||
|
|
|
|||
|
|
@ -8,8 +8,11 @@ import {
|
|||
buildWorkspaceSkillSnapshotMock,
|
||||
getCliSessionIdMock,
|
||||
isCliProviderMock,
|
||||
lookupCachedContextTokensMock,
|
||||
loadRunCronIsolatedAgentTurn,
|
||||
logWarnMock,
|
||||
makeCronSession,
|
||||
makeCronSessionEntry,
|
||||
resolveAgentConfigMock,
|
||||
resolveAgentSkillsFilterMock,
|
||||
resolveAllowedModelRefMock,
|
||||
|
|
@ -320,4 +323,36 @@ describe("runCronIsolatedAgentTurn — skill filter", () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("context token fallback", () => {
|
||||
it("preserves existing session contextTokens when no cached model window is loaded", async () => {
|
||||
const session = makeCronSession({
|
||||
sessionEntry: makeCronSessionEntry({
|
||||
contextTokens: 222_000,
|
||||
}),
|
||||
});
|
||||
resolveCronSessionMock.mockReturnValue(session);
|
||||
lookupCachedContextTokensMock.mockReturnValue(undefined);
|
||||
|
||||
const result = await runSkillFilterCase();
|
||||
|
||||
expect(result.status).toBe("ok");
|
||||
expect(session.sessionEntry.contextTokens).toBe(222_000);
|
||||
});
|
||||
|
||||
it("prefers cached model contextTokens over the previous session value", async () => {
|
||||
const session = makeCronSession({
|
||||
sessionEntry: makeCronSessionEntry({
|
||||
contextTokens: 222_000,
|
||||
}),
|
||||
});
|
||||
resolveCronSessionMock.mockReturnValue(session);
|
||||
lookupCachedContextTokensMock.mockReturnValue(512_000);
|
||||
|
||||
const result = await runSkillFilterCase();
|
||||
|
||||
expect(result.status).toBe("ok");
|
||||
expect(session.sessionEntry.contextTokens).toBe(512_000);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { vi, type Mock } from "vitest";
|
||||
import { LiveSessionModelSwitchError } from "../../agents/live-model-switch.js";
|
||||
|
||||
type CronSessionEntry = {
|
||||
sessionId: string;
|
||||
|
|
@ -24,6 +23,18 @@ function createMock(): Mock {
|
|||
return vi.fn();
|
||||
}
|
||||
|
||||
function normalizeModelSelectionForTest(value: unknown): string | undefined {
|
||||
if (typeof value === "string") {
|
||||
const trimmed = value.trim();
|
||||
return trimmed || undefined;
|
||||
}
|
||||
if (!value || typeof value !== "object") {
|
||||
return undefined;
|
||||
}
|
||||
const primary = (value as { primary?: unknown }).primary;
|
||||
return typeof primary === "string" && primary.trim() ? primary.trim() : undefined;
|
||||
}
|
||||
|
||||
export const buildWorkspaceSkillSnapshotMock = createMock();
|
||||
export const resolveAgentConfigMock = createMock();
|
||||
export const resolveAgentModelFallbacksOverrideMock = createMock();
|
||||
|
|
@ -37,6 +48,7 @@ export const resolveThinkingDefaultMock = createMock();
|
|||
export const runWithModelFallbackMock = createMock();
|
||||
export const runEmbeddedPiAgentMock = createMock();
|
||||
export const runCliAgentMock = createMock();
|
||||
export const lookupCachedContextTokensMock = createMock();
|
||||
export const getCliSessionIdMock = createMock();
|
||||
export const updateSessionStoreMock = createMock();
|
||||
export const resolveCronSessionMock = createMock();
|
||||
|
|
@ -48,39 +60,94 @@ export const resolveCronPayloadOutcomeMock = createMock();
|
|||
export const resolveCronDeliveryPlanMock = createMock();
|
||||
export const resolveDeliveryTargetMock = createMock();
|
||||
export const resolveSessionAuthProfileOverrideMock = createMock();
|
||||
const resolveAgentDirMock = vi.fn().mockReturnValue("/tmp/agent-dir");
|
||||
const resolveAgentWorkspaceDirMock = vi.fn().mockReturnValue("/tmp/workspace");
|
||||
const resolveDefaultAgentIdMock = vi.fn().mockReturnValue("default");
|
||||
const getSkillsSnapshotVersionMock = vi.fn().mockReturnValue(42);
|
||||
const ensureAgentWorkspaceMock = vi.fn().mockResolvedValue({ dir: "/tmp/workspace" });
|
||||
const loadModelCatalogMock = vi.fn().mockResolvedValue({ models: [] });
|
||||
const normalizeModelSelectionMock = vi.fn((value: unknown) =>
|
||||
typeof value === "string" ? value.trim() || undefined : undefined,
|
||||
);
|
||||
const lookupContextTokensMock = vi.fn().mockReturnValue(128000);
|
||||
const resolveCronStyleNowMock = vi.fn().mockReturnValue({
|
||||
formattedTime: "2026-02-10 12:00",
|
||||
timeLine: "Current time: 2026-02-10 12:00 UTC",
|
||||
|
||||
vi.mock("../../agents/agent-scope.js", () => ({
|
||||
resolveAgentConfig: resolveAgentConfigMock,
|
||||
resolveAgentDir: vi.fn().mockReturnValue("/tmp/agent-dir"),
|
||||
resolveAgentModelFallbacksOverride: resolveAgentModelFallbacksOverrideMock,
|
||||
resolveAgentWorkspaceDir: vi.fn().mockReturnValue("/tmp/workspace"),
|
||||
resolveDefaultAgentId: vi.fn().mockReturnValue("default"),
|
||||
resolveAgentSkillsFilter: resolveAgentSkillsFilterMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/skills.js", () => ({
|
||||
buildWorkspaceSkillSnapshot: buildWorkspaceSkillSnapshotMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/skills/refresh.js", () => ({
|
||||
getSkillsSnapshotVersion: vi.fn().mockReturnValue(42),
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/workspace.js", () => ({
|
||||
DEFAULT_IDENTITY_FILENAME: "IDENTITY.md",
|
||||
ensureAgentWorkspace: vi.fn().mockResolvedValue({ dir: "/tmp/workspace" }),
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/model-catalog.js", () => ({
|
||||
loadModelCatalog: vi.fn().mockResolvedValue({ models: [] }),
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/model-selection.js", () => ({
|
||||
getModelRefStatus: getModelRefStatusMock,
|
||||
isCliProvider: isCliProviderMock,
|
||||
normalizeModelSelection: normalizeModelSelectionForTest,
|
||||
resolveAllowedModelRef: resolveAllowedModelRefMock,
|
||||
resolveConfiguredModelRef: resolveConfiguredModelRefMock,
|
||||
resolveHooksGmailModel: resolveHooksGmailModelMock,
|
||||
resolveThinkingDefault: resolveThinkingDefaultMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/model-fallback.js", () => ({
|
||||
runWithModelFallback: runWithModelFallbackMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/auth-profiles/session-override.js", () => ({
|
||||
resolveSessionAuthProfileOverride: resolveSessionAuthProfileOverrideMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/live-model-switch-error.js", async (importOriginal) => {
|
||||
return await importOriginal<typeof import("../../agents/live-model-switch-error.js")>();
|
||||
});
|
||||
const resolveAgentTimeoutMsMock = vi.fn().mockReturnValue(60_000);
|
||||
const deriveSessionTotalTokensMock = vi.fn().mockReturnValue(30);
|
||||
const hasNonzeroUsageMock = vi.fn().mockReturnValue(false);
|
||||
const normalizeThinkLevelMock = vi.fn().mockReturnValue(undefined);
|
||||
const normalizeVerboseLevelMock = vi.fn().mockReturnValue("off");
|
||||
const supportsXHighThinkingMock = vi.fn().mockReturnValue(false);
|
||||
const resolveSessionTranscriptPathMock = vi.fn().mockReturnValue("/tmp/transcript.jsonl");
|
||||
const setSessionRuntimeModelMock = vi.fn();
|
||||
const registerAgentRunContextMock = vi.fn();
|
||||
const buildSafeExternalPromptMock = vi.fn().mockReturnValue("safe prompt");
|
||||
const detectSuspiciousPatternsMock = vi.fn().mockReturnValue([]);
|
||||
const isExternalHookSessionMock = vi.fn().mockReturnValue(false);
|
||||
const mapHookExternalContentSourceMock = vi.fn().mockReturnValue("unknown");
|
||||
const resolveHookExternalContentSourceMock = vi.fn().mockReturnValue(undefined);
|
||||
const estimateUsageCostMock = vi.fn().mockReturnValue(undefined);
|
||||
const resolveModelCostConfigMock = vi.fn().mockReturnValue(undefined);
|
||||
const resolveBootstrapWarningSignaturesSeenMock = vi.fn().mockReturnValue([]);
|
||||
const resolveFastModeStateMock = vi.fn().mockReturnValue({ enabled: false });
|
||||
const resolveNestedAgentLaneMock = vi.fn((lane: string | undefined) => lane);
|
||||
|
||||
vi.mock("../../agents/pi-embedded.js", () => ({
|
||||
runEmbeddedPiAgent: runEmbeddedPiAgentMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/context-cache.js", () => ({
|
||||
lookupCachedContextTokens: lookupCachedContextTokensMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/date-time.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../agents/date-time.js")>();
|
||||
return {
|
||||
...actual,
|
||||
formatUserTime: vi.fn().mockReturnValue("2026-02-10 12:00"),
|
||||
resolveUserTimeFormat: vi.fn().mockReturnValue("24h"),
|
||||
resolveUserTimezone: vi.fn().mockReturnValue("UTC"),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../agents/timeout.js", () => ({
|
||||
resolveAgentTimeoutMs: vi.fn().mockReturnValue(60_000),
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/usage.js", () => ({
|
||||
deriveSessionTotalTokens: vi.fn().mockReturnValue(30),
|
||||
hasNonzeroUsage: vi.fn().mockReturnValue(false),
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/subagent-announce.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../agents/subagent-announce.js")>();
|
||||
return {
|
||||
...actual,
|
||||
runSubagentAnnounceFlow: vi.fn().mockResolvedValue(true),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../agents/subagent-registry.js", () => ({
|
||||
countActiveDescendantRuns: countActiveDescendantRunsMock,
|
||||
listDescendantRunsForRequester: listDescendantRunsForRequesterMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/cli-runner.runtime.js", () => ({
|
||||
runCliAgent: runCliAgentMock,
|
||||
|
|
@ -88,60 +155,96 @@ vi.mock("../../agents/cli-runner.runtime.js", () => ({
|
|||
setCliSessionId: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("./run.runtime.js", () => ({
|
||||
DEFAULT_CONTEXT_TOKENS: 128000,
|
||||
DEFAULT_MODEL: "gpt-4",
|
||||
DEFAULT_PROVIDER: "openai",
|
||||
LiveSessionModelSwitchError,
|
||||
buildSafeExternalPrompt: buildSafeExternalPromptMock,
|
||||
buildWorkspaceSkillSnapshot: buildWorkspaceSkillSnapshotMock,
|
||||
countActiveDescendantRuns: countActiveDescendantRunsMock,
|
||||
deriveSessionTotalTokens: deriveSessionTotalTokensMock,
|
||||
detectSuspiciousPatterns: detectSuspiciousPatternsMock,
|
||||
ensureAgentWorkspace: ensureAgentWorkspaceMock,
|
||||
estimateUsageCost: estimateUsageCostMock,
|
||||
listDescendantRunsForRequester: listDescendantRunsForRequesterMock,
|
||||
getModelRefStatus: getModelRefStatusMock,
|
||||
getRemoteSkillEligibility: vi.fn().mockReturnValue({}),
|
||||
getSkillsSnapshotVersion: getSkillsSnapshotVersionMock,
|
||||
hasNonzeroUsage: hasNonzeroUsageMock,
|
||||
isCliProvider: isCliProviderMock,
|
||||
isExternalHookSession: isExternalHookSessionMock,
|
||||
loadModelCatalog: loadModelCatalogMock,
|
||||
logWarn: (...args: unknown[]) => logWarnMock(...args),
|
||||
lookupContextTokens: lookupContextTokensMock,
|
||||
mapHookExternalContentSource: mapHookExternalContentSourceMock,
|
||||
normalizeAgentId: vi.fn((id: string) => id),
|
||||
normalizeModelSelection: normalizeModelSelectionMock,
|
||||
normalizeThinkLevel: normalizeThinkLevelMock,
|
||||
normalizeVerboseLevel: normalizeVerboseLevelMock,
|
||||
registerAgentRunContext: registerAgentRunContextMock,
|
||||
resolveAgentConfig: resolveAgentConfigMock,
|
||||
resolveAgentDir: resolveAgentDirMock,
|
||||
resolveAgentModelFallbacksOverride: resolveAgentModelFallbacksOverrideMock,
|
||||
resolveAgentSkillsFilter: resolveAgentSkillsFilterMock,
|
||||
resolveAgentTimeoutMs: resolveAgentTimeoutMsMock,
|
||||
resolveAgentWorkspaceDir: resolveAgentWorkspaceDirMock,
|
||||
resolveAllowedModelRef: resolveAllowedModelRefMock,
|
||||
resolveBootstrapWarningSignaturesSeen: resolveBootstrapWarningSignaturesSeenMock,
|
||||
resolveConfiguredModelRef: resolveConfiguredModelRefMock,
|
||||
resolveCronStyleNow: resolveCronStyleNowMock,
|
||||
resolveDefaultAgentId: resolveDefaultAgentIdMock,
|
||||
resolveFastModeState: resolveFastModeStateMock,
|
||||
resolveHookExternalContentSource: resolveHookExternalContentSourceMock,
|
||||
resolveHooksGmailModel: resolveHooksGmailModelMock,
|
||||
resolveModelCostConfig: resolveModelCostConfigMock,
|
||||
resolveNestedAgentLane: resolveNestedAgentLaneMock,
|
||||
resolveSessionAuthProfileOverride: resolveSessionAuthProfileOverrideMock,
|
||||
resolveSessionTranscriptPath: resolveSessionTranscriptPathMock,
|
||||
resolveThinkingDefault: resolveThinkingDefaultMock,
|
||||
runEmbeddedPiAgent: runEmbeddedPiAgentMock,
|
||||
runWithModelFallback: runWithModelFallbackMock,
|
||||
setSessionRuntimeModel: setSessionRuntimeModelMock,
|
||||
supportsXHighThinking: supportsXHighThinkingMock,
|
||||
vi.mock("../../auto-reply/thinking.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../auto-reply/thinking.js")>();
|
||||
return {
|
||||
...actual,
|
||||
normalizeThinkLevel: vi.fn().mockReturnValue(undefined),
|
||||
normalizeVerboseLevel: vi.fn().mockReturnValue("off"),
|
||||
supportsXHighThinking: vi.fn().mockReturnValue(false),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../cli/outbound-send-deps.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../cli/outbound-send-deps.js")>();
|
||||
return {
|
||||
...actual,
|
||||
createOutboundSendDeps: vi.fn().mockReturnValue({}),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../config/sessions/paths.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../config/sessions/paths.js")>();
|
||||
return {
|
||||
...actual,
|
||||
resolveSessionTranscriptPath: vi.fn().mockReturnValue("/tmp/transcript.jsonl"),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../config/sessions/store.runtime.js", () => ({
|
||||
updateSessionStore: updateSessionStoreMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../config/sessions/types.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../config/sessions/types.js")>();
|
||||
return {
|
||||
...actual,
|
||||
setSessionRuntimeModel: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../routing/session-key.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../routing/session-key.js")>();
|
||||
return {
|
||||
...actual,
|
||||
buildAgentMainSessionKey: vi.fn().mockReturnValue("agent:default:cron:test"),
|
||||
normalizeAgentId: vi.fn((id: string) => id),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../infra/agent-events.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../infra/agent-events.js")>();
|
||||
return {
|
||||
...actual,
|
||||
registerAgentRunContext: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../infra/outbound/deliver.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../infra/outbound/deliver.js")>();
|
||||
return {
|
||||
...actual,
|
||||
deliverOutboundPayloads: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../infra/skills-remote.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../infra/skills-remote.js")>();
|
||||
return {
|
||||
...actual,
|
||||
getRemoteSkillEligibility: vi.fn().mockReturnValue({}),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../logger.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../logger.js")>();
|
||||
return {
|
||||
...actual,
|
||||
logWarn: (...args: unknown[]) => logWarnMock(...args),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../security/external-content.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../security/external-content.js")>();
|
||||
return {
|
||||
...actual,
|
||||
buildSafeExternalPrompt: vi.fn().mockReturnValue("safe prompt"),
|
||||
detectSuspiciousPatterns: vi.fn().mockReturnValue([]),
|
||||
getHookType: vi.fn().mockReturnValue("unknown"),
|
||||
isExternalHookSession: vi.fn().mockReturnValue(false),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../delivery.js", () => ({
|
||||
resolveCronDeliveryPlan: resolveCronDeliveryPlanMock,
|
||||
}));
|
||||
|
|
@ -164,6 +267,16 @@ vi.mock("./session.js", () => ({
|
|||
resolveCronSession: resolveCronSessionMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/defaults.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../agents/defaults.js")>();
|
||||
return {
|
||||
...actual,
|
||||
DEFAULT_CONTEXT_TOKENS: 128000,
|
||||
DEFAULT_MODEL: "gpt-4",
|
||||
DEFAULT_PROVIDER: "openai",
|
||||
};
|
||||
});
|
||||
|
||||
export function makeCronSessionEntry(overrides?: Record<string, unknown>): CronSessionEntry {
|
||||
return {
|
||||
sessionId: "test-session-id",
|
||||
|
|
@ -235,6 +348,8 @@ export function resetRunCronIsolatedAgentTurnHarness(): void {
|
|||
runEmbeddedPiAgentMock.mockResolvedValue(makeDefaultEmbeddedResult());
|
||||
|
||||
runCliAgentMock.mockReset();
|
||||
lookupCachedContextTokensMock.mockReset();
|
||||
lookupCachedContextTokensMock.mockReturnValue(undefined);
|
||||
getCliSessionIdMock.mockReturnValue(undefined);
|
||||
|
||||
updateSessionStoreMock.mockReset();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,50 @@
|
|||
import {
|
||||
resolveAgentConfig,
|
||||
resolveAgentDir,
|
||||
resolveAgentModelFallbacksOverride,
|
||||
resolveAgentWorkspaceDir,
|
||||
resolveDefaultAgentId,
|
||||
} from "../../agents/agent-scope.js";
|
||||
import { resolveSessionAuthProfileOverride } from "../../agents/auth-profiles/session-override.js";
|
||||
import { resolveBootstrapWarningSignaturesSeen } from "../../agents/bootstrap-budget.js";
|
||||
import { lookupCachedContextTokens } from "../../agents/context-cache.js";
|
||||
import { resolveCronStyleNow } from "../../agents/current-time.js";
|
||||
import { DEFAULT_CONTEXT_TOKENS } from "../../agents/defaults.js";
|
||||
import { resolveFastModeState } from "../../agents/fast-mode.js";
|
||||
import { resolveNestedAgentLane } from "../../agents/lanes.js";
|
||||
import { LiveSessionModelSwitchError } from "../../agents/live-model-switch-error.js";
|
||||
import { loadModelCatalog } from "../../agents/model-catalog.js";
|
||||
import { runWithModelFallback } from "../../agents/model-fallback.js";
|
||||
import { isCliProvider, resolveThinkingDefault } from "../../agents/model-selection.js";
|
||||
import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
|
||||
import {
|
||||
countActiveDescendantRuns,
|
||||
listDescendantRunsForRequester,
|
||||
} from "../../agents/subagent-registry.js";
|
||||
import { resolveAgentTimeoutMs } from "../../agents/timeout.js";
|
||||
import { deriveSessionTotalTokens, hasNonzeroUsage } from "../../agents/usage.js";
|
||||
import { ensureAgentWorkspace } from "../../agents/workspace.js";
|
||||
import {
|
||||
normalizeThinkLevel,
|
||||
normalizeVerboseLevel,
|
||||
supportsXHighThinking,
|
||||
} from "../../auto-reply/thinking.js";
|
||||
import type { CliDeps } from "../../cli/outbound-send-deps.js";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { resolveSessionTranscriptPath } from "../../config/sessions/paths.js";
|
||||
import { updateSessionStore } from "../../config/sessions/store.runtime.js";
|
||||
import { setSessionRuntimeModel } from "../../config/sessions/types.js";
|
||||
import { registerAgentRunContext } from "../../infra/agent-events.js";
|
||||
import { logWarn } from "../../logger.js";
|
||||
import { normalizeAgentId } from "../../routing/session-key.js";
|
||||
import {
|
||||
buildSafeExternalPrompt,
|
||||
detectSuspiciousPatterns,
|
||||
mapHookExternalContentSource,
|
||||
isExternalHookSession,
|
||||
resolveHookExternalContentSource,
|
||||
} from "../../security/external-content.js";
|
||||
import { estimateUsageCost, resolveModelCostConfig } from "../../utils/usage-format.js";
|
||||
import { resolveCronDeliveryPlan } from "../delivery.js";
|
||||
import type { CronJob, CronRunOutcome, CronRunTelemetry } from "../types.js";
|
||||
import {
|
||||
|
|
@ -15,48 +60,6 @@ import {
|
|||
} from "./helpers.js";
|
||||
import { resolveCronModelSelection } from "./model-selection.js";
|
||||
import { buildCronAgentDefaultsConfig } from "./run-config.js";
|
||||
import {
|
||||
DEFAULT_CONTEXT_TOKENS,
|
||||
LiveSessionModelSwitchError,
|
||||
buildSafeExternalPrompt,
|
||||
countActiveDescendantRuns,
|
||||
deriveSessionTotalTokens,
|
||||
detectSuspiciousPatterns,
|
||||
ensureAgentWorkspace,
|
||||
estimateUsageCost,
|
||||
hasNonzeroUsage,
|
||||
isCliProvider,
|
||||
isExternalHookSession,
|
||||
listDescendantRunsForRequester,
|
||||
loadModelCatalog,
|
||||
logWarn,
|
||||
lookupContextTokens,
|
||||
mapHookExternalContentSource,
|
||||
normalizeAgentId,
|
||||
normalizeThinkLevel,
|
||||
normalizeVerboseLevel,
|
||||
registerAgentRunContext,
|
||||
resolveAgentConfig,
|
||||
resolveAgentDir,
|
||||
resolveAgentModelFallbacksOverride,
|
||||
resolveAgentTimeoutMs,
|
||||
resolveAgentWorkspaceDir,
|
||||
resolveBootstrapWarningSignaturesSeen,
|
||||
resolveCronStyleNow,
|
||||
resolveDefaultAgentId,
|
||||
resolveFastModeState,
|
||||
resolveHookExternalContentSource,
|
||||
resolveModelCostConfig,
|
||||
resolveNestedAgentLane,
|
||||
resolveSessionAuthProfileOverride,
|
||||
resolveSessionTranscriptPath,
|
||||
resolveThinkingDefault,
|
||||
runEmbeddedPiAgent,
|
||||
runWithModelFallback,
|
||||
setSessionRuntimeModel,
|
||||
supportsXHighThinking,
|
||||
updateSessionStore,
|
||||
} from "./run.runtime.js";
|
||||
import { resolveCronAgentSessionKey } from "./session-key.js";
|
||||
import { resolveCronSession } from "./session.js";
|
||||
import { resolveCronSkillsSnapshot } from "./skills-snapshot.js";
|
||||
|
|
@ -163,6 +166,10 @@ function appendCronDeliveryInstruction(params: {
|
|||
return `${params.commandBody}\n\nReturn your summary as plain text; it will be delivered automatically. If the task explicitly calls for messaging a specific external recipient, note who/where it should go instead of sending it yourself.`.trim();
|
||||
}
|
||||
|
||||
function resolvePositiveContextTokens(value: unknown): number | undefined {
|
||||
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
|
||||
}
|
||||
|
||||
async function loadCliRunnerRuntime() {
|
||||
return await import("../../agents/cli-runner.runtime.js");
|
||||
}
|
||||
|
|
@ -702,8 +709,9 @@ export async function runCronIsolatedAgentTurn(params: {
|
|||
const providerUsed =
|
||||
finalRunResult.meta?.agentMeta?.provider ?? fallbackProvider ?? liveSelection.provider;
|
||||
const contextTokens =
|
||||
agentCfg?.contextTokens ??
|
||||
lookupContextTokens(modelUsed, { allowAsyncLoad: false }) ??
|
||||
resolvePositiveContextTokens(agentCfg?.contextTokens) ??
|
||||
lookupCachedContextTokens(modelUsed) ??
|
||||
resolvePositiveContextTokens(cronSession.sessionEntry.contextTokens) ??
|
||||
DEFAULT_CONTEXT_TOKENS;
|
||||
|
||||
setSessionRuntimeModel(cronSession.sessionEntry, {
|
||||
|
|
|
|||
Loading…
Reference in New Issue