1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118import { db, event, graphqlQuery, bedrock } from "#src/utils";
export const getBlockerSummary = async () => {
const { blocker_id, refresh } = event.queryStringParameters as {
blocker_id: string;
refresh?: string;
};
await db.connect();
try {
const optionsData = await graphqlQuery({
query: `query {
options(where: { key: { _in: ["llm_enabled", "llm_model_id"] } }) {
key
value
}
}`,
});
const optMap = Object.fromEntries(
(optionsData?.options ?? []).map((o: any) => [o.key, o.value]),
);
if (optMap.llm_enabled === "false") {
return { disabled: true };
}
const modelId = optMap.llm_model_id || undefined;
if (refresh !== "true") {
const existing = (
await db.query({
text: `SELECT "id", "summary", "flagged" FROM "blocker_llm_summaries" WHERE "blocker_id" = $1 ORDER BY "created_at" DESC LIMIT 1`,
values: [blocker_id],
})
).rows[0];
if (existing?.flagged) {
return { flagged: true };
}
if (existing) {
return { id: existing.id, summary: existing.summary, cached: true };
}
}
const data = await graphqlQuery({
query: `query($id: uuid!) {
blockers_by_pk(id: $id) {
content
url { url }
blocker_messages {
message {
content
category
message_tags { tag { content } }
}
}
}
}`,
variables: { id: blocker_id },
});
const blocker = data?.blockers_by_pk;
if (!blocker) {
return {
statusCode: 404,
body: JSON.stringify({ error: "Blocker not found" }),
};
}
const messages = blocker.blocker_messages
.map(
(bm: any) =>
`Error: ${bm.message.content} (Category: ${bm.message.category}, Tags: ${bm.message.message_tags.map((t: any) => t.tag.content).join(", ")})`,
)
.join("\n");
const prompt = `You are an accessibility expert helping a website owner fix an issue detected by an automated accessibility scanner.
The issue was found on this URL: ${blocker.url.url}
Accessibility error details:
${messages}
Affected HTML:
\`\`\`html
${blocker.content}
\`\`\`
Please provide:
1. A plain-language explanation of what this accessibility issue is and why it matters to users.
2. Clear step-by-step instructions to fix it.
Be concise and practical. Target a general audience. This is for use in a UI context, so do not be conversational and begin or end with a question.`;
const summary = await bedrock.invoke(prompt, modelId);
const result = (
await db.query({
text: `INSERT INTO "blocker_llm_summaries" ("blocker_id", "summary")
VALUES ($1, $2)
ON CONFLICT ("blocker_id") DO UPDATE SET "summary" = $2, "flagged" = false, "updated_at" = now()
RETURNING "id"`,
values: [blocker_id, summary],
})
).rows[0];
return { id: result.id, summary, cached: false };
} catch (err) {
console.error("getBlockerSummary error:", err);
return {
statusCode: 500,
body: JSON.stringify({ error: String(err) }),
};
} finally {
await db.clean();
}
};