mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:10:44 +00:00
ci(qa): slim release transport startup
This commit is contained in:
@@ -667,8 +667,8 @@ jobs:
|
||||
--repo-root . \
|
||||
--output-dir "${output_dir}" \
|
||||
--provider-mode mock-openai \
|
||||
--model "${OPENCLAW_CI_OPENAI_MODEL}" \
|
||||
--alt-model openai/gpt-5.4-alt \
|
||||
--model mock-openai/gpt-5.5 \
|
||||
--alt-model mock-openai/gpt-5.5-alt \
|
||||
--profile fast \
|
||||
--fast
|
||||
)
|
||||
@@ -755,8 +755,8 @@ jobs:
|
||||
--repo-root . \
|
||||
--output-dir "${output_dir}" \
|
||||
--provider-mode mock-openai \
|
||||
--model "${OPENCLAW_CI_OPENAI_MODEL}" \
|
||||
--alt-model openai/gpt-5.4-alt \
|
||||
--model mock-openai/gpt-5.5 \
|
||||
--alt-model mock-openai/gpt-5.5-alt \
|
||||
--fast \
|
||||
--credential-source convex \
|
||||
--credential-role ci
|
||||
|
||||
@@ -87,6 +87,7 @@ describe("buildQaRuntimeEnv", () => {
|
||||
expect(env.OPENCLAW_TEST_FAST).toBe("1");
|
||||
expect(env.OPENCLAW_QA_ALLOW_LOCAL_IMAGE_PROVIDER).toBe("1");
|
||||
expect(env.OPENCLAW_ALLOW_SLOW_REPLY_TESTS).toBe("1");
|
||||
expect(env.OPENCLAW_SKIP_STARTUP_MODEL_PREWARM).toBe("1");
|
||||
expect(env.OPENCLAW_BUNDLED_PLUGINS_DIR).toBe("/tmp/openclaw-qa/bundled-plugins");
|
||||
expect(env.OPENCLAW_COMPATIBILITY_HOST_VERSION).toBe("2026.4.8");
|
||||
});
|
||||
|
||||
@@ -212,6 +212,7 @@ export function buildQaRuntimeEnv(params: {
|
||||
OPENCLAW_SKIP_BROWSER_CONTROL_SERVER: "1",
|
||||
OPENCLAW_SKIP_GMAIL_WATCHER: "1",
|
||||
OPENCLAW_SKIP_CANVAS_HOST: "1",
|
||||
OPENCLAW_SKIP_STARTUP_MODEL_PREWARM: "1",
|
||||
OPENCLAW_NO_RESPAWN: "1",
|
||||
OPENCLAW_TEST_FAST: "1",
|
||||
OPENCLAW_QA_ALLOW_LOCAL_IMAGE_PROVIDER: "1",
|
||||
|
||||
@@ -94,6 +94,54 @@ describe("startQaLiveLaneGateway", () => {
|
||||
expect(mockStop).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("disables memory search for transport-only live lanes", async () => {
|
||||
await startQaLiveLaneGateway({
|
||||
repoRoot: "/tmp/openclaw-repo",
|
||||
transport: createStubTransport(),
|
||||
transportBaseUrl: "http://127.0.0.1:43123",
|
||||
providerMode: "mock-openai",
|
||||
primaryModel: "mock-openai/gpt-5.5",
|
||||
alternateModel: "mock-openai/gpt-5.5-alt",
|
||||
controlUiEnabled: false,
|
||||
});
|
||||
|
||||
const [{ mutateConfig }] = startQaGatewayChild.mock.calls[0] ?? [];
|
||||
expect(typeof mutateConfig).toBe("function");
|
||||
const cfg = mutateConfig?.({
|
||||
plugins: {
|
||||
allow: ["acpx", "memory-core", "qa-channel"],
|
||||
entries: {
|
||||
acpx: { enabled: true },
|
||||
"memory-core": { enabled: true },
|
||||
"qa-channel": { enabled: true },
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
defaults: {
|
||||
memorySearch: {
|
||||
enabled: true,
|
||||
sync: {
|
||||
onSearch: true,
|
||||
onSessionStart: true,
|
||||
watch: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(cfg?.plugins?.allow).toEqual(["acpx", "qa-channel"]);
|
||||
expect(cfg?.plugins?.entries).not.toHaveProperty("memory-core");
|
||||
expect(cfg?.agents?.defaults?.memorySearch).toMatchObject({
|
||||
enabled: false,
|
||||
sync: {
|
||||
onSearch: false,
|
||||
onSessionStart: false,
|
||||
watch: false,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("forwards gateway stop options to the child harness", async () => {
|
||||
const harness = await startQaLiveLaneGateway({
|
||||
repoRoot: "/tmp/openclaw-repo",
|
||||
|
||||
@@ -34,6 +34,44 @@ async function stopQaLiveLaneResources(
|
||||
}
|
||||
}
|
||||
|
||||
function omitMemoryCoreEntry<T extends Record<string, unknown> | undefined>(entries: T): T {
|
||||
if (!entries || !Object.prototype.hasOwnProperty.call(entries, "memory-core")) {
|
||||
return entries;
|
||||
}
|
||||
const { "memory-core": _memoryCore, ...rest } = entries;
|
||||
return rest as T;
|
||||
}
|
||||
|
||||
function prepareLiveTransportGatewayConfig(cfg: OpenClawConfig): OpenClawConfig {
|
||||
const defaults = cfg.agents?.defaults ?? {};
|
||||
return {
|
||||
...cfg,
|
||||
plugins: cfg.plugins
|
||||
? {
|
||||
...cfg.plugins,
|
||||
allow: cfg.plugins.allow?.filter((pluginId) => pluginId !== "memory-core"),
|
||||
entries: omitMemoryCoreEntry(cfg.plugins.entries),
|
||||
}
|
||||
: cfg.plugins,
|
||||
agents: {
|
||||
...cfg.agents,
|
||||
defaults: {
|
||||
...defaults,
|
||||
memorySearch: {
|
||||
...defaults.memorySearch,
|
||||
enabled: false,
|
||||
sync: {
|
||||
...defaults.memorySearch?.sync,
|
||||
onSearch: false,
|
||||
onSessionStart: false,
|
||||
watch: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function startQaLiveLaneGateway(params: {
|
||||
repoRoot: string;
|
||||
command?: QaGatewayChildCommand;
|
||||
@@ -70,7 +108,8 @@ export async function startQaLiveLaneGateway(params: {
|
||||
thinkingDefault: params.thinkingDefault,
|
||||
claudeCliAuthMode: params.claudeCliAuthMode,
|
||||
controlUiEnabled: params.controlUiEnabled,
|
||||
mutateConfig: params.mutateConfig,
|
||||
mutateConfig: (cfg) =>
|
||||
prepareLiveTransportGatewayConfig(params.mutateConfig ? params.mutateConfig(cfg) : cfg),
|
||||
});
|
||||
return {
|
||||
gateway,
|
||||
|
||||
@@ -23,6 +23,7 @@ const ACP_BACKEND_READY_TIMEOUT_MS = 5_000;
|
||||
const ACP_BACKEND_READY_POLL_MS = 50;
|
||||
const PRIMARY_MODEL_PREWARM_TIMEOUT_MS = 5_000;
|
||||
const STARTUP_PROVIDER_DISCOVERY_TIMEOUT_MS = 5_000;
|
||||
const SKIP_STARTUP_MODEL_PREWARM_ENV = "OPENCLAW_SKIP_STARTUP_MODEL_PREWARM";
|
||||
|
||||
type Awaitable<T> = T | Promise<T>;
|
||||
|
||||
@@ -43,6 +44,11 @@ function shouldCheckRestartSentinel(env: NodeJS.ProcessEnv = process.env): boole
|
||||
return !env.VITEST && env.NODE_ENV !== "test";
|
||||
}
|
||||
|
||||
function shouldSkipStartupModelPrewarm(env: NodeJS.ProcessEnv = process.env): boolean {
|
||||
const raw = env[SKIP_STARTUP_MODEL_PREWARM_ENV]?.trim().toLowerCase();
|
||||
return raw === "1" || raw === "true" || raw === "yes" || raw === "on";
|
||||
}
|
||||
|
||||
function shouldStartGatewayMemoryBackend(cfg: OpenClawConfig): boolean {
|
||||
return cfg.memory?.backend === "qmd";
|
||||
}
|
||||
@@ -189,6 +195,9 @@ function schedulePrimaryModelPrewarm(
|
||||
},
|
||||
prewarm: typeof prewarmConfiguredPrimaryModel = prewarmConfiguredPrimaryModel,
|
||||
): void {
|
||||
if (shouldSkipStartupModelPrewarm()) {
|
||||
return;
|
||||
}
|
||||
void measureStartup(params.startupTrace, "sidecars.model-prewarm", () =>
|
||||
prewarmConfiguredPrimaryModelWithTimeout(
|
||||
{
|
||||
@@ -661,4 +670,5 @@ export const __testing = {
|
||||
prewarmConfiguredPrimaryModel,
|
||||
prewarmConfiguredPrimaryModelWithTimeout,
|
||||
schedulePrimaryModelPrewarm,
|
||||
shouldSkipStartupModelPrewarm,
|
||||
};
|
||||
|
||||
@@ -32,11 +32,12 @@ vi.mock("../agents/pi-embedded-runner/runtime.js", () => ({
|
||||
}));
|
||||
|
||||
let prewarmConfiguredPrimaryModel: typeof import("./server-startup.js").__testing.prewarmConfiguredPrimaryModel;
|
||||
let shouldSkipStartupModelPrewarm: typeof import("./server-startup.js").__testing.shouldSkipStartupModelPrewarm;
|
||||
|
||||
describe("gateway startup primary model warmup", () => {
|
||||
beforeAll(async () => {
|
||||
({
|
||||
__testing: { prewarmConfiguredPrimaryModel },
|
||||
__testing: { prewarmConfiguredPrimaryModel, shouldSkipStartupModelPrewarm },
|
||||
} = await import("./server-startup.js"));
|
||||
});
|
||||
|
||||
@@ -84,6 +85,20 @@ describe("gateway startup primary model warmup", () => {
|
||||
expect(piModelModuleLoadedMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("honors the startup model prewarm skip env", () => {
|
||||
expect(shouldSkipStartupModelPrewarm({})).toBe(false);
|
||||
expect(
|
||||
shouldSkipStartupModelPrewarm({
|
||||
OPENCLAW_SKIP_STARTUP_MODEL_PREWARM: "1",
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
shouldSkipStartupModelPrewarm({
|
||||
OPENCLAW_SKIP_STARTUP_MODEL_PREWARM: "true",
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("skips static warmup for configured CLI backends", async () => {
|
||||
await prewarmConfiguredPrimaryModel({
|
||||
cfg: {
|
||||
|
||||
Reference in New Issue
Block a user