From b45e39f83e79877d041f6e005052e374ba66c948 Mon Sep 17 00:00:00 2001 From: Michal Vanek Date: Fri, 5 Jun 2026 13:35:41 +0200 Subject: [PATCH] feat: persist sourceFile in MCP annotation store --- mcp/src/server/mcp.ts | 2 ++ mcp/src/server/sqlite.ts | 9 +++++++-- mcp/src/types.ts | 1 + package/example/public/schema/annotation.v1.json | 4 ++++ package/example/src/app/api/page.tsx | 1 + package/example/src/app/mcp/page.tsx | 1 + package/example/src/app/schema/page.tsx | 4 ++++ 7 files changed, 20 insertions(+), 2 deletions(-) diff --git a/mcp/src/server/mcp.ts b/mcp/src/server/mcp.ts index 4265a9cd..ff210c06 100644 --- a/mcp/src/server/mcp.ts +++ b/mcp/src/server/mcp.ts @@ -304,6 +304,7 @@ type Annotation = { timestamp?: number; nearbyText?: string; reactComponents?: string; + sourceFile?: string; status: string; kind?: "feedback" | "placement" | "rearrange"; placement?: { @@ -345,6 +346,7 @@ function mapAnnotationForMcp(a: Annotation) { timestamp: a.timestamp, nearbyText: a.nearbyText, reactComponents: a.reactComponents, + ...(a.sourceFile ? { sourceFile: a.sourceFile } : {}), ...(a.kind === "placement" && a.placement ? { placement: a.placement } : {}), ...(a.kind === "rearrange" && a.rearrange ? { rearrange: a.rearrange } : {}), }; diff --git a/mcp/src/server/sqlite.ts b/mcp/src/server/sqlite.ts index 007c386a..8a3704f3 100644 --- a/mcp/src/server/sqlite.ts +++ b/mcp/src/server/sqlite.ts @@ -102,6 +102,7 @@ function initDatabase(db: Database.Database): void { is_multi_select INTEGER DEFAULT 0, is_fixed INTEGER DEFAULT 0, react_components TEXT, + source_file TEXT, url TEXT, intent TEXT, severity TEXT, @@ -215,6 +216,7 @@ function rowToAnnotation(row: Record): Annotation { isMultiSelect: Boolean(row.is_multi_select), isFixed: Boolean(row.is_fixed), reactComponents: row.react_components as string | undefined, + sourceFile: row.source_file as string | undefined, kind, ...(kind === "placement" && extra?.placement ? { placement: extra.placement } : {}), ...(kind === "rearrange" && extra?.rearrange ? { rearrange: extra.rearrange } : {}), @@ -243,6 +245,7 @@ export function createSQLiteStore(dbPath?: string): AFSStore { // Safe migrations for new columns (no-ops if already exist) try { db.exec("ALTER TABLE annotations ADD COLUMN kind TEXT DEFAULT 'feedback'"); } catch {} try { db.exec("ALTER TABLE annotations ADD COLUMN extra TEXT"); } catch {} + try { db.exec("ALTER TABLE annotations ADD COLUMN source_file TEXT"); } catch {} // Restore event sequence from last event const lastEvent = db.prepare("SELECT MAX(sequence) as seq FROM events").get() as { seq: number | null }; @@ -269,13 +272,13 @@ export function createSQLiteStore(dbPath?: string): AFSStore { id, session_id, x, y, comment, element, element_path, timestamp, selected_text, bounding_box, nearby_text, css_classes, nearby_elements, computed_styles, full_path, accessibility, is_multi_select, is_fixed, - react_components, url, intent, severity, status, thread, created_at, + react_components, source_file, url, intent, severity, status, thread, created_at, updated_at, resolved_at, resolved_by, author_id, kind, extra ) VALUES ( @id, @sessionId, @x, @y, @comment, @element, @elementPath, @timestamp, @selectedText, @boundingBox, @nearbyText, @cssClasses, @nearbyElements, @computedStyles, @fullPath, @accessibility, @isMultiSelect, @isFixed, - @reactComponents, @url, @intent, @severity, @status, @thread, @createdAt, + @reactComponents, @sourceFile, @url, @intent, @severity, @status, @thread, @createdAt, @updatedAt, @resolvedAt, @resolvedBy, @authorId, @kind, @extra ) `), @@ -430,6 +433,7 @@ export function createSQLiteStore(dbPath?: string): AFSStore { isMultiSelect: annotation.isMultiSelect ? 1 : 0, isFixed: annotation.isFixed ? 1 : 0, reactComponents: annotation.reactComponents ?? null, + sourceFile: annotation.sourceFile ?? null, url: annotation.url ?? null, intent: annotation.intent ?? null, severity: annotation.severity ?? null, @@ -612,6 +616,7 @@ export function createTenantStore(dbPath?: string): TenantStore { // Safe migrations for new columns (no-ops if already exist) try { db.exec("ALTER TABLE annotations ADD COLUMN kind TEXT DEFAULT 'feedback'"); } catch {} try { db.exec("ALTER TABLE annotations ADD COLUMN extra TEXT"); } catch {} + try { db.exec("ALTER TABLE annotations ADD COLUMN source_file TEXT"); } catch {} // Restore event sequence from last event const lastEvent = db.prepare("SELECT MAX(sequence) as seq FROM events").get() as { seq: number | null }; diff --git a/mcp/src/types.ts b/mcp/src/types.ts index b6ba3ac7..6cdf2917 100644 --- a/mcp/src/types.ts +++ b/mcp/src/types.ts @@ -21,6 +21,7 @@ export type Annotation = { isMultiSelect?: boolean; // true if created via drag selection isFixed?: boolean; // true if element has fixed/sticky positioning (marker stays fixed) reactComponents?: string; // React component hierarchy (e.g. "