improved a lot of things
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.56.0",
|
||||
"@anthropic-ai/sdk": "^0.91.1",
|
||||
"@originmain/design-language": "workspace:*",
|
||||
"@originmain/diff-engine": "workspace:*",
|
||||
"zod": "^3.0.0"
|
||||
|
||||
@@ -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() };
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user