fix: harden assistant authoring and UI
This commit is contained in:
1 parent
fa0e55cc93
commit
edc7b4d55b
51 files changed
+4118
-916
No files matched your search
@@ -21,6 +21,7 @@ import { customJsxExamples, getCustomWidgetJsonSchema } from "@homarr/custom-wid
|
||||
import { db } from "@homarr/db";
|
||||
|
||||
import { getPackageVersion } from "~/versions/package-reader";
|
||||
import { getSafeAssistantToolError } from "../assistant/chat/assistant-tool-error";
|
||||
import { extractMcpTools } from "./_extract-tools";
|
||||
import { createMcpProtocolHandler } from "./_protocol";
|
||||
|
||||
@@ -204,7 +205,8 @@ const SAFE_ERROR_MESSAGES: Record<string, string> = {
|
||||
PRECONDITION_FAILED: "A precondition for this operation was not met",
|
||||
};
|
||||
|
||||
function sanitizeErrorMessage(error: unknown): string {
|
||||
function sanitizeErrorMessage(error: unknown, toolName: string): string {
|
||||
if (toolName.startsWith("customWidget_")) return getSafeAssistantToolError(error, { toolName });
|
||||
if (error instanceof Error && "code" in error) {
|
||||
const trpcCode = (error as Error & { code: string }).code;
|
||||
const safeMessage = SAFE_ERROR_MESSAGES[trpcCode];
|
||||
|
||||
@@ -99,6 +99,30 @@ describe("MCP v2 protocol", () => {
|
||||
expect(response.result.content).toEqual([{ type: "text", text: '{"message":"hello"}' }]);
|
||||
});
|
||||
|
||||
test("passes the tool name to safe error formatting", async () => {
|
||||
const formatToolError = vi.fn((_error: unknown, toolName: string) => `${toolName} input was invalid`);
|
||||
const handler = createMcpProtocolHandler({
|
||||
caller: {
|
||||
echo: vi.fn(async () => {
|
||||
throw new Error("private details");
|
||||
}),
|
||||
},
|
||||
tools: [echoTool],
|
||||
version: "1.0.0",
|
||||
instructions: "Test server",
|
||||
formatToolError,
|
||||
});
|
||||
const response = await parseResponse(
|
||||
await handler.fetch(createRequest("tools/call", { name: "echo", arguments: { message: "hello" } }, "echo")),
|
||||
);
|
||||
|
||||
expect(formatToolError).toHaveBeenCalledWith(expect.any(Error), "echo");
|
||||
expect(response.result).toMatchObject({
|
||||
isError: true,
|
||||
content: [{ type: "text", text: '{"error":"echo input was invalid"}' }],
|
||||
});
|
||||
});
|
||||
|
||||
test("keeps stateless compatibility with 2025 Streamable HTTP clients", async () => {
|
||||
const { handler } = createTestHandler();
|
||||
const request = new Request("http://homarr.test/api/mcp", {
|
||||
|
||||
@@ -8,7 +8,7 @@ interface CreateMcpProtocolHandlerOptions {
|
||||
version: string;
|
||||
instructions: string;
|
||||
configureServer?: (server: McpServer) => void;
|
||||
formatToolError: (error: unknown) => string;
|
||||
formatToolError: (error: unknown, toolName: string) => string;
|
||||
onToolError?: (toolName: string, error: unknown) => void;
|
||||
onProtocolError?: (error: Error) => void;
|
||||
}
|
||||
@@ -70,7 +70,9 @@ export const createMcpProtocolHandler = ({
|
||||
} catch (error) {
|
||||
onToolError?.(tool.name, error);
|
||||
return {
|
||||
content: [{ type: "text" as const, text: JSON.stringify({ error: formatToolError(error) }) }],
|
||||
content: [
|
||||
{ type: "text" as const, text: JSON.stringify({ error: formatToolError(error, tool.name) }) },
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user