Project Files
src / types.ts
/**
* Types for Find Image Plugin
* Focused on image/media records, optional embedded metadata, and visual search.
*/
// ═══════════════════════════════════════════════════════════════
// Source Information
// ═══════════════════════════════════════════════════════════════
/**
* Structured source information for tracking where a match was found
*/
export type SourceInfo =
| { type: 'attachment'; originalName: string; filePath?: string; chatId?: string; imageType?: string }
| { type: 'variant'; chatId: string; filePath: string; imageType?: string }
| { type: 'image'; chatId: string; filePath: string; imageType?: string }
| { type: 'picture'; chatId: string; filePath: string; imageType?: string }
| { type: 'saved_image'; filePath: string; imageType?: string }
| { type: 'draw_things_project'; projectFile: string; logicalTime?: number; insertionOrder?: number; generationFingerprint?: string };
// ═══════════════════════════════════════════════════════════════
// Generation Metadata
// ═══════════════════════════════════════════════════════════════
/**
* Generation metadata from Draw Things audit logs or image XMP
*/
export interface GenerationMetadata {
timestamp?: string;
latitude?: number;
longitude?: number;
lensModel?: string;
exposureTime?: string;
fNumber?: number;
iso?: number;
exposureCompensation?: number;
focalLength?: number;
focalLength35mm?: number;
exposureProgram?: string;
meteringMode?: string;
whiteBalance?: string;
flash?: string;
orientation?: string;
exposureMode?: string;
prompt: string;
negativePrompt?: string;
model: string;
loras?: string[] | Array<{ model: string; weight: number }>;
/** User-managed labels persisted in generation_index_cache.json. */
tags?: string[];
sampler?: string;
steps?: number;
cfgScale?: number;
seed?: number;
seedMode?: string;
shift?: number;
strength?: number;
mode?: string;
width?: number;
height?: number;
inferenceTimeMs?: number;
/**
* Number of frames for video generations (> 1 means this is a video clip).
* Only set for project-file video generations where num_frames > 1.
*/
numFrames?: number;
imagePaths?: string[];
/** SHA-256 of a filesystem image, used to synchronize tags across exact copies. */
contentHash?: string;
httpPreviewUrls?: string[];
/** Where this generation was found */
sourceInfo?: SourceInfo;
}
export type IndexedGeneration = GenerationMetadata;
// ═══════════════════════════════════════════════════════════════
// Search Results (Structured Output for draw-things-chat)
// ═══════════════════════════════════════════════════════════════
/**
* Match type indicates how the result was found
*/
export type MatchType = 'exact' | 'visual' | 'hybrid' | 'reranked';
/**
* A single generation match with score and match details
*/
export interface GenerationMatch {
/** Original prompt used for generation */
prompt: string;
/** Negative prompt if available */
negativePrompt?: string;
/** Model used */
model: string;
/** LoRAs used (as strings for display) */
loras?: string[];
/** User-managed labels */
tags?: string[];
/** Generation seed */
seed?: number;
/** Seed selection mode */
seedMode?: string;
/** Diffusion shift */
shift?: number;
/** Image-to-image denoise strength */
strength?: number;
/** Generation mode */
mode?: string;
/** Sampling algorithm */
sampler?: string;
/** Number of steps */
steps?: number;
/** CFG scale */
cfgScale?: number;
/** Image dimensions */
width?: number;
height?: number;
/** Paths to generated images */
imagePaths: string[];
/** Exact image reference whose multimodal embedding produced this match. */
multimodalImageRef?: string;
/** HTTP preview URLs for thumbnails */
httpPreviewUrls?: string[];
/** Where this generation was found */
sourceInfo?: SourceInfo;
/** Generation timestamp */
timestamp?: string;
latitude?: number;
longitude?: number;
lensModel?: string;
exposureTime?: string;
fNumber?: number;
iso?: number;
exposureCompensation?: number;
focalLength?: number;
focalLength35mm?: number;
exposureProgram?: string;
meteringMode?: string;
whiteBalance?: string;
flash?: string;
orientation?: string;
exposureMode?: string;
/** Match score (0-100) */
matchScore: number;
/** How this result was matched */
matchType: MatchType;
/** Combined Qwen multimodal score on the 0-100 result scale */
multimodalScore?: number;
/** Unrounded Qwen cosine similarity used only to order multimodal results. */
rankingSimilarity?: number;
/** Unscaled native reranker score used only to order reranked results. */
rerankingScore?: number;
/** Qwen image-to-image score on the 0-100 result scale */
visualScore?: number;
/** Qwen text-to-image score on the 0-100 result scale */
semanticScore?: number;
/** Exact/metadata score component on the 0-100 result scale */
exactScore?: number;
/** Query media that produced a visual or hybrid result */
queryMedia?: {
notation?: string;
path?: string;
mediaKind?: string;
};
/** Which part of the query matched */
matchedTerms?: string[];
/** Number of frames for video generations (> 1 means video). Only set for project-file video generations. */
numFrames?: number;
/** SHA-256 of the source image bytes, used for exact identity and deduplication. */
contentHash?: string;
}
/**
* Image result for UI display (compatible with brave_image_search style)
*/
export interface ImageResult {
/** Full path to image file */
path: string;
/** Thumbnail path if available */
thumbnailPath?: string;
/** HTTP preview URL if available */
httpPreviewUrl?: string;
/** The prompt that generated this image */
prompt: string;
/** Model used */
model: string;
/** Match type for visual distinction */
matchType: MatchType;
/** Match score */
score: number;
/** Generation timestamp */
timestamp?: string;
}
/**
* Complete search result (structured for draw-things-chat)
*/
export interface DrawThingsSearchResult {
/** Original search query */
query: string;
/** Total number of results found */
totalFound: number;
/** Search took this many milliseconds */
searchTimeMs: number;
/**
* Volltreffer: Exact, fuzzy, or partial keyword matches
* High confidence - prompt contains query terms
*/
exactMatches: GenerationMatch[];
/**
* Beifang: Semantically similar results
* Lower confidence - thematically related
* Only populated if embedding model available
*/
semanticMatches: GenerationMatch[];
/**
* Flattened image list for UI display
* Compatible with brave_image_search result format
*/
imageResults: ImageResult[];
/** Whether semantic search was used */
semanticSearchEnabled: boolean;
/** Whether Qwen multimodal search was enabled */
multimodalSearchEnabled?: boolean;
/** Summary for chat context */
summary: string;
}
// ═══════════════════════════════════════════════════════════════
// Internal Types
// ═══════════════════════════════════════════════════════════════
/**
* Parsed document result (internal)
*/
export interface ParsedDocument {
content: string;
metadata: {
title?: string;
format?: string;
generationCount?: number;
generations?: GenerationMetadata[];
hasMetadata?: boolean;
path?: string;
prompt?: string;
model?: string;
loras?: Array<{ model: string; weight: number }>;
[key: string]: any;
};
}
/**
* Indexed data cache
*/
export interface IndexedData {
generations: GenerationMetadata[];
images: ImageInfo[];
timestamp: number;
}
/**
* Image file info (internal)
*/
export interface ImageInfo {
path: string;
hasMetadata: boolean;
metadata?: GenerationMetadata;
vlmAnalysis?: string;
}
export type DocumentFormat = 'png' | 'jpg' | 'jpeg' | 'tga' | 'bmp' | 'psd' | 'gif' | 'hdr' | 'pic' | 'ppm' | 'pgm' | 'unknown';