mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:20:43 +00:00
test: speed up embedded run orchestration specs
This commit is contained in:
@@ -1,185 +0,0 @@
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { AgentInternalEvent } from "../internal-events.js";
|
||||
import { makeAttemptResult } from "./run.overflow-compaction.fixture.js";
|
||||
import {
|
||||
loadRunOverflowCompactionHarness,
|
||||
mockedGetApiKeyForModel,
|
||||
mockedRunEmbeddedAttempt,
|
||||
overflowBaseRunParams,
|
||||
resetRunOverflowCompactionHarnessMocks,
|
||||
} from "./run.overflow-compaction.harness.js";
|
||||
import type { RunEmbeddedPiAgentParams } from "./run/params.js";
|
||||
|
||||
type ForwardingCase = {
|
||||
runId: string;
|
||||
params: Partial<RunEmbeddedPiAgentParams>;
|
||||
expected: Record<string, unknown>;
|
||||
};
|
||||
|
||||
let runEmbeddedPiAgent: typeof import("./run.js").runEmbeddedPiAgent;
|
||||
const internalEvents: AgentInternalEvent[] = [];
|
||||
const forwardingCase = {
|
||||
runId: "forward-attempt-params",
|
||||
params: {
|
||||
toolsAllow: ["exec", "read"],
|
||||
bootstrapContextMode: "lightweight",
|
||||
bootstrapContextRunKind: "cron",
|
||||
disableMessageTool: true,
|
||||
forceMessageTool: true,
|
||||
requireExplicitMessageTarget: true,
|
||||
internalEvents,
|
||||
},
|
||||
expected: {
|
||||
toolsAllow: ["exec", "read"],
|
||||
bootstrapContextMode: "lightweight",
|
||||
bootstrapContextRunKind: "cron",
|
||||
disableMessageTool: true,
|
||||
forceMessageTool: true,
|
||||
requireExplicitMessageTarget: true,
|
||||
internalEvents,
|
||||
},
|
||||
} satisfies ForwardingCase;
|
||||
|
||||
describe("runEmbeddedPiAgent forwards optional params to runEmbeddedAttempt", () => {
|
||||
beforeAll(async () => {
|
||||
({ runEmbeddedPiAgent } = await loadRunOverflowCompactionHarness());
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
resetRunOverflowCompactionHarnessMocks();
|
||||
});
|
||||
|
||||
it("forwards optional attempt params in one attempt call", async () => {
|
||||
mockedRunEmbeddedAttempt.mockResolvedValueOnce(makeAttemptResult({ promptError: null }));
|
||||
|
||||
await runEmbeddedPiAgent({
|
||||
...overflowBaseRunParams,
|
||||
...forwardingCase.params,
|
||||
runId: forwardingCase.runId,
|
||||
});
|
||||
|
||||
expect(mockedRunEmbeddedAttempt).toHaveBeenCalledWith(
|
||||
expect.objectContaining(forwardingCase.expected),
|
||||
);
|
||||
});
|
||||
|
||||
it("lets plugin harnesses own auth before the attempt runs", async () => {
|
||||
const { clearAgentHarnesses, registerAgentHarness } = await import("../harness/registry.js");
|
||||
const pluginRunAttempt = vi.fn(async () => makeAttemptResult({ assistantTexts: ["ok"] }));
|
||||
clearAgentHarnesses();
|
||||
registerAgentHarness({
|
||||
id: "codex",
|
||||
label: "Codex",
|
||||
supports: (ctx) =>
|
||||
ctx.provider === "codex" ? { supported: true, priority: 100 } : { supported: false },
|
||||
runAttempt: pluginRunAttempt,
|
||||
});
|
||||
mockedGetApiKeyForModel.mockRejectedValueOnce(new Error("generic auth should be skipped"));
|
||||
|
||||
try {
|
||||
await runEmbeddedPiAgent({
|
||||
...overflowBaseRunParams,
|
||||
provider: "codex",
|
||||
model: "gpt-5.4",
|
||||
config: {
|
||||
agents: {
|
||||
defaults: {
|
||||
embeddedHarness: { runtime: "codex", fallback: "none" },
|
||||
},
|
||||
},
|
||||
},
|
||||
runId: "plugin-harness-skips-generic-auth",
|
||||
});
|
||||
} finally {
|
||||
clearAgentHarnesses();
|
||||
}
|
||||
|
||||
expect(mockedGetApiKeyForModel).not.toHaveBeenCalled();
|
||||
expect(pluginRunAttempt).toHaveBeenCalledWith(expect.objectContaining({ provider: "codex" }));
|
||||
});
|
||||
|
||||
it("forwards explicit OpenAI Codex auth profiles to codex plugin harnesses", async () => {
|
||||
const { clearAgentHarnesses, registerAgentHarness } = await import("../harness/registry.js");
|
||||
const pluginRunAttempt = vi.fn(async () => makeAttemptResult({ assistantTexts: ["ok"] }));
|
||||
clearAgentHarnesses();
|
||||
registerAgentHarness({
|
||||
id: "codex",
|
||||
label: "Codex",
|
||||
supports: (ctx) =>
|
||||
ctx.provider === "codex" ? { supported: true, priority: 100 } : { supported: false },
|
||||
runAttempt: pluginRunAttempt,
|
||||
});
|
||||
mockedGetApiKeyForModel.mockRejectedValueOnce(new Error("generic auth should be skipped"));
|
||||
|
||||
try {
|
||||
await runEmbeddedPiAgent({
|
||||
...overflowBaseRunParams,
|
||||
provider: "codex",
|
||||
model: "gpt-5.4",
|
||||
config: {
|
||||
agents: {
|
||||
defaults: {
|
||||
embeddedHarness: { runtime: "codex", fallback: "none" },
|
||||
},
|
||||
},
|
||||
},
|
||||
authProfileId: "openai-codex:work",
|
||||
authProfileIdSource: "user",
|
||||
runId: "plugin-harness-forwards-openai-codex-auth",
|
||||
});
|
||||
} finally {
|
||||
clearAgentHarnesses();
|
||||
}
|
||||
|
||||
expect(mockedGetApiKeyForModel).not.toHaveBeenCalled();
|
||||
expect(pluginRunAttempt).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
provider: "codex",
|
||||
authProfileId: "openai-codex:work",
|
||||
authProfileIdSource: "user",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("forwards OpenAI Codex auth profiles when openai/* is forced through codex", async () => {
|
||||
const { clearAgentHarnesses, registerAgentHarness } = await import("../harness/registry.js");
|
||||
const pluginRunAttempt = vi.fn(async () => makeAttemptResult({ assistantTexts: ["ok"] }));
|
||||
clearAgentHarnesses();
|
||||
registerAgentHarness({
|
||||
id: "codex",
|
||||
label: "Codex",
|
||||
supports: () => ({ supported: false }),
|
||||
runAttempt: pluginRunAttempt,
|
||||
});
|
||||
mockedGetApiKeyForModel.mockRejectedValueOnce(new Error("generic auth should be skipped"));
|
||||
|
||||
try {
|
||||
await runEmbeddedPiAgent({
|
||||
...overflowBaseRunParams,
|
||||
provider: "openai",
|
||||
model: "gpt-5.4",
|
||||
config: {
|
||||
agents: {
|
||||
defaults: {
|
||||
embeddedHarness: { runtime: "codex", fallback: "none" },
|
||||
},
|
||||
},
|
||||
},
|
||||
authProfileId: "openai-codex:work",
|
||||
authProfileIdSource: "user",
|
||||
runId: "forced-codex-harness-forwards-openai-codex-auth",
|
||||
});
|
||||
} finally {
|
||||
clearAgentHarnesses();
|
||||
}
|
||||
|
||||
expect(mockedGetApiKeyForModel).not.toHaveBeenCalled();
|
||||
expect(pluginRunAttempt).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
provider: "openai",
|
||||
authProfileId: "openai-codex:work",
|
||||
authProfileIdSource: "user",
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -10,6 +10,7 @@ import type {
|
||||
} from "../../plugins/types.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
import type { FailoverReason } from "../pi-embedded-helpers/types.js";
|
||||
import type { buildEmbeddedRunPayloads } from "./run/payloads.js";
|
||||
import type { EmbeddedRunAttemptResult } from "./run/types.js";
|
||||
|
||||
type MockCompactionResult =
|
||||
@@ -72,11 +73,18 @@ export const mockedContextEngine = {
|
||||
|
||||
export const mockedContextEngineCompact = mockedContextEngine.compact;
|
||||
export const mockedCompactDirect = mockedContextEngine.compact;
|
||||
export const mockedResolveContextEngine = vi.fn(async () => mockedContextEngine);
|
||||
export const mockedBuildAgentRuntimePlan = vi.fn(() => ({}));
|
||||
export const mockedRunPostCompactionSideEffects = vi.fn(async () => {});
|
||||
export const mockedEnsureRuntimePluginsLoaded = vi.fn<(params?: unknown) => void>();
|
||||
export const mockedPrepareProviderRuntimeAuth = vi.fn(async () => undefined);
|
||||
export const mockedRunEmbeddedAttempt =
|
||||
vi.fn<(params: unknown) => Promise<EmbeddedRunAttemptResult>>();
|
||||
export const mockedBuildEmbeddedRunPayloads = vi.fn<
|
||||
(
|
||||
...args: Parameters<typeof buildEmbeddedRunPayloads>
|
||||
) => ReturnType<typeof buildEmbeddedRunPayloads>
|
||||
>(() => []);
|
||||
export const mockedRunContextEngineMaintenance = vi.fn(async () => undefined);
|
||||
export const mockedSessionLikelyHasOversizedToolResults = vi.fn(() => false);
|
||||
export const mockedResolveLiveToolResultMaxChars = vi.fn(() => 32_000);
|
||||
@@ -223,6 +231,10 @@ export function resetRunOverflowCompactionHarnessMocks(): void {
|
||||
mockedGlobalHookRunner.runAfterCompaction.mockResolvedValue(undefined);
|
||||
|
||||
mockedContextEngine.info.ownsCompaction = false;
|
||||
mockedResolveContextEngine.mockReset();
|
||||
mockedResolveContextEngine.mockResolvedValue(mockedContextEngine);
|
||||
mockedBuildAgentRuntimePlan.mockReset();
|
||||
mockedBuildAgentRuntimePlan.mockReturnValue({});
|
||||
mockedContextEngineCompact.mockReset();
|
||||
mockedContextEngineCompact.mockResolvedValue({
|
||||
ok: false,
|
||||
@@ -234,6 +246,8 @@ export function resetRunOverflowCompactionHarnessMocks(): void {
|
||||
mockedPrepareProviderRuntimeAuth.mockReset();
|
||||
mockedPrepareProviderRuntimeAuth.mockResolvedValue(undefined);
|
||||
mockedRunEmbeddedAttempt.mockReset();
|
||||
mockedBuildEmbeddedRunPayloads.mockReset();
|
||||
mockedBuildEmbeddedRunPayloads.mockReturnValue([]);
|
||||
mockedRunContextEngineMaintenance.mockReset();
|
||||
mockedRunContextEngineMaintenance.mockResolvedValue(undefined);
|
||||
mockedSessionLikelyHasOversizedToolResults.mockReset();
|
||||
@@ -361,13 +375,17 @@ export async function loadRunOverflowCompactionHarness(): Promise<{
|
||||
ensureContextEnginesInitialized: vi.fn(),
|
||||
}));
|
||||
vi.doMock("../../context-engine/registry.js", () => ({
|
||||
resolveContextEngine: vi.fn(async () => mockedContextEngine),
|
||||
resolveContextEngine: mockedResolveContextEngine,
|
||||
}));
|
||||
|
||||
vi.doMock("../runtime-plugins.js", () => ({
|
||||
ensureRuntimePluginsLoaded: mockedEnsureRuntimePluginsLoaded,
|
||||
}));
|
||||
|
||||
vi.doMock("../runtime-plan/build.js", () => ({
|
||||
buildAgentRuntimePlan: mockedBuildAgentRuntimePlan,
|
||||
}));
|
||||
|
||||
vi.doMock("../../plugins/provider-runtime.js", () => ({
|
||||
prepareProviderRuntimeAuth: mockedPrepareProviderRuntimeAuth,
|
||||
resolveProviderCapabilitiesWithPlugin: vi.fn(() => ({})),
|
||||
@@ -515,7 +533,7 @@ export async function loadRunOverflowCompactionHarness(): Promise<{
|
||||
}));
|
||||
|
||||
vi.doMock("./run/payloads.js", () => ({
|
||||
buildEmbeddedRunPayloads: vi.fn(() => []),
|
||||
buildEmbeddedRunPayloads: mockedBuildEmbeddedRunPayloads,
|
||||
}));
|
||||
|
||||
vi.doMock("./compaction-hooks.js", () => ({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
makeAttemptResult,
|
||||
makeCompactionSuccess,
|
||||
@@ -8,12 +8,14 @@ import {
|
||||
} from "./run.overflow-compaction.fixture.js";
|
||||
import {
|
||||
loadRunOverflowCompactionHarness,
|
||||
mockedBuildEmbeddedRunPayloads,
|
||||
mockedCoerceToFailoverError,
|
||||
mockedCompactDirect,
|
||||
mockedContextEngine,
|
||||
mockedDescribeFailoverError,
|
||||
mockedEvaluateContextWindowGuard,
|
||||
mockedGlobalHookRunner,
|
||||
mockedGetApiKeyForModel,
|
||||
mockedPickFallbackThinkingLevel,
|
||||
mockedResolveContextWindowInfo,
|
||||
mockedResolveFailoverStatus,
|
||||
@@ -34,6 +36,7 @@ describe("runEmbeddedPiAgent overflow compaction trigger routing", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
resetRunOverflowCompactionHarnessMocks();
|
||||
mockedBuildEmbeddedRunPayloads.mockReturnValue([{ text: "ok" }]);
|
||||
});
|
||||
|
||||
it("passes precomputed legacy before_agent_start result into the attempt", async () => {
|
||||
@@ -72,7 +75,6 @@ describe("runEmbeddedPiAgent overflow compaction trigger routing", () => {
|
||||
...overflowBaseRunParams,
|
||||
runId: "run-auth-profile-passthrough",
|
||||
});
|
||||
|
||||
expect(mockedRunEmbeddedAttempt).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
authProfileId: "test-profile",
|
||||
@@ -81,6 +83,91 @@ describe("runEmbeddedPiAgent overflow compaction trigger routing", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("forwards explicit OpenAI Codex auth profiles to codex plugin harnesses", async () => {
|
||||
const { clearAgentHarnesses, registerAgentHarness } = await import("../harness/registry.js");
|
||||
const pluginRunAttempt = vi.fn(async () => makeAttemptResult({ assistantTexts: ["ok"] }));
|
||||
clearAgentHarnesses();
|
||||
registerAgentHarness({
|
||||
id: "codex",
|
||||
label: "Codex",
|
||||
supports: (ctx) =>
|
||||
ctx.provider === "codex" ? { supported: true, priority: 100 } : { supported: false },
|
||||
runAttempt: pluginRunAttempt,
|
||||
});
|
||||
mockedGetApiKeyForModel.mockRejectedValueOnce(new Error("generic auth should be skipped"));
|
||||
|
||||
try {
|
||||
await runEmbeddedPiAgent({
|
||||
...overflowBaseRunParams,
|
||||
provider: "codex",
|
||||
model: "gpt-5.4",
|
||||
config: {
|
||||
agents: {
|
||||
defaults: {
|
||||
embeddedHarness: { runtime: "codex", fallback: "none" },
|
||||
},
|
||||
},
|
||||
},
|
||||
authProfileId: "openai-codex:work",
|
||||
authProfileIdSource: "user",
|
||||
runId: "plugin-harness-forwards-openai-codex-auth",
|
||||
});
|
||||
} finally {
|
||||
clearAgentHarnesses();
|
||||
}
|
||||
|
||||
expect(mockedGetApiKeyForModel).not.toHaveBeenCalled();
|
||||
expect(pluginRunAttempt).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
provider: "codex",
|
||||
authProfileId: "openai-codex:work",
|
||||
authProfileIdSource: "user",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("forwards OpenAI Codex auth profiles when openai/* is forced through codex", async () => {
|
||||
const { clearAgentHarnesses, registerAgentHarness } = await import("../harness/registry.js");
|
||||
const pluginRunAttempt = vi.fn(async () => makeAttemptResult({ assistantTexts: ["ok"] }));
|
||||
clearAgentHarnesses();
|
||||
registerAgentHarness({
|
||||
id: "codex",
|
||||
label: "Codex",
|
||||
supports: () => ({ supported: false }),
|
||||
runAttempt: pluginRunAttempt,
|
||||
});
|
||||
mockedGetApiKeyForModel.mockRejectedValueOnce(new Error("generic auth should be skipped"));
|
||||
|
||||
try {
|
||||
await runEmbeddedPiAgent({
|
||||
...overflowBaseRunParams,
|
||||
provider: "openai",
|
||||
model: "gpt-5.4",
|
||||
config: {
|
||||
agents: {
|
||||
defaults: {
|
||||
embeddedHarness: { runtime: "codex", fallback: "none" },
|
||||
},
|
||||
},
|
||||
},
|
||||
authProfileId: "openai-codex:work",
|
||||
authProfileIdSource: "user",
|
||||
runId: "forced-codex-harness-forwards-openai-codex-auth",
|
||||
});
|
||||
} finally {
|
||||
clearAgentHarnesses();
|
||||
}
|
||||
|
||||
expect(mockedGetApiKeyForModel).not.toHaveBeenCalled();
|
||||
expect(pluginRunAttempt).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
provider: "openai",
|
||||
authProfileId: "openai-codex:work",
|
||||
authProfileIdSource: "user",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("blocks undersized models before dispatching a provider attempt", async () => {
|
||||
mockedResolveContextWindowInfo.mockReturnValue({
|
||||
tokens: 800,
|
||||
|
||||
Reference in New Issue
Block a user