mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-13 15:47:28 +00:00
fix: guard empty MiniMax Anthropic messages (#74731)
Fixes #74589. Thanks @neeravmakwana and @DerekEXS.
This commit is contained in:
@@ -60,6 +60,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Bonjour/Gateway: treat active ciao probing and fresh name-conflict renames as in-progress so the mDNS watchdog waits for probe settlement before retrying, preventing rapid re-advertise loops on Windows, WSL, and other multicast-hostile hosts. (#74778) Refs #74242. Thanks @fuller-stack-dev.
|
||||
- Providers/MiniMax: send a minimal Anthropic-compatible user fallback when message conversion filters a turn to an empty payload, so MiniMax M2.7 no longer returns `chat content is empty` after tool-heavy sessions. Fixes #74589. Thanks @neeravmakwana and @DerekEXS.
|
||||
- Cron: keep long manual cron runs active in the task registry until completion, preventing transient `lost` markers before durable recovery reconciles. Fixes #78233. (#78243) Thanks @Feelw00.
|
||||
- Doctor/GitHub CLI: surface a `GH_CONFIG_DIR` hint when the GitHub skill is usable but `gh` auth lives under a different operator HOME than the agent process, without warning for disabled or filtered skills. Fixes #78063. (#78095) Thanks @tmimmanuel.
|
||||
- Gateway: dedupe concurrent `send`, `poll`, and `message.action` requests while delivery is still in flight, preventing duplicate outbound work for the same idempotency key. (#68341) Thanks @thesomewhatyou.
|
||||
|
||||
@@ -718,6 +718,61 @@ describe("anthropic transport stream", () => {
|
||||
expect(toolUse.input).toEqual({});
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: "empty history",
|
||||
context: { messages: [] } as AnthropicStreamContext,
|
||||
},
|
||||
{
|
||||
name: "blank user content",
|
||||
context: {
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: " \n\t ",
|
||||
timestamp: 0,
|
||||
},
|
||||
],
|
||||
} as AnthropicStreamContext,
|
||||
},
|
||||
])(
|
||||
"sends a minimal user fallback when Anthropic message conversion has no content: $name",
|
||||
async ({ context }) => {
|
||||
await runTransportStream(
|
||||
makeAnthropicTransportModel({
|
||||
id: "MiniMax-M2.7",
|
||||
name: "MiniMax M2.7",
|
||||
provider: "minimax",
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
}),
|
||||
context,
|
||||
{
|
||||
apiKey: "sk-minimax-test",
|
||||
} as AnthropicStreamOptions,
|
||||
);
|
||||
|
||||
expect(latestAnthropicRequest().payload).toMatchObject({
|
||||
model: "MiniMax-M2.7",
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: ".",
|
||||
cache_control: { type: "ephemeral" },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(guardedFetchMock).toHaveBeenCalledWith(
|
||||
"https://api.minimax.io/anthropic/v1/messages",
|
||||
expect.objectContaining({ method: "POST" }),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
["empty", ""],
|
||||
["whitespace-only", " \n\t "],
|
||||
|
||||
@@ -108,6 +108,8 @@ type MutableAssistantOutput = {
|
||||
errorMessage?: string;
|
||||
};
|
||||
|
||||
const EMPTY_ANTHROPIC_MESSAGES_FALLBACK_TEXT = ".";
|
||||
|
||||
function isClaudeOpus47Model(modelId: string): boolean {
|
||||
return modelId.includes("opus-4-7") || modelId.includes("opus-4.7");
|
||||
}
|
||||
@@ -425,6 +427,12 @@ function convertAnthropicMessages(
|
||||
return params;
|
||||
}
|
||||
|
||||
function ensureNonEmptyAnthropicMessages(messages: Array<Record<string, unknown>>) {
|
||||
return messages.length > 0
|
||||
? messages
|
||||
: [{ role: "user", content: EMPTY_ANTHROPIC_MESSAGES_FALLBACK_TEXT }];
|
||||
}
|
||||
|
||||
function convertAnthropicTools(tools: Context["tools"], isOAuthToken: boolean) {
|
||||
if (!tools) {
|
||||
return [];
|
||||
@@ -754,7 +762,9 @@ function buildAnthropicParams(
|
||||
});
|
||||
const params: Record<string, unknown> = {
|
||||
model: model.id,
|
||||
messages: convertAnthropicMessages(context.messages, model, isOAuthToken),
|
||||
messages: ensureNonEmptyAnthropicMessages(
|
||||
convertAnthropicMessages(context.messages, model, isOAuthToken),
|
||||
),
|
||||
max_tokens: maxTokens,
|
||||
stream: true,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user