Vendor OpenClaw source as Adolf fork baseline
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
This commit is contained in:
364
extensions/moonshot/moonshot.live.test.ts
Normal file
364
extensions/moonshot/moonshot.live.test.ts
Normal file
@@ -0,0 +1,364 @@
|
||||
// Moonshot tests cover moonshot plugin behavior.
|
||||
import {
|
||||
streamSimple,
|
||||
type AssistantMessage,
|
||||
type Context,
|
||||
type Model,
|
||||
type Tool,
|
||||
} from "openclaw/plugin-sdk/llm";
|
||||
import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/plugin-test-runtime";
|
||||
import { isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
|
||||
import { Type } from "typebox";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import plugin from "./index.js";
|
||||
import { buildMoonshotProvider, MOONSHOT_CN_BASE_URL } from "./provider-catalog.js";
|
||||
import { createKimiWebSearchProvider } from "./src/kimi-web-search-provider.js";
|
||||
|
||||
const KIMI_SEARCH_KEY =
|
||||
process.env.KIMI_API_KEY?.trim() || process.env.MOONSHOT_API_KEY?.trim() || "";
|
||||
const MOONSHOT_API_KEY = process.env.MOONSHOT_API_KEY?.trim() || "";
|
||||
const describeLive = isLiveTestEnabled() && KIMI_SEARCH_KEY.length > 0 ? describe : describe.skip;
|
||||
const describeModelLive =
|
||||
isLiveTestEnabled() && MOONSHOT_API_KEY.length > 0 ? describe : describe.skip;
|
||||
const KIMI_LIVE_SEARCH_TIMEOUT_SECONDS = 60;
|
||||
|
||||
function isTransientKimiSearchError(error: unknown): boolean {
|
||||
if (!(error instanceof Error)) {
|
||||
return false;
|
||||
}
|
||||
if (error.name === "AbortError") {
|
||||
return true;
|
||||
}
|
||||
const message = error.message.toLowerCase();
|
||||
return message.includes("timeout") || message.includes("aborted");
|
||||
}
|
||||
|
||||
function isMoonshotAuthDrift(error: unknown): boolean {
|
||||
if (!(error instanceof Error)) {
|
||||
return false;
|
||||
}
|
||||
const message = error.message.toLowerCase();
|
||||
return (
|
||||
message.includes("401") &&
|
||||
(message.includes("incorrect api key") ||
|
||||
message.includes("incorrect_api_key") ||
|
||||
message.includes("invalid authentication") ||
|
||||
message.includes("invalid_authentication_error"))
|
||||
);
|
||||
}
|
||||
|
||||
describe("moonshot live auth drift detection", () => {
|
||||
it.each([
|
||||
["401 Incorrect API key provided", true],
|
||||
["401 invalid_authentication_error: Invalid Authentication", true],
|
||||
["401 Permission denied", false],
|
||||
["400 Incorrect API key provided", false],
|
||||
])("classifies %s", (message, expected) => {
|
||||
expect(isMoonshotAuthDrift(new Error(message))).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describeLive("moonshot plugin live", () => {
|
||||
it("runs Kimi web search through the provider tool", async () => {
|
||||
const provider = createKimiWebSearchProvider();
|
||||
const tool = provider.createTool?.({
|
||||
config: {},
|
||||
searchConfig: {
|
||||
kimi: { apiKey: KIMI_SEARCH_KEY },
|
||||
cacheTtlMinutes: 0,
|
||||
timeoutSeconds: KIMI_LIVE_SEARCH_TIMEOUT_SECONDS,
|
||||
},
|
||||
} as never);
|
||||
|
||||
let result: { provider?: string; content?: unknown; citations?: unknown } | undefined;
|
||||
let lastError: unknown;
|
||||
for (let attempt = 0; attempt < 2; attempt += 1) {
|
||||
try {
|
||||
result = await tool?.execute({ query: "OpenClaw GitHub", count: 1 });
|
||||
lastError = undefined;
|
||||
break;
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
if (isMoonshotAuthDrift(error)) {
|
||||
console.warn("[moonshot:live] skip Kimi web search: auth drift");
|
||||
return;
|
||||
}
|
||||
if (!isTransientKimiSearchError(error) || attempt === 1) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lastError) {
|
||||
throw toLintErrorObject(lastError, "Non-Error thrown");
|
||||
}
|
||||
|
||||
expect(result?.provider).toBe("kimi");
|
||||
expect(typeof result?.content).toBe("string");
|
||||
expect((result!.content as string).length).toBeGreaterThan(20);
|
||||
expect(Array.isArray(result?.citations)).toBe(true);
|
||||
}, 180_000);
|
||||
});
|
||||
|
||||
function resolveMoonshotModels(modelId: string): Model<"openai-completions">[] {
|
||||
const provider = buildMoonshotProvider();
|
||||
const model = provider.models.find((entry) => entry.id === modelId);
|
||||
if (!model) {
|
||||
throw new Error(`Moonshot catalog does not include ${modelId}`);
|
||||
}
|
||||
const defaultModel = {
|
||||
provider: "moonshot",
|
||||
baseUrl: provider.baseUrl,
|
||||
...model,
|
||||
api: "openai-completions",
|
||||
} as Model<"openai-completions">;
|
||||
return [defaultModel, { ...defaultModel, baseUrl: MOONSHOT_CN_BASE_URL }];
|
||||
}
|
||||
|
||||
function createNoopTool(): Tool {
|
||||
return {
|
||||
name: "noop",
|
||||
description: "Return ok.",
|
||||
parameters: Type.Object({}, { additionalProperties: false }),
|
||||
};
|
||||
}
|
||||
|
||||
async function collectDoneMessage(
|
||||
stream: AsyncIterable<{ type: string; message?: AssistantMessage; error?: AssistantMessage }>,
|
||||
): Promise<AssistantMessage> {
|
||||
let doneMessage: AssistantMessage | undefined;
|
||||
for await (const event of stream) {
|
||||
if (event.type === "error") {
|
||||
throw new Error(event.error?.errorMessage || "Moonshot live request failed");
|
||||
}
|
||||
if (event.type === "done") {
|
||||
doneMessage = event.message;
|
||||
}
|
||||
}
|
||||
if (!doneMessage) {
|
||||
throw new Error("Moonshot live stream ended without a done message");
|
||||
}
|
||||
return doneMessage;
|
||||
}
|
||||
|
||||
describeModelLive("moonshot K2.6 replay live", () => {
|
||||
it("accepts a cross-model tool-call replay after backfilling reasoning_content", async () => {
|
||||
const provider = await registerSingleProviderPlugin(plugin);
|
||||
const wrappedStream = provider.wrapStreamFn?.({
|
||||
provider: "moonshot",
|
||||
modelId: "kimi-k2.6",
|
||||
thinkingLevel: "low",
|
||||
streamFn: streamSimple,
|
||||
} as never);
|
||||
if (!wrappedStream) {
|
||||
throw new Error("Moonshot provider did not register a stream wrapper");
|
||||
}
|
||||
|
||||
const tool = createNoopTool();
|
||||
const replayContext: Context = {
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: "Call the noop tool.",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
api: "openai-responses",
|
||||
provider: "openai",
|
||||
model: "gpt-5.5",
|
||||
stopReason: "toolUse",
|
||||
content: [{ type: "toolCall", id: "call_cross_model", name: "noop", arguments: {} }],
|
||||
timestamp: Date.now(),
|
||||
} as AssistantMessage,
|
||||
{
|
||||
role: "toolResult",
|
||||
toolCallId: "call_cross_model",
|
||||
toolName: "noop",
|
||||
content: [{ type: "text", text: "ok" }],
|
||||
isError: false,
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: "The tool returned ok. Reply with exactly: ok",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
],
|
||||
tools: [tool],
|
||||
};
|
||||
|
||||
const runScenario = async (model: Model<"openai-completions">) => {
|
||||
let payload: Record<string, unknown> | undefined;
|
||||
const response = await collectDoneMessage(
|
||||
wrappedStream(model, replayContext, {
|
||||
apiKey: MOONSHOT_API_KEY,
|
||||
maxTokens: 256,
|
||||
onPayload: (value) => {
|
||||
payload = value as Record<string, unknown>;
|
||||
},
|
||||
}) as AsyncIterable<{
|
||||
type: string;
|
||||
message?: AssistantMessage;
|
||||
error?: AssistantMessage;
|
||||
}>,
|
||||
);
|
||||
|
||||
const messages = payload?.messages as Array<Record<string, unknown>> | undefined;
|
||||
const replayedAssistant = messages?.find(
|
||||
(message) => message.role === "assistant" && Array.isArray(message.tool_calls),
|
||||
);
|
||||
expect(replayedAssistant?.reasoning_content).toBe("");
|
||||
expect(response.stopReason).not.toBe("error");
|
||||
};
|
||||
|
||||
let lastAuthError: unknown;
|
||||
for (const model of resolveMoonshotModels("kimi-k2.6")) {
|
||||
try {
|
||||
await runScenario(model);
|
||||
return;
|
||||
} catch (error) {
|
||||
if (!isMoonshotAuthDrift(error)) {
|
||||
throw error;
|
||||
}
|
||||
lastAuthError = error;
|
||||
}
|
||||
}
|
||||
throw toLintErrorObject(lastAuthError, "Moonshot K2.6 rejected the API key in both regions");
|
||||
}, 180_000);
|
||||
});
|
||||
|
||||
describeModelLive("moonshot K2.7 Code live", () => {
|
||||
it("omits thinking controls and completes a replayed tool turn", async () => {
|
||||
const provider = await registerSingleProviderPlugin(plugin);
|
||||
const wrappedStream = provider.wrapStreamFn?.({
|
||||
provider: "moonshot",
|
||||
modelId: "kimi-k2.7-code",
|
||||
thinkingLevel: "off",
|
||||
extraParams: { thinking: { type: "disabled", keep: "all" } },
|
||||
streamFn: streamSimple,
|
||||
} as never);
|
||||
if (!wrappedStream) {
|
||||
throw new Error("Moonshot provider did not register a stream wrapper");
|
||||
}
|
||||
|
||||
const tool = createNoopTool();
|
||||
const firstUser = {
|
||||
role: "user" as const,
|
||||
content: "Call the noop tool with {}. Do not answer directly.",
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
|
||||
const runScenario = async (model: Model<"openai-completions">) => {
|
||||
let firstPayload: Record<string, unknown> | undefined;
|
||||
const first = await collectDoneMessage(
|
||||
wrappedStream(
|
||||
model,
|
||||
{ messages: [firstUser], tools: [tool] },
|
||||
{
|
||||
apiKey: MOONSHOT_API_KEY,
|
||||
maxTokens: 16_000,
|
||||
temperature: 0,
|
||||
onPayload: (payload) => {
|
||||
firstPayload = payload as Record<string, unknown>;
|
||||
},
|
||||
},
|
||||
) as AsyncIterable<{
|
||||
type: string;
|
||||
message?: AssistantMessage;
|
||||
error?: AssistantMessage;
|
||||
}>,
|
||||
);
|
||||
|
||||
expect(firstPayload).toBeDefined();
|
||||
expect(firstPayload).not.toHaveProperty("thinking");
|
||||
expect(firstPayload).not.toHaveProperty("reasoning_effort");
|
||||
expect(firstPayload).not.toHaveProperty("temperature");
|
||||
const reasoning = first.content.find((block) => block.type === "thinking");
|
||||
if (!reasoning || reasoning.type !== "thinking" || reasoning.thinking.length === 0) {
|
||||
throw new Error("Moonshot K2.7 Code did not return captured reasoning");
|
||||
}
|
||||
const toolCall = first.content.find((block) => block.type === "toolCall");
|
||||
if (!toolCall || toolCall.type !== "toolCall") {
|
||||
throw new Error(`Moonshot K2.7 Code did not call noop: ${first.stopReason}`);
|
||||
}
|
||||
expect(toolCall.name).toBe("noop");
|
||||
|
||||
let secondPayload: Record<string, unknown> | undefined;
|
||||
const replayContext: Context = {
|
||||
messages: [
|
||||
firstUser,
|
||||
first,
|
||||
{
|
||||
role: "toolResult",
|
||||
toolCallId: toolCall.id,
|
||||
toolName: toolCall.name,
|
||||
content: [{ type: "text", text: "ok" }],
|
||||
isError: false,
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: "Reply with exactly: ok",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
],
|
||||
tools: [tool],
|
||||
};
|
||||
const second = await collectDoneMessage(
|
||||
wrappedStream(model, replayContext, {
|
||||
apiKey: MOONSHOT_API_KEY,
|
||||
maxTokens: 16_000,
|
||||
temperature: 0,
|
||||
onPayload: (payload) => {
|
||||
secondPayload = payload as Record<string, unknown>;
|
||||
},
|
||||
}) as AsyncIterable<{
|
||||
type: string;
|
||||
message?: AssistantMessage;
|
||||
error?: AssistantMessage;
|
||||
}>,
|
||||
);
|
||||
|
||||
expect(secondPayload).toBeDefined();
|
||||
expect(secondPayload).not.toHaveProperty("thinking");
|
||||
expect(secondPayload).not.toHaveProperty("reasoning_effort");
|
||||
expect(secondPayload).not.toHaveProperty("temperature");
|
||||
const text = second.content
|
||||
.filter((block) => block.type === "text")
|
||||
.map((block) => block.text.trim())
|
||||
.join(" ");
|
||||
expect(text).toMatch(/^ok[.!]?$/i);
|
||||
};
|
||||
|
||||
let lastAuthError: unknown;
|
||||
for (const model of resolveMoonshotModels("kimi-k2.7-code")) {
|
||||
try {
|
||||
await runScenario(model);
|
||||
return;
|
||||
} catch (error) {
|
||||
if (!isMoonshotAuthDrift(error)) {
|
||||
throw error;
|
||||
}
|
||||
lastAuthError = error;
|
||||
}
|
||||
}
|
||||
throw toLintErrorObject(
|
||||
lastAuthError,
|
||||
"Moonshot K2.7 Code rejected the API key in both regions",
|
||||
);
|
||||
}, 180_000);
|
||||
});
|
||||
|
||||
function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
|
||||
if (value instanceof Error) {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
return new Error(value);
|
||||
}
|
||||
const error = new Error(fallbackMessage, { cause: value });
|
||||
if ((typeof value === "object" && value !== null) || typeof value === "function") {
|
||||
Object.assign(error, value);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
Reference in New Issue
Block a user