fix(webchat): support image-only sends

This commit is contained in:
Peter Steinberger
2026-01-26 05:32:29 +00:00
parent 9ba4b1e32b
commit 6859e1e6a6
11 changed files with 93 additions and 27 deletions

View File

@@ -35,7 +35,7 @@ export const ChatHistoryParamsSchema = Type.Object(
export const ChatSendParamsSchema = Type.Object(
{
sessionKey: NonEmptyString,
message: NonEmptyString,
message: Type.String(),
thinking: Type.Optional(Type.String()),
deliver: Type.Optional(Type.Boolean()),
attachments: Type.Optional(Type.Array(Type.Unknown())),

View File

@@ -338,6 +338,15 @@ export const chatHandlers: GatewayRequestHandlers = {
: undefined,
}))
.filter((a) => a.content) ?? [];
const rawMessage = p.message.trim();
if (!rawMessage && normalizedAttachments.length === 0) {
respond(
false,
undefined,
errorShape(ErrorCodes.INVALID_REQUEST, "message or attachment required"),
);
return;
}
let parsedMessage = p.message;
let parsedImages: ChatImageContent[] = [];
if (normalizedAttachments.length > 0) {

View File

@@ -208,6 +208,39 @@ describe("gateway server chat", () => {
| undefined;
expect(imgOpts?.images).toEqual([{ type: "image", data: pngB64, mimeType: "image/png" }]);
const callsBeforeImageOnly = spy.mock.calls.length;
const reqIdOnly = "chat-img-only";
ws.send(
JSON.stringify({
type: "req",
id: reqIdOnly,
method: "chat.send",
params: {
sessionKey: "main",
message: "",
idempotencyKey: "idem-img-only",
attachments: [
{
type: "image",
mimeType: "image/png",
fileName: "dot.png",
content: `data:image/png;base64,${pngB64}`,
},
],
},
}),
);
const imgOnlyRes = await onceMessage(ws, (o) => o.type === "res" && o.id === reqIdOnly, 8000);
expect(imgOnlyRes.ok).toBe(true);
expect(imgOnlyRes.payload?.runId).toBeDefined();
await waitFor(() => spy.mock.calls.length > callsBeforeImageOnly, 8000);
const imgOnlyOpts = spy.mock.calls.at(-1)?.[1] as
| { images?: Array<{ type: string; data: string; mimeType: string }> }
| undefined;
expect(imgOnlyOpts?.images).toEqual([{ type: "image", data: pngB64, mimeType: "image/png" }]);
const historyDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
tempDirs.push(historyDir);
testState.sessionStorePath = path.join(historyDir, "sessions.json");