mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-30 21:01:54 +08:00
Add skill context to Ask Hexclave
This commit is contained in:
parent
c7ef9e9461
commit
29b6554cb2
@ -3,6 +3,7 @@ import { selectModel } from "@/lib/ai/models";
|
||||
import { getFullSystemPrompt } from "@/lib/ai/prompts";
|
||||
import { reviewMcpCall } from "@/lib/ai/qa-reviewer";
|
||||
import { requestBodySchema } from "@/lib/ai/schema";
|
||||
import { getMcpSkillContextPrompt } from "@/lib/ai/mcp-skill-context";
|
||||
import { getTools } from "@/lib/ai/tools";
|
||||
import { getVerifiedQaContext } from "@/lib/ai/verified-qa";
|
||||
import { listManagedProjectIds } from "@/lib/projects";
|
||||
@ -61,6 +62,7 @@ export const POST = createSmartRouteHandler({
|
||||
if (isDocsOrSearch) {
|
||||
systemPrompt += await getVerifiedQaContext();
|
||||
}
|
||||
systemPrompt += await getMcpSkillContextPrompt(body.mcpCallMetadata?.toolName);
|
||||
const tools = await getTools(toolNames, { auth: fullReq.auth, targetProjectId: projectId });
|
||||
const toolsArg = Object.keys(tools).length > 0 ? tools : undefined;
|
||||
const isCreateDashboard = systemPromptId === "create-dashboard";
|
||||
|
||||
51
apps/backend/src/lib/ai/mcp-skill-context.test.ts
Normal file
51
apps/backend/src/lib/ai/mcp-skill-context.test.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { getMcpSkillContextPrompt } from "./mcp-skill-context";
|
||||
|
||||
describe("getMcpSkillContextPrompt", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("does not fetch skill context for non-ask_hexclave requests", async () => {
|
||||
const fetchSpy = vi.spyOn(globalThis, "fetch");
|
||||
|
||||
await expect(getMcpSkillContextPrompt("other_tool")).resolves.toMatchInlineSnapshot(`""`);
|
||||
expect(fetchSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("fetches and embeds the canonical skill for ask_hexclave requests", async () => {
|
||||
const fetchSpy = vi.spyOn(globalThis, "fetch").mockResolvedValue(
|
||||
new Response("# Hexclave Skill\n\nUse Hexclave docs."),
|
||||
);
|
||||
|
||||
await expect(getMcpSkillContextPrompt("ask_hexclave")).resolves.toMatchInlineSnapshot(`
|
||||
"
|
||||
|
||||
## MCP-Provided Hexclave Skill Context
|
||||
|
||||
The current request came through the public Hexclave MCP server's ask_hexclave tool.
|
||||
The backend fetched the canonical Hexclave agent skill from https://skill.hexclave.com
|
||||
immediately before spawning this assistant. Treat this skill content as baseline context
|
||||
for answering the user's question, while still using documentation tools for specific
|
||||
facts and citations:
|
||||
|
||||
# Hexclave Skill
|
||||
|
||||
Use Hexclave docs.
|
||||
"
|
||||
`);
|
||||
expect(fetchSpy).toHaveBeenCalledWith("https://skill.hexclave.com", {
|
||||
headers: { Accept: "text/markdown" },
|
||||
});
|
||||
});
|
||||
|
||||
it("fails loudly when the canonical skill cannot be fetched", async () => {
|
||||
vi.spyOn(globalThis, "fetch").mockResolvedValue(
|
||||
new Response("missing", { status: 503, statusText: "Service Unavailable" }),
|
||||
);
|
||||
|
||||
await expect(getMcpSkillContextPrompt("ask_hexclave")).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Failed to fetch skill from https://skill.hexclave.com: 503 Service Unavailable]`,
|
||||
);
|
||||
});
|
||||
});
|
||||
30
apps/backend/src/lib/ai/mcp-skill-context.ts
Normal file
30
apps/backend/src/lib/ai/mcp-skill-context.ts
Normal file
@ -0,0 +1,30 @@
|
||||
const hexclaveSkillResourceUri = "https://skill.hexclave.com";
|
||||
|
||||
export async function getMcpSkillContextPrompt(toolName: string | null | undefined): Promise<string> {
|
||||
if (toolName !== "ask_hexclave") {
|
||||
return "";
|
||||
}
|
||||
|
||||
const response = await fetch(hexclaveSkillResourceUri, {
|
||||
headers: { Accept: "text/markdown" },
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch skill from ${hexclaveSkillResourceUri}: ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
const skillContext = await response.text();
|
||||
return `
|
||||
|
||||
## MCP-Provided Hexclave Skill Context
|
||||
|
||||
The current request came through the public Hexclave MCP server's ask_hexclave tool.
|
||||
The backend fetched the canonical Hexclave agent skill from https://skill.hexclave.com
|
||||
immediately before spawning this assistant. Treat this skill content as baseline context
|
||||
for answering the user's question, while still using documentation tools for specific
|
||||
facts and citations:
|
||||
|
||||
${skillContext}
|
||||
`;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user