fix: stabilize GPT-5.5 release gates

This commit is contained in:
Peter Steinberger
2026-05-02 06:35:44 +01:00
parent fecac7e40a
commit e052bdcfb6
5 changed files with 70 additions and 15 deletions

View File

@@ -40,6 +40,7 @@ const providerConfig = {
secretEnv: "OPENAI_API_KEY",
authChoice: "openai-api-key",
model: "openai/gpt-5.5",
timeoutSeconds: 600,
},
anthropic: {
extensionId: "anthropic",
@@ -91,7 +92,7 @@ export const CROSS_OS_GATEWAY_STATUS_COMMAND_TIMEOUT_MS =
CROSS_OS_GATEWAY_STATUS_RPC_TIMEOUT_MS + 45_000;
export const CROSS_OS_GATEWAY_READY_TIMEOUT_MS = 3 * 60_000;
export const CROSS_OS_WINDOWS_GATEWAY_READY_TIMEOUT_MS = 5 * 60_000;
export const CROSS_OS_AGENT_TURN_TIMEOUT_SECONDS = 360;
export const CROSS_OS_AGENT_TURN_TIMEOUT_SECONDS = 600;
if (isMainModule()) {
try {
@@ -1840,6 +1841,22 @@ async function runInstalledModelsSet(params) {
logPath: params.logPath,
timeoutMs: 2 * 60 * 1000,
});
if (typeof params.providerConfig.timeoutSeconds === "number") {
await runInstalledCli({
cliPath: params.cliPath,
args: [
"config",
"set",
`models.providers.${params.providerConfig.extensionId}.timeoutSeconds`,
String(params.providerConfig.timeoutSeconds),
"--strict-json",
],
cwd: params.cwd,
env: params.env,
logPath: params.logPath,
timeoutMs: 2 * 60 * 1000,
});
}
await runInstalledCli({
cliPath: params.cliPath,
args: [
@@ -1875,7 +1892,7 @@ async function runInstalledAgentTurn(params) {
cwd: params.cwd,
env: params.env,
logPath: params.logPath,
timeoutMs: 10 * 60 * 1000,
timeoutMs: (CROSS_OS_AGENT_TURN_TIMEOUT_SECONDS + 60) * 1000,
});
if (!agentOutputHasExpectedOkMarker(result.stdout, { logPath: params.logPath })) {
throw new Error("Agent output did not contain the expected OK marker.");
@@ -2616,6 +2633,21 @@ async function runModelsSet(params) {
logPath: params.logPath,
timeoutMs: 2 * 60 * 1000,
});
if (typeof params.providerConfig.timeoutSeconds === "number") {
await runOpenClaw({
lane: params.lane,
env: params.env,
args: [
"config",
"set",
`models.providers.${params.providerConfig.extensionId}.timeoutSeconds`,
String(params.providerConfig.timeoutSeconds),
"--strict-json",
],
logPath: params.logPath,
timeoutMs: 2 * 60 * 1000,
});
}
await runOpenClaw({
lane: params.lane,
env: params.env,
@@ -2648,7 +2680,7 @@ async function runAgentTurn(params) {
env: params.env,
args: buildReleaseAgentTurnArgs(sessionId),
logPath: params.logPath,
timeoutMs: 10 * 60 * 1000,
timeoutMs: (CROSS_OS_AGENT_TURN_TIMEOUT_SECONDS + 60) * 1000,
});
if (!agentOutputHasExpectedOkMarker(result.stdout, { logPath: params.logPath })) {
throw new Error("Agent output did not contain the expected OK marker.");

View File

@@ -56,7 +56,7 @@ const DEFAULT_MODEL =
// The cron/MCP live probe now tolerates more cancelled tool-call retries in CI,
// so the outer test budget needs enough headroom to finish those retries.
const CLI_BACKEND_LIVE_TIMEOUT_MS = 20 * 60_000;
const CLI_BACKEND_REQUEST_TIMEOUT_MS = 240_000;
const CLI_BACKEND_REQUEST_TIMEOUT_MS = 600_000;
const CLI_BACKEND_AGENT_TIMEOUT_SECONDS = Math.max(
1,
Math.ceil(CLI_BACKEND_REQUEST_TIMEOUT_MS / 1000) - 10,

View File

@@ -129,15 +129,18 @@ function createManager(options?: {
getRuntimeConfig?: () => Record<string, unknown>;
channelIds?: ChannelId[];
startupTrace?: { measure: <T>(name: string, run: () => T | Promise<T>) => Promise<T> };
fillChannelDependencies?: boolean;
}) {
const log = createSubsystemLogger("gateway/server-channels-test");
const channelLogs = { discord: log } as Record<ChannelId, SubsystemLogger>;
const runtime = runtimeForLogger(log);
const channelRuntimeEnvs = { discord: runtime } as unknown as Record<ChannelId, RuntimeEnv>;
const channelIds = options?.channelIds ?? ["discord"];
for (const channelId of channelIds) {
channelLogs[channelId] ??= log.child(channelId);
channelRuntimeEnvs[channelId] ??= runtime;
if (options?.fillChannelDependencies !== false) {
for (const channelId of channelIds) {
channelLogs[channelId] ??= log.child(channelId);
channelRuntimeEnvs[channelId] ??= runtime;
}
}
return createChannelManager({
getRuntimeConfig: () => options?.getRuntimeConfig?.() ?? {},
@@ -576,6 +579,21 @@ describe("server-channels auto restart", () => {
expect(succeedingStart).toHaveBeenCalledTimes(1);
});
it("uses fallback logger and runtime when a channel is missing startup wiring", async () => {
const startAccount = vi.fn(async () => {
throw new Error("invalid_auth");
});
installTestRegistry(createTestPlugin({ id: "slack", startAccount }));
const manager = createManager({ channelIds: ["slack"], fillChannelDependencies: false });
await manager.startChannels();
await vi.advanceTimersByTimeAsync(0);
expect(startAccount).toHaveBeenCalledTimes(1);
const account = manager.getRuntimeSnapshot().channelAccounts.slack?.[DEFAULT_ACCOUNT_ID];
expect(account?.lastError).toBe("invalid_auth");
});
it("emits startup trace spans for channel preflight and handoff", async () => {
const measureMock = vi.fn(async (name: string, run: () => unknown) => await run());
const startupTrace = {

View File

@@ -13,7 +13,11 @@ import { type BackoffPolicy, computeBackoff, sleepWithAbort } from "../infra/bac
import { createTaskScopedChannelRuntime } from "../infra/channel-runtime-context.js";
import { formatErrorMessage } from "../infra/errors.js";
import { resetDirectoryCache } from "../infra/outbound/target-resolver.js";
import { createSubsystemLogger, runtimeForLogger } from "../logging/subsystem.js";
import {
createSubsystemLogger,
runtimeForLogger,
type SubsystemLogger,
} from "../logging/subsystem.js";
import { resolveAccountEntry, resolveNormalizedAccountEntry } from "../routing/account-lookup.js";
import {
DEFAULT_ACCOUNT_ID,
@@ -33,8 +37,6 @@ const CHANNEL_RESTART_POLICY: BackoffPolicy = {
const MAX_RESTART_ATTEMPTS = 10;
const CHANNEL_STOP_ABORT_TIMEOUT_MS = 5_000;
type SubsystemLogger = ReturnType<typeof createSubsystemLogger>;
type ChannelRuntimeStore = {
aborts: Map<string, AbortController>;
starting: Map<string, Promise<void>>;
@@ -128,8 +130,8 @@ function applyDescribedAccountFields(
type ChannelManagerOptions = {
getRuntimeConfig: () => OpenClawConfig;
channelLogs: Record<ChannelId, SubsystemLogger>;
channelRuntimeEnvs: Record<ChannelId, RuntimeEnv>;
channelLogs: Partial<Record<ChannelId, SubsystemLogger>>;
channelRuntimeEnvs: Partial<Record<ChannelId, RuntimeEnv>>;
/**
* Optional channel runtime helpers for external channel plugins.
*
@@ -706,7 +708,7 @@ export function createChannelManager(opts: ChannelManagerOptions): ChannelManage
try {
await measureStartup(`channels.${plugin.id}.start`, () => startChannel(plugin.id));
} catch (err) {
channelLogs[plugin.id]?.error?.(
ensureChannelLog(plugin.id).error?.(
`[${plugin.id}] channel startup failed: ${formatErrorMessage(err)}`,
);
}

View File

@@ -160,11 +160,14 @@ describe("scripts/openclaw-cross-os-release-checks", () => {
expect(allowlist).not.toContain("web-readability");
});
it("keeps cross-OS live smoke agent turns on minimal thinking", () => {
it("keeps cross-OS live smoke agent turns on GPT-5.5-safe timeouts and minimal thinking", () => {
const source = readFileSync("scripts/openclaw-cross-os-release-checks.ts", "utf8");
expect(source).toContain('"--thinking",\n "minimal"');
expect(CROSS_OS_AGENT_TURN_TIMEOUT_SECONDS).toBeLessThanOrEqual(360);
expect(CROSS_OS_AGENT_TURN_TIMEOUT_SECONDS).toBeGreaterThanOrEqual(600);
expect(source).toContain(
"models.providers.${params.providerConfig.extensionId}.timeoutSeconds",
);
expect(source).toContain('"--timeout",\n String(CROSS_OS_AGENT_TURN_TIMEOUT_SECONDS)');
expect(source.match(/buildReleaseAgentTurnArgs\(sessionId\)/g)?.length).toBeGreaterThanOrEqual(
2,