browser-visual-search 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export { embedImage, embedBatch } from './embedding/index.js';
2
2
  export { segmentImage } from './segmentation/index.js';
3
- export { buildIndex, loadIndex } from './search/index.js';
3
+ export { buildFromDirectory } from './search-index/build-from-directory.js';
4
+ export { indexExists, openIndex } from './search-index/index.js';
4
5
  export type { BBox, IndexedImage, IndexedImageSegment, SearchOptions, SearchResult, Segment, VisualSearchIndex } from './types.js';
5
- export type { BuildOptions, BuildProgress } from './search/build-index.js';
6
- export type { LoadIndexOptions } from './search/load-index.js';
6
+ export type { BuildFromDirectoryOptions, BuildFromDirectoryProgress } from './search-index/build-from-directory.js';
7
+ export type { BuildIndexOptions, LoadIndexOptions } from './search-index/index.js';
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE1D,YAAY,EACV,IAAI,EACJ,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,OAAO,EACP,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,YAAY,EACZ,aAAa,EACd,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EACV,gBAAgB,EACjB,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEjE,YAAY,EACV,IAAI,EACJ,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,OAAO,EACP,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,yBAAyB,EACzB,0BAA0B,EAC3B,MAAM,wCAAwC,CAAC;AAEhD,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { embedImage, embedBatch } from './embedding/index.js';
2
2
  export { segmentImage } from './segmentation/index.js';
3
- export { buildIndex, loadIndex } from './search/index.js';
3
+ export { buildFromDirectory } from './search-index/build-from-directory.js';
4
+ export { indexExists, openIndex } from './search-index/index.js';
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type BuildIndexOptions } from './index.js';
2
+ import type { VisualSearchIndex } from '../types.js';
3
+ export interface BuildFromDirectoryOptions extends BuildIndexOptions {
4
+ forceReindex?: boolean;
5
+ onProgress?: (progress: BuildFromDirectoryProgress) => void;
6
+ }
7
+ export type BuildFromDirectoryProgress = {
8
+ phase: 'loading' | 'scanning' | 'saving' | 'done';
9
+ } | {
10
+ phase: 'indexing';
11
+ total: number;
12
+ completed: number;
13
+ currentFile?: string;
14
+ };
15
+ export declare const buildFromDirectory: (dirHandle: FileSystemDirectoryHandle, opts: BuildFromDirectoryOptions) => Promise<VisualSearchIndex>;
16
+ //# sourceMappingURL=build-from-directory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-from-directory.d.ts","sourceRoot":"","sources":["../../src/search-index/build-from-directory.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyC,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,KAAK,EAAqC,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAExF,MAAM,WAAW,yBAA0B,SAAQ,iBAAiB;IAElE,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,0BAA0B,KAAK,IAAI,CAAC;CAE7D;AAED,MAAM,MAAM,0BAA0B,GAClC;IAAE,KAAK,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAA;CAAE,GACrD;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AA8BlF,eAAO,MAAM,kBAAkB,GAC7B,WAAW,yBAAyB,EACpC,MAAM,yBAAyB,KAC9B,OAAO,CAAC,iBAAiB,CAgG3B,CAAA"}
@@ -0,0 +1,99 @@
1
+ import { embedBatch } from '../embedding/embed.js';
2
+ import { segmentImage } from '../segmentation/index.js';
3
+ import { createIndex, openIndex, EMBEDDING_DIM } from './index.js';
4
+ const collectImages = async (dirHandle, path = '') => {
5
+ const images = [];
6
+ const entries = dirHandle.entries();
7
+ for await (const [name, handle] of entries) {
8
+ const fullPath = path ? `${path}/${name}` : name;
9
+ if (handle.kind === 'file') {
10
+ const ext = name.toLowerCase().split('.').pop();
11
+ if (['jpg', 'jpeg', 'png', 'webp'].includes(ext ?? '')) {
12
+ const file = await handle.getFile();
13
+ images.push({ id: fullPath, file });
14
+ }
15
+ }
16
+ else if (handle.kind === 'directory') {
17
+ images.push(...await collectImages(handle, fullPath));
18
+ }
19
+ }
20
+ return images;
21
+ };
22
+ export const buildFromDirectory = async (dirHandle, opts) => {
23
+ const { onProgress, forceReindex } = opts;
24
+ // 1. Try to load existing index
25
+ onProgress?.({ phase: 'loading' });
26
+ let existingImages = [];
27
+ let existingEmbeddings = new Float32Array(0);
28
+ try {
29
+ const existing = await openIndex(dirHandle, opts);
30
+ existingImages = [...existing.images];
31
+ existingEmbeddings = existing.embeddings;
32
+ ;
33
+ }
34
+ catch {
35
+ // No index yet — start fresh
36
+ }
37
+ // 2. Scan directory
38
+ onProgress?.({ phase: 'scanning' });
39
+ const allImages = await collectImages(dirHandle);
40
+ const allImageIds = new Set(allImages.map(img => img.id));
41
+ // 3. Prune images no longer on disk
42
+ const keptImages = existingImages.filter(img => allImageIds.has(img.imageId));
43
+ // 4. Determine which images need indexing
44
+ const indexedIds = new Set(keptImages.map(img => img.imageId));
45
+ const toIndex = forceReindex
46
+ ? allImages
47
+ : allImages.filter(img => !indexedIds.has(img.id));
48
+ // 5. Index new images
49
+ const newImages = [];
50
+ const newEmbeddings = [];
51
+ let nextRow = 0;
52
+ for (let i = 0; i < toIndex.length; i++) {
53
+ const input = toIndex[i];
54
+ onProgress?.({ phase: 'indexing', total: toIndex.length, completed: i, currentFile: input.id });
55
+ const detections = await segmentImage(input.file, opts);
56
+ const bitmap = await createImageBitmap(input.file);
57
+ const embeddings = await embedBatch(bitmap, detections.map(d => d.bbox), opts);
58
+ bitmap.close();
59
+ const segments = detections.map((det, j) => ({
60
+ bbox: det.bbox,
61
+ area: det.area,
62
+ embeddingRow: nextRow++,
63
+ }));
64
+ newImages.push({ imageId: input.id, indexedAt: new Date().toISOString(), segments });
65
+ newEmbeddings.push(...embeddings);
66
+ }
67
+ // 6. Merge kept + new
68
+ // Re-map embeddingRows for kept images, then append new
69
+ const mergedImages = [];
70
+ const mergedEmbeddingVecs = [];
71
+ let row = 0;
72
+ const baseImages = forceReindex ? [] : keptImages;
73
+ for (const img of baseImages) {
74
+ const remappedSegments = img.segments.map(seg => {
75
+ const vec = existingEmbeddings.subarray(seg.embeddingRow * EMBEDDING_DIM, seg.embeddingRow * EMBEDDING_DIM + EMBEDDING_DIM);
76
+ mergedEmbeddingVecs.push(new Float32Array(vec));
77
+ return { ...seg, embeddingRow: row++ };
78
+ });
79
+ mergedImages.push({ ...img, segments: remappedSegments });
80
+ }
81
+ for (const img of newImages) {
82
+ const remappedSegments = img.segments.map(seg => ({
83
+ ...seg,
84
+ embeddingRow: row++,
85
+ }));
86
+ mergedImages.push({ ...img, segments: remappedSegments });
87
+ }
88
+ mergedEmbeddingVecs.push(...newEmbeddings);
89
+ // Flatten into a single Float32Array
90
+ const mergedEmbeddings = new Float32Array(mergedEmbeddingVecs.length * EMBEDDING_DIM);
91
+ mergedEmbeddingVecs.forEach((vec, i) => mergedEmbeddings.set(vec, i * EMBEDDING_DIM));
92
+ // 7. Serialize
93
+ onProgress?.({ phase: 'saving' });
94
+ const index = createIndex(mergedImages, mergedEmbeddings, dirHandle, opts);
95
+ await index.save();
96
+ onProgress?.({ phase: 'done' });
97
+ return index;
98
+ };
99
+ //# sourceMappingURL=build-from-directory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-from-directory.js","sourceRoot":"","sources":["../../src/search-index/build-from-directory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { IndexedImage, VisualSearchIndex } from '../types.js';
2
+ export declare const EMBEDDING_DIM = 512;
3
+ export interface LoadIndexOptions {
4
+ embedderUrl: string;
5
+ executionProviders?: string[];
6
+ create?: boolean;
7
+ }
8
+ export interface BuildIndexOptions extends LoadIndexOptions {
9
+ segmenterUrl: string;
10
+ }
11
+ export declare const indexExists: (dirHandle: FileSystemDirectoryHandle) => Promise<boolean>;
12
+ export declare const createIndex: (images: IndexedImage[], embeddings: Float32Array, dirHandle: FileSystemDirectoryHandle, opts: LoadIndexOptions | BuildIndexOptions) => VisualSearchIndex;
13
+ /**
14
+ * Load an existing visual search index from a directory handle.
15
+ * @param dirHandle The directory handle containing index.json and embeddings.bin
16
+ * @returns The loaded index
17
+ */
18
+ export declare const openIndex: (dirHandle: FileSystemDirectoryHandle, opts: LoadIndexOptions | BuildIndexOptions) => Promise<VisualSearchIndex>;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/search-index/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,YAAY,EAIZ,iBAAiB,EAClB,MAAM,aAAa,CAAC;AAMrB,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC,MAAM,WAAW,gBAAgB;IAE/B,WAAW,EAAE,MAAM,CAAC;IAEpB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE9B,MAAM,CAAC,EAAE,OAAO,CAAC;CAElB;AAED,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IAEzD,YAAY,EAAE,MAAM,CAAC;CAEtB;AAsDD,eAAO,MAAM,WAAW,GACtB,WAAW,yBAAyB,KACnC,OAAO,CAAC,OAAO,CAYjB,CAAA;AAED,eAAO,MAAM,WAAW,GACtB,QAAQ,YAAY,EAAE,EACtB,YAAY,YAAY,EACxB,WAAW,yBAAyB,EACpC,MAAM,gBAAgB,GAAG,iBAAiB,KACzC,iBAgEF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,GACpB,WAAW,yBAAyB,EACpC,MAAM,gBAAgB,GAAG,iBAAiB,KACzC,OAAO,CAAC,iBAAiB,CAwB3B,CAAA"}
@@ -0,0 +1,123 @@
1
+ import { embedBatch, embedImage } from '../embedding/embed.js';
2
+ import { segmentImage } from '../segmentation/segment.js';
3
+ const DIR_NAME = '.visual-search';
4
+ const INDEX_FILE = 'index.json';
5
+ const EMBED_FILE = 'embeddings.bin';
6
+ export const EMBEDDING_DIM = 512;
7
+ const nearestNeighbours = (query, embeddings, images, topK = 20) => {
8
+ const results = [];
9
+ for (const img of images) {
10
+ for (const seg of img.segments) {
11
+ const offset = seg.embeddingRow * EMBEDDING_DIM;
12
+ let score = 0;
13
+ for (let k = 0; k < EMBEDDING_DIM; k++)
14
+ score += query[k] * embeddings[offset + k];
15
+ results.push({ imageId: img.imageId, bbox: seg.bbox, area: seg.area, score });
16
+ }
17
+ }
18
+ return results
19
+ .sort((a, b) => b.score - a.score)
20
+ .slice(0, topK);
21
+ };
22
+ const appendEmbeddings = (current, toAdd) => {
23
+ const totalFloats = current.length + toAdd.reduce((n, c) => n + c.length, 0);
24
+ const next = new Float32Array(totalFloats);
25
+ next.set(current, 0);
26
+ let offset = current.length;
27
+ for (const chunk of toAdd) {
28
+ next.set(chunk, offset);
29
+ offset += chunk.length;
30
+ }
31
+ return next;
32
+ };
33
+ export const indexExists = async (dirHandle) => {
34
+ try {
35
+ const vsDir = await dirHandle.getDirectoryHandle(DIR_NAME);
36
+ await vsDir.getFileHandle(INDEX_FILE);
37
+ await vsDir.getFileHandle(EMBED_FILE);
38
+ return true;
39
+ }
40
+ catch (err) {
41
+ if (err instanceof DOMException && err.name === 'NotFoundError') {
42
+ return false;
43
+ }
44
+ throw err; // re-throw unexpected errors (e.g. SecurityError, TypeError)
45
+ }
46
+ };
47
+ export const createIndex = (images, embeddings, dirHandle, opts) => {
48
+ const imageMap = new Map(images.map(img => [img.imageId, img]));
49
+ let _embeddings = embeddings;
50
+ return {
51
+ dirHandle,
52
+ images,
53
+ get embeddings() { return _embeddings; },
54
+ async addToIndex(image, id) {
55
+ if (!('segmenterUrl' in opts))
56
+ throw new Error('addToIndex requires a segmenter model');
57
+ const detections = await segmentImage(image, opts);
58
+ const bitmap = await createImageBitmap(image);
59
+ const vecs = await embedBatch(bitmap, detections.map(d => d.bbox), opts);
60
+ bitmap.close();
61
+ const nextRow = _embeddings.length / EMBEDDING_DIM;
62
+ const segments = detections.map((det, j) => ({
63
+ bbox: det.bbox,
64
+ area: det.area,
65
+ embeddingRow: nextRow + j
66
+ }));
67
+ images.push({
68
+ imageId: id,
69
+ indexedAt: new Date().toISOString(),
70
+ segments
71
+ });
72
+ _embeddings = appendEmbeddings(_embeddings, vecs);
73
+ },
74
+ getImage(imageId) {
75
+ return imageMap.get(imageId);
76
+ },
77
+ async query(file, bbox, options) {
78
+ const queryEmbedding = await embedImage(file, bbox, {
79
+ embedderUrl: opts.embedderUrl,
80
+ executionProviders: opts.executionProviders,
81
+ });
82
+ return nearestNeighbours(queryEmbedding, _embeddings, images, options?.topK);
83
+ },
84
+ async save() {
85
+ const vsDir = await dirHandle.getDirectoryHandle(DIR_NAME, { create: true });
86
+ const jsonHandle = await vsDir.getFileHandle('index.json', { create: true });
87
+ const jsonWriter = await jsonHandle.createWritable();
88
+ await jsonWriter.write(JSON.stringify({ version: 1, updatedAt: new Date().toISOString(), images }, null, 2));
89
+ await jsonWriter.close();
90
+ const binHandle = await vsDir.getFileHandle('embeddings.bin', { create: true });
91
+ const binWriter = await binHandle.createWritable();
92
+ await binWriter.write(_embeddings.buffer);
93
+ await binWriter.close();
94
+ }
95
+ };
96
+ };
97
+ /**
98
+ * Load an existing visual search index from a directory handle.
99
+ * @param dirHandle The directory handle containing index.json and embeddings.bin
100
+ * @returns The loaded index
101
+ */
102
+ export const openIndex = async (dirHandle, opts) => {
103
+ if (!await indexExists(dirHandle)) {
104
+ if (opts.create)
105
+ return createIndex([], new Float32Array(0), dirHandle, opts);
106
+ throw new Error(`No index found in directory`);
107
+ }
108
+ const vsDir = await dirHandle.getDirectoryHandle(DIR_NAME);
109
+ const jsonHandle = await vsDir.getFileHandle(INDEX_FILE);
110
+ const jsonFile = await jsonHandle.getFile();
111
+ const jsonText = await jsonFile.text();
112
+ const { images } = JSON.parse(jsonText);
113
+ const binHandle = await vsDir.getFileHandle(EMBED_FILE);
114
+ const binFile = await binHandle.getFile();
115
+ const binBuffer = await binFile.arrayBuffer();
116
+ const embeddings = new Float32Array(binBuffer);
117
+ // Validate length
118
+ const totalSegments = images.reduce((n, img) => n + img.segments.length, 0);
119
+ if (embeddings.length !== totalSegments * EMBEDDING_DIM)
120
+ throw new Error(`embeddings.bin length mismatch: expected ${totalSegments * EMBEDDING_DIM}, got ${embeddings.length}`);
121
+ return createIndex(images, embeddings, dirHandle, opts);
122
+ };
123
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/search-index/index.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -15,11 +15,13 @@ export interface IndexedImage {
15
15
  segments: IndexedImageSegment[];
16
16
  }
17
17
  export interface VisualSearchIndex {
18
+ readonly dirHandle: FileSystemDirectoryHandle;
18
19
  readonly images: ReadonlyArray<IndexedImage>;
19
20
  readonly embeddings: Float32Array;
20
- readonly dirHandle: FileSystemDirectoryHandle;
21
- query(file: File, bbox?: BBox, options?: SearchOptions): Promise<SearchResult[]>;
21
+ addToIndex(image: File, id: string): Promise<void>;
22
22
  getImage(imageId: string): IndexedImage | undefined;
23
+ query(file: File, bbox?: BBox, options?: SearchOptions): Promise<SearchResult[]>;
24
+ save(): Promise<void>;
23
25
  }
24
26
  export interface SearchOptions {
25
27
  topK?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEpD,MAAM,WAAW,OAAO;IAEtB,IAAI,EAAE,IAAI,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,SAAS,EAAE,YAAY,CAAC;CAEzB;AAED,MAAM,WAAW,mBAAmB;IAElC,IAAI,EAAE,IAAI,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,YAAY,EAAE,MAAM,CAAC;CAEtB;AAED,MAAM,WAAW,YAAY;IAE3B,OAAO,EAAE,MAAM,CAAC;IAEhB,SAAS,EAAE,MAAM,CAAC;IAElB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CAEjC;AAED,MAAM,WAAW,iBAAiB;IAEhC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IAE7C,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAElC,QAAQ,CAAC,SAAS,EAAE,yBAAyB,CAAC;IAE9C,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAEjF,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;CAErD;AAED,MAAM,WAAW,aAAa;IAE5B,IAAI,CAAC,EAAE,MAAM,CAAC;CAEf;AAED,MAAM,WAAW,YAAY;IAE3B,OAAO,EAAE,MAAM,CAAC;IAEhB,IAAI,EAAE,IAAI,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;CAEf"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEpD,MAAM,WAAW,OAAO;IAEtB,IAAI,EAAE,IAAI,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,SAAS,EAAE,YAAY,CAAC;CAEzB;AAED,MAAM,WAAW,mBAAmB;IAElC,IAAI,EAAE,IAAI,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,YAAY,EAAE,MAAM,CAAC;CAEtB;AAED,MAAM,WAAW,YAAY;IAE3B,OAAO,EAAE,MAAM,CAAC;IAEhB,SAAS,EAAE,MAAM,CAAC;IAElB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CAEjC;AAED,MAAM,WAAW,iBAAiB;IAEhC,QAAQ,CAAC,SAAS,EAAE,yBAAyB,CAAC;IAE9C,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IAE7C,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAElC,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAEpD,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAEjF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAEvB;AAED,MAAM,WAAW,aAAa;IAE5B,IAAI,CAAC,EAAE,MAAM,CAAC;CAEf;AAED,MAAM,WAAW,YAAY;IAE3B,OAAO,EAAE,MAAM,CAAC;IAEhB,IAAI,EAAE,IAAI,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;CAEf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-visual-search",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "In-browser visual search powered by FastSAM, CLIP and onnxruntime-web.",
5
5
  "type": "module",
6
6
  "sideEffects": false,