mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:10:44 +00:00
test: harden release validation smokes
This commit is contained in:
@@ -155,8 +155,11 @@ describeLive("buildOpenAIProvider live", () => {
|
||||
|
||||
const response = await client.responses.create({
|
||||
model: normalized?.id ?? liveCase.modelId,
|
||||
input: "Reply with exactly OK.",
|
||||
max_output_tokens: 16,
|
||||
instructions: "Return exactly OK and no other text.",
|
||||
input: "Return exactly OK.",
|
||||
max_output_tokens: 64,
|
||||
reasoning: { effort: "none" },
|
||||
text: { verbosity: "low" },
|
||||
});
|
||||
|
||||
expect(response.output_text.trim()).toMatch(/^OK[.!]?$/);
|
||||
|
||||
@@ -223,8 +223,11 @@ describeLive("openai plugin live", () => {
|
||||
});
|
||||
const response = await client.responses.create({
|
||||
model: normalized?.id ?? LIVE_MODEL_ID,
|
||||
input: "Reply with exactly OK.",
|
||||
max_output_tokens: 16,
|
||||
instructions: "Return exactly OK and no other text.",
|
||||
input: "Return exactly OK.",
|
||||
max_output_tokens: 64,
|
||||
reasoning: { effort: "none" },
|
||||
text: { verbosity: "low" },
|
||||
});
|
||||
|
||||
expect(response.output_text.trim()).toMatch(/^OK[.!]?$/);
|
||||
@@ -274,7 +277,7 @@ describeLive("openai plugin live", () => {
|
||||
const ttsConfig = createLiveTtsConfig();
|
||||
|
||||
const synthesized = await speechProvider.synthesize({
|
||||
text: "OpenClaw integration test OK.",
|
||||
text: "Open claw. Open claw. Integration test OK.",
|
||||
cfg,
|
||||
providerConfig: ttsConfig.providerConfigs.openai ?? {},
|
||||
target: "audio-file",
|
||||
|
||||
@@ -1377,6 +1377,80 @@ describe("qa mock openai server", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("does not let fanout completion state hijack child worker replies", async () => {
|
||||
const server = await startQaMockOpenAiServer({
|
||||
host: "127.0.0.1",
|
||||
port: 0,
|
||||
});
|
||||
cleanups.push(async () => {
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
const prompt =
|
||||
"Subagent fanout synthesis check: delegate two bounded subagents sequentially, then report both results together.";
|
||||
const spawn = await fetch(`${server.baseUrl}/v1/responses`, {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
stream: true,
|
||||
tools: [SESSIONS_SPAWN_TOOL],
|
||||
input: [{ role: "user", content: [{ type: "input_text", text: prompt }] }],
|
||||
}),
|
||||
});
|
||||
expect(spawn.status).toBe(200);
|
||||
expect(await spawn.text()).toContain('\\"label\\":\\"qa-fanout-alpha\\"');
|
||||
|
||||
const secondSpawn = await fetch(`${server.baseUrl}/v1/responses`, {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
stream: true,
|
||||
tools: [SESSIONS_SPAWN_TOOL],
|
||||
input: [
|
||||
{ role: "user", content: [{ type: "input_text", text: prompt }] },
|
||||
{
|
||||
type: "function_call_output",
|
||||
output:
|
||||
'{"status":"accepted","childSessionKey":"agent:qa:subagent:alpha","note":"ALPHA-OK"}',
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
expect(secondSpawn.status).toBe(200);
|
||||
expect(await secondSpawn.text()).toContain('\\"label\\":\\"qa-fanout-beta\\"');
|
||||
|
||||
const childReply = await fetch(`${server.baseUrl}/v1/responses`, {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
stream: false,
|
||||
input: [
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "input_text",
|
||||
text: "Fanout worker alpha: inspect the QA workspace and finish with exactly ALPHA-OK.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
expect(childReply.status).toBe(200);
|
||||
expect(await childReply.json()).toMatchObject({
|
||||
output: [
|
||||
{
|
||||
content: [
|
||||
{
|
||||
text: "ALPHA-OK",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps subagent fanout state isolated per mock server instance", async () => {
|
||||
const serverA = await startQaMockOpenAiServer({
|
||||
host: "127.0.0.1",
|
||||
|
||||
@@ -795,7 +795,9 @@ function buildAssistantText(
|
||||
return "FORKED-CONTEXT-ALPHA";
|
||||
}
|
||||
const fanoutCompleteReply = "subagent-1: ok\nsubagent-2: ok";
|
||||
if (scenarioState.subagentFanoutPhase === 2 && prompt) {
|
||||
const isFanoutCompletionTurn =
|
||||
/subagent fanout synthesis check/i.test(allInputText) || /^continue\.?$/i.test(prompt.trim());
|
||||
if (scenarioState.subagentFanoutPhase === 2 && prompt && isFanoutCompletionTurn) {
|
||||
scenarioState.subagentFanoutPhase = 3;
|
||||
return fanoutCompleteReply;
|
||||
}
|
||||
@@ -1191,6 +1193,12 @@ async function buildResponsesPayload(
|
||||
if (isHeartbeatPrompt(prompt)) {
|
||||
return buildAssistantEvents("HEARTBEAT_OK");
|
||||
}
|
||||
if (/fanout worker alpha/i.test(prompt)) {
|
||||
return buildAssistantEvents("ALPHA-OK");
|
||||
}
|
||||
if (/fanout worker beta/i.test(prompt)) {
|
||||
return buildAssistantEvents("BETA-OK");
|
||||
}
|
||||
if (QA_REASONING_ONLY_RECOVERY_PROMPT_RE.test(allInputText)) {
|
||||
if (!toolOutput) {
|
||||
return buildToolCallEventsWithArgs("read", { path: "QA_KICKOFF_TASK.md" });
|
||||
|
||||
@@ -585,6 +585,14 @@ async function runFreshLane(params) {
|
||||
logPath: join(params.logsDir, "fresh-onboard.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "models-set");
|
||||
await runModelsSet({
|
||||
lane,
|
||||
env,
|
||||
providerConfig: params.providerConfig,
|
||||
logPath: join(params.logsDir, "fresh-models-set.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "start-gateway");
|
||||
const gateway = await startGateway({
|
||||
lane,
|
||||
@@ -606,14 +614,6 @@ async function runFreshLane(params) {
|
||||
logPath: join(params.logsDir, "fresh-dashboard.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "models-set");
|
||||
await runModelsSet({
|
||||
lane,
|
||||
env,
|
||||
providerConfig: params.providerConfig,
|
||||
logPath: join(params.logsDir, "fresh-models-set.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "agent-turn");
|
||||
const agent = await runAgentTurn({
|
||||
lane,
|
||||
@@ -720,6 +720,14 @@ async function runUpgradeLane(params) {
|
||||
logPath: join(params.logsDir, "upgrade-onboard.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "models-set");
|
||||
await runModelsSet({
|
||||
lane,
|
||||
env,
|
||||
providerConfig: params.providerConfig,
|
||||
logPath: join(params.logsDir, "upgrade-models-set.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "start-gateway");
|
||||
const gateway = await startGateway({
|
||||
lane,
|
||||
@@ -741,14 +749,6 @@ async function runUpgradeLane(params) {
|
||||
logPath: join(params.logsDir, "upgrade-dashboard.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "models-set");
|
||||
await runModelsSet({
|
||||
lane,
|
||||
env,
|
||||
providerConfig: params.providerConfig,
|
||||
logPath: join(params.logsDir, "upgrade-models-set.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "agent-turn");
|
||||
const agent = await runAgentTurn({
|
||||
lane,
|
||||
@@ -837,6 +837,15 @@ async function runInstallerFreshSuite(params) {
|
||||
});
|
||||
}
|
||||
|
||||
logLanePhase(lane, "models-set");
|
||||
await runInstalledModelsSet({
|
||||
cliPath: freshShell.cliPath,
|
||||
env,
|
||||
providerConfig: params.providerConfig,
|
||||
cwd: lane.homeDir,
|
||||
logPath: join(params.logsDir, "installer-fresh-models-set.log"),
|
||||
});
|
||||
|
||||
if (!useManagedGatewayAfterInstall) {
|
||||
// Keep the Windows installer lane validating Scheduled Task registration during
|
||||
// onboarding and lifecycle commands, but use a manual gateway for the runtime
|
||||
@@ -884,15 +893,6 @@ async function runInstallerFreshSuite(params) {
|
||||
logPath: join(params.logsDir, "installer-fresh-dashboard.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "models-set");
|
||||
await runInstalledModelsSet({
|
||||
cliPath: freshShell.cliPath,
|
||||
env,
|
||||
providerConfig: params.providerConfig,
|
||||
cwd: lane.homeDir,
|
||||
logPath: join(params.logsDir, "installer-fresh-models-set.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "agent-turn");
|
||||
const agent = await runInstalledAgentTurn({
|
||||
cliPath: freshShell.cliPath,
|
||||
@@ -1023,6 +1023,15 @@ async function runDevUpdateSuite(params) {
|
||||
logPath: join(params.logsDir, "dev-update-onboard.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "models-set");
|
||||
await runInstalledModelsSet({
|
||||
cliPath: verifiedShell.cliPath,
|
||||
env,
|
||||
providerConfig: params.providerConfig,
|
||||
cwd: lane.homeDir,
|
||||
logPath: join(params.logsDir, "dev-update-models-set.log"),
|
||||
});
|
||||
|
||||
if (!useManagedGatewayAfterDevUpdate) {
|
||||
logLanePhase(lane, "gateway-start");
|
||||
const gateway = await startManualGatewayFromInstalledCli({
|
||||
@@ -1056,15 +1065,6 @@ async function runDevUpdateSuite(params) {
|
||||
logPath: join(params.logsDir, "dev-update-dashboard.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "models-set");
|
||||
await runInstalledModelsSet({
|
||||
cliPath: verifiedShell.cliPath,
|
||||
env,
|
||||
providerConfig: params.providerConfig,
|
||||
cwd: lane.homeDir,
|
||||
logPath: join(params.logsDir, "dev-update-models-set.log"),
|
||||
});
|
||||
|
||||
logLanePhase(lane, "agent-turn");
|
||||
const agent = await runInstalledAgentTurn({
|
||||
cliPath: verifiedShell.cliPath,
|
||||
|
||||
Reference in New Issue
Block a user