improved a lot of things

This commit is contained in:
SinachPat
2026-04-27 04:52:15 +01:00
parent 197313c0ef
commit 9d9d7d7a37
25 changed files with 1598 additions and 288 deletions
@@ -36,7 +36,6 @@ export async function answerAgentQuestion(
},
],
maxTokens: 1024,
temperature: 0.7,
});
let parsed: unknown;
@@ -34,7 +34,6 @@ export async function queryCrossArtboard(
},
],
maxTokens: 1024,
temperature: 0.3,
});
// Returning empty results on parse failure is indistinguishable from "no match".
@@ -49,5 +48,19 @@ export async function queryCrossArtboard(
);
}
// Runtime guard: ensure the parsed value has the expected shape before casting.
// Without this, a malformed AI response (e.g. { results: null }) would let
// callers hit a TypeError on `.results.map()` instead of a clear error message.
if (
typeof parsed !== 'object' ||
parsed === null ||
!Array.isArray((parsed as Record<string, unknown>)['results'])
) {
throw new Error(
`Artboard query response missing "results" array. ` +
`Raw response (first 300 chars): ${response.text.slice(0, 300)}`
);
}
return parsed as ArtboardQueryOutput;
}
@@ -57,7 +57,6 @@ export async function fillCompletionZone(
system,
messages: [{ role: 'user', content: userContent }],
maxTokens: 4096,
temperature: 0.3,
});
try {
@@ -27,7 +27,6 @@ export async function generateDiffSummary(
},
],
maxTokens: 128,
temperature: 0.3,
});
return { summary: response.text.trim() };
+34 -25
View File
@@ -2,10 +2,12 @@ import type { AIGateway } from '../gateway.js';
import { buildSystemPrompt } from '../prompts/system.js';
export interface DriftReportInput {
/** Screenshot of the live app as base64 data URL */
screenshotBase64: string;
/** Active Design Language File as JSON string */
dlfJson: string;
/** Screenshot of the live app as base64 data URL (optional — text-only analysis if absent) */
screenshotBase64?: string;
/** Active Design Language File as JSON string (optional — generic advice if absent) */
dlfJson?: string;
/** Human-readable artboard metadata to give the model context (name, size, origin, etc.) */
artboardContext?: string;
}
export interface DriftViolation {
@@ -29,32 +31,39 @@ export async function generateDriftReport(
): Promise<DriftReportOutput> {
const system = buildSystemPrompt({
role: 'a design system compliance auditor',
dlfJson: input.dlfJson,
...(input.dlfJson !== undefined ? { dlfJson: input.dlfJson } : {}),
});
type ContentBlock =
| { type: 'image'; source: { type: 'base64'; media_type: 'image/png'; data: string } }
| { type: 'text'; text: string };
const userContent: ContentBlock[] = [];
if (input.screenshotBase64) {
userContent.push({
type: 'image',
source: {
type: 'base64',
media_type: 'image/png',
data: input.screenshotBase64.replace(/^data:image\/\w+;base64,/, ''),
},
});
}
const analysisInstructions = input.screenshotBase64
? 'Compare this screenshot against the design language file provided in your system context.'
: `Analyse the following artboard for design system drift:\n\n${input.artboardContext ?? '(no artboard context provided)'}`;
userContent.push({
type: 'text',
text: `${analysisInstructions} Identify all design system drift violations.\n\nReturn a JSON object:\n{\n "violations": [{"component":"...", "property":"...", "currentValue":"...", "expectedValue":"...", "severity":"critical|warning", "description":"..."}],\n "summary": "...",\n "violationCount": N\n}\n\nRespond ONLY with valid JSON.`,
});
const response = await gateway.complete({
system,
messages: [
{
role: 'user',
content: [
{
type: 'image',
source: {
type: 'base64',
media_type: 'image/png',
data: input.screenshotBase64.replace(/^data:image\/\w+;base64,/, ''),
},
},
{
type: 'text',
text: 'Compare this screenshot against the design language file provided in your system context. Identify all design system drift violations.\n\nReturn a JSON object:\n{\n "violations": [{"component":"...", "property":"...", "currentValue":"...", "expectedValue":"...", "severity":"critical|warning", "description":"..."}],\n "summary": "...",\n "violationCount": N\n}\n\nRespond ONLY with valid JSON.',
},
],
},
],
messages: [{ role: 'user', content: userContent }],
maxTokens: 4096,
temperature: 0.3,
});
// Returning empty violations on parse failure would be a false-negative in a
+3 -5
View File
@@ -73,10 +73,8 @@ export interface GatewayRequest {
messages: Anthropic.Messages.MessageParam[];
system?: Anthropic.Messages.TextBlockParam[];
maxTokens?: number;
// NOTE: adaptive thinking (`thinking: { type: 'adaptive' }`) requires SDK >=0.58.
// Upgrade @anthropic-ai/sdk and uncomment when available.
/** Temperature: 0.3 for deterministic, 0.7 for generative */
temperature?: number;
// NOTE: temperature is intentionally omitted — Opus 4.7 with adaptive thinking
// rejects temperature, top_p, and top_k with a 400 error.
}
export interface GatewayResponse {
@@ -106,7 +104,7 @@ export class AIGateway {
const response = await this.client.messages.create({
model: MODEL,
max_tokens: req.maxTokens ?? 4096,
...(req.temperature !== undefined ? { temperature: req.temperature } : {}),
thinking: { type: 'adaptive' },
...(req.system !== undefined ? { system: req.system } : {}),
messages: req.messages,
});