refactor(gateway): share rpc attachment normalization
This commit is contained in:
@@ -48,6 +48,7 @@ import {
|
||||
import { formatForLog } from "../ws-log.js";
|
||||
import { waitForAgentJob } from "./agent-job.js";
|
||||
import { injectTimestamp, timestampOptsFromConfig } from "./agent-timestamp.js";
|
||||
import { normalizeRpcAttachmentsToChatAttachments } from "./attachment-normalize.js";
|
||||
import { sessionsHandlers } from "./sessions.js";
|
||||
|
||||
const RESET_COMMAND_RE = /^\/(new|reset)(?:\s+([\s\S]*))?$/i;
|
||||
@@ -213,24 +214,7 @@ export const agentHandlers: GatewayRequestHandlers = {
|
||||
});
|
||||
return;
|
||||
}
|
||||
const normalizedAttachments =
|
||||
request.attachments
|
||||
?.map((a) => ({
|
||||
type: typeof a?.type === "string" ? a.type : undefined,
|
||||
mimeType: typeof a?.mimeType === "string" ? a.mimeType : undefined,
|
||||
fileName: typeof a?.fileName === "string" ? a.fileName : undefined,
|
||||
content:
|
||||
typeof a?.content === "string"
|
||||
? a.content
|
||||
: ArrayBuffer.isView(a?.content)
|
||||
? Buffer.from(
|
||||
a.content.buffer,
|
||||
a.content.byteOffset,
|
||||
a.content.byteLength,
|
||||
).toString("base64")
|
||||
: undefined,
|
||||
}))
|
||||
.filter((a) => a.content) ?? [];
|
||||
const normalizedAttachments = normalizeRpcAttachmentsToChatAttachments(request.attachments);
|
||||
|
||||
let message = request.message.trim();
|
||||
let images: Array<{ type: "image"; data: string; mimeType: string }> = [];
|
||||
|
||||
19
src/gateway/server-methods/attachment-normalize.test.ts
Normal file
19
src/gateway/server-methods/attachment-normalize.test.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { normalizeRpcAttachmentsToChatAttachments } from "./attachment-normalize.js";
|
||||
|
||||
describe("normalizeRpcAttachmentsToChatAttachments", () => {
|
||||
it("passes through string content", () => {
|
||||
const res = normalizeRpcAttachmentsToChatAttachments([
|
||||
{ type: "file", mimeType: "image/png", fileName: "a.png", content: "Zm9v" },
|
||||
]);
|
||||
expect(res).toEqual([
|
||||
{ type: "file", mimeType: "image/png", fileName: "a.png", content: "Zm9v" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("converts Uint8Array content to base64", () => {
|
||||
const bytes = new TextEncoder().encode("foo");
|
||||
const res = normalizeRpcAttachmentsToChatAttachments([{ content: bytes }]);
|
||||
expect(res[0]?.content).toBe("Zm9v");
|
||||
});
|
||||
});
|
||||
32
src/gateway/server-methods/attachment-normalize.ts
Normal file
32
src/gateway/server-methods/attachment-normalize.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { ChatAttachment } from "../chat-attachments.js";
|
||||
|
||||
export type RpcAttachmentInput = {
|
||||
type?: unknown;
|
||||
mimeType?: unknown;
|
||||
fileName?: unknown;
|
||||
content?: unknown;
|
||||
};
|
||||
|
||||
export function normalizeRpcAttachmentsToChatAttachments(
|
||||
attachments: RpcAttachmentInput[] | undefined,
|
||||
): ChatAttachment[] {
|
||||
return (
|
||||
attachments
|
||||
?.map((a) => ({
|
||||
type: typeof a?.type === "string" ? a.type : undefined,
|
||||
mimeType: typeof a?.mimeType === "string" ? a.mimeType : undefined,
|
||||
fileName: typeof a?.fileName === "string" ? a.fileName : undefined,
|
||||
content:
|
||||
typeof a?.content === "string"
|
||||
? a.content
|
||||
: ArrayBuffer.isView(a?.content)
|
||||
? Buffer.from(a.content.buffer, a.content.byteOffset, a.content.byteLength).toString(
|
||||
"base64",
|
||||
)
|
||||
: a?.content instanceof ArrayBuffer
|
||||
? Buffer.from(a.content).toString("base64")
|
||||
: undefined,
|
||||
}))
|
||||
.filter((a) => a.content) ?? []
|
||||
);
|
||||
}
|
||||
@@ -39,6 +39,7 @@ import {
|
||||
} from "../session-utils.js";
|
||||
import { formatForLog } from "../ws-log.js";
|
||||
import { injectTimestamp, timestampOptsFromConfig } from "./agent-timestamp.js";
|
||||
import { normalizeRpcAttachmentsToChatAttachments } from "./attachment-normalize.js";
|
||||
|
||||
type TranscriptAppendResult = {
|
||||
ok: boolean;
|
||||
@@ -385,24 +386,7 @@ export const chatHandlers: GatewayRequestHandlers = {
|
||||
}
|
||||
const inboundMessage = sanitizedMessageResult.message;
|
||||
const stopCommand = isChatStopCommandText(inboundMessage);
|
||||
const normalizedAttachments =
|
||||
p.attachments
|
||||
?.map((a) => ({
|
||||
type: typeof a?.type === "string" ? a.type : undefined,
|
||||
mimeType: typeof a?.mimeType === "string" ? a.mimeType : undefined,
|
||||
fileName: typeof a?.fileName === "string" ? a.fileName : undefined,
|
||||
content:
|
||||
typeof a?.content === "string"
|
||||
? a.content
|
||||
: ArrayBuffer.isView(a?.content)
|
||||
? Buffer.from(
|
||||
a.content.buffer,
|
||||
a.content.byteOffset,
|
||||
a.content.byteLength,
|
||||
).toString("base64")
|
||||
: undefined,
|
||||
}))
|
||||
.filter((a) => a.content) ?? [];
|
||||
const normalizedAttachments = normalizeRpcAttachmentsToChatAttachments(p.attachments);
|
||||
const rawMessage = inboundMessage.trim();
|
||||
if (!rawMessage && normalizedAttachments.length === 0) {
|
||||
respond(
|
||||
|
||||
Reference in New Issue
Block a user