@coreviz/sdk 1.0.19 → 1.1.1
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/README.md +430 -83
- package/dist/coreviz.d.ts +205 -0
- package/dist/coreviz.js +236 -8
- package/dist/coreviz.native.d.ts +126 -0
- package/dist/coreviz.native.js +139 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.native.d.ts +2 -2
- package/package.json +1 -1
package/dist/coreviz.d.ts
CHANGED
|
@@ -1,6 +1,199 @@
|
|
|
1
1
|
export interface CoreVizConfig {
|
|
2
2
|
apiKey?: string;
|
|
3
3
|
token?: string;
|
|
4
|
+
/** Override the API base URL (default: https://lab.coreviz.io) */
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface UserContext {
|
|
8
|
+
userId: string;
|
|
9
|
+
email: string;
|
|
10
|
+
name: string;
|
|
11
|
+
organizationId: string;
|
|
12
|
+
organizationName: string | null;
|
|
13
|
+
}
|
|
14
|
+
export interface Collection {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
icon?: string;
|
|
18
|
+
type: string;
|
|
19
|
+
organizationId: string;
|
|
20
|
+
}
|
|
21
|
+
export interface MediaObject {
|
|
22
|
+
id: string;
|
|
23
|
+
type: string;
|
|
24
|
+
label: string;
|
|
25
|
+
}
|
|
26
|
+
export interface MediaFrame {
|
|
27
|
+
id: string;
|
|
28
|
+
timestamp: number;
|
|
29
|
+
blob: string;
|
|
30
|
+
objects: MediaObject[];
|
|
31
|
+
}
|
|
32
|
+
export interface Media {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
type: 'image' | 'video' | 'folder';
|
|
36
|
+
blob: string | null;
|
|
37
|
+
path: string;
|
|
38
|
+
width?: number;
|
|
39
|
+
height?: number;
|
|
40
|
+
sizeBytes?: number;
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
frames?: MediaFrame[];
|
|
43
|
+
createdAt?: string;
|
|
44
|
+
_score?: number;
|
|
45
|
+
}
|
|
46
|
+
export interface Folder {
|
|
47
|
+
id: string;
|
|
48
|
+
name: string;
|
|
49
|
+
path: string;
|
|
50
|
+
collectionId: string;
|
|
51
|
+
}
|
|
52
|
+
export interface BrowseOptions {
|
|
53
|
+
path?: string;
|
|
54
|
+
limit?: number;
|
|
55
|
+
offset?: number;
|
|
56
|
+
type?: 'image' | 'video' | 'folder' | 'all';
|
|
57
|
+
dateFrom?: string;
|
|
58
|
+
dateTo?: string;
|
|
59
|
+
sortBy?: string;
|
|
60
|
+
sortDirection?: 'asc' | 'desc';
|
|
61
|
+
tagFilters?: Record<string, string[]>;
|
|
62
|
+
/** Text / semantic search query (triggers scored mode on the server) */
|
|
63
|
+
q?: string;
|
|
64
|
+
/** Object ID to find visually similar media within this collection */
|
|
65
|
+
similarToObjectId?: string;
|
|
66
|
+
/** Vision model used for similarity scoring */
|
|
67
|
+
similarToObjectModel?: string;
|
|
68
|
+
/** Comma-separated tag label filter */
|
|
69
|
+
tags?: string;
|
|
70
|
+
/** Filter to a specific media item ID */
|
|
71
|
+
mediaId?: string;
|
|
72
|
+
/** Filter to a specific cluster ID */
|
|
73
|
+
clusterId?: string;
|
|
74
|
+
/** When true, list all descendants recursively (flattened view) */
|
|
75
|
+
recursive?: boolean;
|
|
76
|
+
}
|
|
77
|
+
export interface BrowseResult {
|
|
78
|
+
media: Media[];
|
|
79
|
+
pagination: {
|
|
80
|
+
total: number;
|
|
81
|
+
limit: number;
|
|
82
|
+
offset: number;
|
|
83
|
+
hasMore: boolean;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export interface SearchResult {
|
|
87
|
+
mediaId: string;
|
|
88
|
+
mediaName: string;
|
|
89
|
+
mediaType: string;
|
|
90
|
+
blobUrl: string;
|
|
91
|
+
objects: MediaObject[];
|
|
92
|
+
rank: number;
|
|
93
|
+
caption?: string;
|
|
94
|
+
}
|
|
95
|
+
export interface SearchOptions {
|
|
96
|
+
limit?: number;
|
|
97
|
+
/** Pass the organization ID directly to skip the /api/me round-trip. */
|
|
98
|
+
organizationId?: string;
|
|
99
|
+
}
|
|
100
|
+
export interface FolderUpdateOptions {
|
|
101
|
+
name?: string;
|
|
102
|
+
metadata?: Record<string, unknown>;
|
|
103
|
+
}
|
|
104
|
+
export interface CollectionUpdateOptions {
|
|
105
|
+
name?: string;
|
|
106
|
+
icon?: string;
|
|
107
|
+
}
|
|
108
|
+
export interface DeleteVersionResult {
|
|
109
|
+
deletedId: string;
|
|
110
|
+
promotedId: string | null;
|
|
111
|
+
}
|
|
112
|
+
export interface SimilarityOptions {
|
|
113
|
+
limit?: number;
|
|
114
|
+
model?: string;
|
|
115
|
+
}
|
|
116
|
+
export interface UploadOptions {
|
|
117
|
+
/** Target collection ID */
|
|
118
|
+
collectionId: string;
|
|
119
|
+
/** ltree folder path to upload into (e.g. "collectionId.folderId"). Defaults to collection root. */
|
|
120
|
+
path?: string;
|
|
121
|
+
/** Override the file name stored in CoreViz */
|
|
122
|
+
name?: string;
|
|
123
|
+
}
|
|
124
|
+
export interface UploadResult {
|
|
125
|
+
mediaId: string;
|
|
126
|
+
url: string;
|
|
127
|
+
message: string;
|
|
128
|
+
}
|
|
129
|
+
export interface CollectionsNamespace {
|
|
130
|
+
/**
|
|
131
|
+
* List all collections in an organization.
|
|
132
|
+
* @param organizationId - If omitted the SDK resolves it via /api/me (one extra round-trip).
|
|
133
|
+
*/
|
|
134
|
+
list(organizationId?: string): Promise<Collection[]>;
|
|
135
|
+
/** Get a single collection by ID */
|
|
136
|
+
get(collectionId: string): Promise<Collection>;
|
|
137
|
+
/** Create a new collection in the user's current organization */
|
|
138
|
+
create(name: string, icon?: string): Promise<Collection>;
|
|
139
|
+
/** Update a collection's name or icon */
|
|
140
|
+
update(collectionId: string, updates: CollectionUpdateOptions): Promise<Collection>;
|
|
141
|
+
}
|
|
142
|
+
export interface MediaNamespace {
|
|
143
|
+
/** Browse/list media items in a collection folder */
|
|
144
|
+
browse(collectionId: string, options?: BrowseOptions): Promise<BrowseResult>;
|
|
145
|
+
/** Semantic search across all org media */
|
|
146
|
+
search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
147
|
+
/** Get full details for a media item */
|
|
148
|
+
get(mediaId: string): Promise<Media>;
|
|
149
|
+
/** Rename a media item */
|
|
150
|
+
rename(mediaId: string, name: string): Promise<Media>;
|
|
151
|
+
/** Move a media item to a new ltree destination path */
|
|
152
|
+
move(mediaId: string, destinationPath: string): Promise<{
|
|
153
|
+
id: string;
|
|
154
|
+
newPath: string;
|
|
155
|
+
}>;
|
|
156
|
+
/** Permanently delete a media item */
|
|
157
|
+
delete(mediaId: string): Promise<void>;
|
|
158
|
+
/** Add a tag group+value to a media item */
|
|
159
|
+
addTag(mediaId: string, label: string, value: string): Promise<void>;
|
|
160
|
+
/** Remove a specific tag value from a media item */
|
|
161
|
+
removeTag(mediaId: string, label: string, value: string): Promise<void>;
|
|
162
|
+
/** Remove an entire tag group (all values) from a media item */
|
|
163
|
+
removeTagGroup(mediaId: string, label: string): Promise<void>;
|
|
164
|
+
/** Rename a tag group across a media item */
|
|
165
|
+
renameTagGroup(mediaId: string, oldLabel: string, newLabel: string): Promise<void>;
|
|
166
|
+
/** List all versions of a media item */
|
|
167
|
+
listVersions(mediaId: string): Promise<Media[]>;
|
|
168
|
+
/** Delete a specific version; returns the promoted active version ID if applicable */
|
|
169
|
+
deleteVersion(rootMediaId: string, versionId: string): Promise<DeleteVersionResult>;
|
|
170
|
+
/** Mark a version as the active/current version */
|
|
171
|
+
selectVersion(versionId: string): Promise<void>;
|
|
172
|
+
/** Find visually similar media using an object ID */
|
|
173
|
+
findSimilar(collectionId: string, objectId: string, options?: SimilarityOptions): Promise<BrowseResult>;
|
|
174
|
+
/**
|
|
175
|
+
* Upload a photo or video to CoreViz.
|
|
176
|
+
* - Node.js: pass a local file path string
|
|
177
|
+
* - Browser: pass a File or Blob object
|
|
178
|
+
*/
|
|
179
|
+
upload(file: string | File | Blob, options: UploadOptions): Promise<UploadResult>;
|
|
180
|
+
}
|
|
181
|
+
export interface FoldersNamespace {
|
|
182
|
+
/**
|
|
183
|
+
* Create a folder inside a collection.
|
|
184
|
+
* @param reuse - When true, return the existing folder if one with the same name already exists at that path (upsert).
|
|
185
|
+
*/
|
|
186
|
+
create(collectionId: string, name: string, path?: string, reuse?: boolean): Promise<Folder>;
|
|
187
|
+
/** Get a folder by ID */
|
|
188
|
+
get(folderId: string): Promise<Folder>;
|
|
189
|
+
/** Update a folder's name or metadata */
|
|
190
|
+
update(folderId: string, updates: FolderUpdateOptions): Promise<Folder>;
|
|
191
|
+
/** Delete a folder and all its contents */
|
|
192
|
+
delete(folderId: string): Promise<void>;
|
|
193
|
+
}
|
|
194
|
+
export interface TagsNamespace {
|
|
195
|
+
/** Aggregate all tag groups + values across a collection */
|
|
196
|
+
list(collectionId: string): Promise<Record<string, string[]>>;
|
|
4
197
|
}
|
|
5
198
|
export interface DescribeOptions {
|
|
6
199
|
}
|
|
@@ -35,8 +228,20 @@ export interface GenerateOptions {
|
|
|
35
228
|
export declare class CoreViz {
|
|
36
229
|
private apiKey?;
|
|
37
230
|
private token?;
|
|
231
|
+
private _baseUrl;
|
|
232
|
+
private _orgIdCache;
|
|
233
|
+
collections: CollectionsNamespace;
|
|
234
|
+
media: MediaNamespace;
|
|
235
|
+
folders: FoldersNamespace;
|
|
236
|
+
tags: TagsNamespace;
|
|
38
237
|
constructor(config?: CoreVizConfig);
|
|
39
238
|
private getHeaders;
|
|
239
|
+
/** Resolve the current user's org ID (cached after first call) */
|
|
240
|
+
private _me;
|
|
241
|
+
/** GET request helper for management endpoints */
|
|
242
|
+
private _fetch;
|
|
243
|
+
/** Non-GET request helper for management endpoints */
|
|
244
|
+
private _fetchMethod;
|
|
40
245
|
private handleResponse;
|
|
41
246
|
describe(image: string, options?: DescribeOptions): Promise<string>;
|
|
42
247
|
edit(image: string, options: EditOptions): Promise<string>;
|
package/dist/coreviz.js
CHANGED
|
@@ -37,9 +37,207 @@ exports.CoreViz = void 0;
|
|
|
37
37
|
const resize_1 = require("./resize");
|
|
38
38
|
class CoreViz {
|
|
39
39
|
constructor(config = {}) {
|
|
40
|
+
this._orgIdCache = null;
|
|
40
41
|
this.apiKey = config.apiKey || (typeof process !== 'undefined' ? process.env.COREVIZ_API_KEY : undefined);
|
|
41
42
|
this.token = config.token;
|
|
43
|
+
this._baseUrl = config.baseUrl || 'https://lab.coreviz.io';
|
|
44
|
+
// ── Management namespaces ────────────────────────────────────────────
|
|
45
|
+
this.collections = {
|
|
46
|
+
list: async (organizationId) => {
|
|
47
|
+
const orgId = organizationId || (await this._me()).organizationId;
|
|
48
|
+
const data = await this._fetch(`/api/organization/${orgId}/datasets`);
|
|
49
|
+
return Array.isArray(data) ? data : data.datasets ?? [];
|
|
50
|
+
},
|
|
51
|
+
get: async (collectionId) => {
|
|
52
|
+
const data = await this._fetch(`/api/dataset/${collectionId}`);
|
|
53
|
+
return data.dataset;
|
|
54
|
+
},
|
|
55
|
+
create: async (name, icon) => {
|
|
56
|
+
const { organizationId } = await this._me();
|
|
57
|
+
const data = await this._fetchMethod('POST', `/api/organization/${organizationId}/datasets`, {
|
|
58
|
+
name,
|
|
59
|
+
...(icon ? { icon } : {}),
|
|
60
|
+
});
|
|
61
|
+
return data.dataset;
|
|
62
|
+
},
|
|
63
|
+
update: async (collectionId, updates) => {
|
|
64
|
+
const data = await this._fetchMethod('PATCH', `/api/dataset/${collectionId}`, updates);
|
|
65
|
+
return data.dataset;
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
this.media = {
|
|
69
|
+
browse: async (collectionId, options = {}) => {
|
|
70
|
+
const params = new URLSearchParams();
|
|
71
|
+
if (options.path)
|
|
72
|
+
params.set('path', options.path);
|
|
73
|
+
if (options.limit != null)
|
|
74
|
+
params.set('limit', String(options.limit));
|
|
75
|
+
if (options.offset != null)
|
|
76
|
+
params.set('offset', String(options.offset));
|
|
77
|
+
if (options.type)
|
|
78
|
+
params.set('type', options.type);
|
|
79
|
+
if (options.dateFrom)
|
|
80
|
+
params.set('dateFrom', options.dateFrom);
|
|
81
|
+
if (options.dateTo)
|
|
82
|
+
params.set('dateTo', options.dateTo);
|
|
83
|
+
if (options.sortBy)
|
|
84
|
+
params.set('sortBy', options.sortBy);
|
|
85
|
+
if (options.sortDirection)
|
|
86
|
+
params.set('sortDirection', options.sortDirection);
|
|
87
|
+
if (options.tagFilters)
|
|
88
|
+
params.set('tagFilters', JSON.stringify(options.tagFilters));
|
|
89
|
+
if (options.q)
|
|
90
|
+
params.set('q', options.q);
|
|
91
|
+
if (options.similarToObjectId)
|
|
92
|
+
params.set('similarToObjectId', options.similarToObjectId);
|
|
93
|
+
if (options.similarToObjectModel)
|
|
94
|
+
params.set('similarToObjectModel', options.similarToObjectModel);
|
|
95
|
+
if (options.tags)
|
|
96
|
+
params.set('tags', options.tags);
|
|
97
|
+
if (options.mediaId)
|
|
98
|
+
params.set('mediaId', options.mediaId);
|
|
99
|
+
if (options.clusterId)
|
|
100
|
+
params.set('clusterId', options.clusterId);
|
|
101
|
+
if (options.recursive)
|
|
102
|
+
params.set('recursive', 'true');
|
|
103
|
+
const qs = params.toString();
|
|
104
|
+
return this._fetch(`/api/dataset/${collectionId}/media${qs ? `?${qs}` : ''}`);
|
|
105
|
+
},
|
|
106
|
+
search: async (query, options = {}) => {
|
|
107
|
+
const orgId = options.organizationId || (await this._me()).organizationId;
|
|
108
|
+
const params = new URLSearchParams({ q: query, organizationId: orgId });
|
|
109
|
+
if (options.limit != null)
|
|
110
|
+
params.set('limit', String(options.limit));
|
|
111
|
+
const data = await this._fetch(`/api/search?${params.toString()}`);
|
|
112
|
+
return (data.results || []).map((r) => ({
|
|
113
|
+
mediaId: r.media?.id,
|
|
114
|
+
mediaName: r.media?.name,
|
|
115
|
+
mediaType: r.media?.type,
|
|
116
|
+
blobUrl: r.blob,
|
|
117
|
+
objects: (r.objects || []).map((o) => ({ id: o.id, type: o.type, label: o.label })),
|
|
118
|
+
rank: r.rank,
|
|
119
|
+
caption: r.captions?.[0]?.text,
|
|
120
|
+
}));
|
|
121
|
+
},
|
|
122
|
+
get: async (mediaId) => {
|
|
123
|
+
const data = await this._fetch(`/api/media/${mediaId}`);
|
|
124
|
+
return data.media;
|
|
125
|
+
},
|
|
126
|
+
rename: async (mediaId, name) => {
|
|
127
|
+
const data = await this._fetchMethod('PATCH', `/api/media/${mediaId}`, { name });
|
|
128
|
+
return data.media;
|
|
129
|
+
},
|
|
130
|
+
move: async (mediaId, destinationPath) => {
|
|
131
|
+
return this._fetchMethod('PATCH', `/api/media/${mediaId}/move`, { destinationPath });
|
|
132
|
+
},
|
|
133
|
+
delete: async (mediaId) => {
|
|
134
|
+
await this._fetchMethod('DELETE', `/api/media/${mediaId}`);
|
|
135
|
+
},
|
|
136
|
+
addTag: async (mediaId, label, value) => {
|
|
137
|
+
await this._fetchMethod('POST', `/api/media/${mediaId}/tags`, { label, value });
|
|
138
|
+
},
|
|
139
|
+
removeTag: async (mediaId, label, value) => {
|
|
140
|
+
await this._fetchMethod('DELETE', `/api/media/${mediaId}/tags`, { label, value });
|
|
141
|
+
},
|
|
142
|
+
removeTagGroup: async (mediaId, label) => {
|
|
143
|
+
await this._fetchMethod('DELETE', `/api/media/${mediaId}/tags`, { label });
|
|
144
|
+
},
|
|
145
|
+
renameTagGroup: async (mediaId, oldLabel, newLabel) => {
|
|
146
|
+
await this._fetchMethod('PATCH', `/api/media/${mediaId}/tags`, { oldLabel, newLabel });
|
|
147
|
+
},
|
|
148
|
+
listVersions: async (mediaId) => {
|
|
149
|
+
const data = await this._fetch(`/api/media/${mediaId}/versions`);
|
|
150
|
+
return data.versions;
|
|
151
|
+
},
|
|
152
|
+
deleteVersion: async (rootMediaId, versionId) => {
|
|
153
|
+
return this._fetchMethod('DELETE', `/api/media/${rootMediaId}/versions?versionId=${versionId}`);
|
|
154
|
+
},
|
|
155
|
+
selectVersion: async (versionId) => {
|
|
156
|
+
await this._fetchMethod('PATCH', `/api/media/${versionId}/select-version`);
|
|
157
|
+
},
|
|
158
|
+
findSimilar: async (collectionId, objectId, options = {}) => {
|
|
159
|
+
const params = new URLSearchParams({ similarToObjectId: objectId });
|
|
160
|
+
if (options.limit != null)
|
|
161
|
+
params.set('limit', String(options.limit));
|
|
162
|
+
if (options.model)
|
|
163
|
+
params.set('similarToObjectModel', options.model);
|
|
164
|
+
return this._fetch(`/api/dataset/${collectionId}/media?${params.toString()}`);
|
|
165
|
+
},
|
|
166
|
+
upload: async (file, options) => {
|
|
167
|
+
const formData = new FormData();
|
|
168
|
+
formData.append('datasetId', options.collectionId);
|
|
169
|
+
if (options.path)
|
|
170
|
+
formData.append('path', options.path);
|
|
171
|
+
if (typeof file === 'string') {
|
|
172
|
+
// Node.js: treat as a file path — dynamic import fs to stay browser-compatible
|
|
173
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
174
|
+
const path = await Promise.resolve().then(() => __importStar(require('path')));
|
|
175
|
+
const buffer = fs.readFileSync(file);
|
|
176
|
+
const ext = path.extname(file).slice(1).toLowerCase();
|
|
177
|
+
const mimeTypes = {
|
|
178
|
+
jpg: 'image/jpeg', jpeg: 'image/jpeg', png: 'image/png',
|
|
179
|
+
gif: 'image/gif', webp: 'image/webp', heic: 'image/heic',
|
|
180
|
+
mp4: 'video/mp4', webm: 'video/webm', mov: 'video/quicktime',
|
|
181
|
+
};
|
|
182
|
+
const contentType = mimeTypes[ext] || 'application/octet-stream';
|
|
183
|
+
const fileName = options.name || path.basename(file);
|
|
184
|
+
const blob = new Blob([buffer], { type: contentType });
|
|
185
|
+
formData.append('file', blob, fileName);
|
|
186
|
+
if (!options.name)
|
|
187
|
+
formData.append('name', fileName);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
const fileName = options.name || (file instanceof File ? file.name : 'upload');
|
|
191
|
+
formData.append('file', file, fileName);
|
|
192
|
+
if (options.name)
|
|
193
|
+
formData.append('name', options.name);
|
|
194
|
+
}
|
|
195
|
+
// Build headers without Content-Type (let fetch set the multipart boundary)
|
|
196
|
+
const authHeaders = {};
|
|
197
|
+
if (this.token) {
|
|
198
|
+
authHeaders['Authorization'] = `Bearer ${this.token}`;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
authHeaders['x-api-key'] = this.apiKey || '';
|
|
202
|
+
}
|
|
203
|
+
const response = await fetch(`${this._baseUrl}/api/upload/multipart`, {
|
|
204
|
+
method: 'POST',
|
|
205
|
+
headers: authHeaders,
|
|
206
|
+
body: formData,
|
|
207
|
+
});
|
|
208
|
+
return this.handleResponse(response);
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
this.folders = {
|
|
212
|
+
create: async (collectionId, name, path, reuse) => {
|
|
213
|
+
const data = await this._fetchMethod('POST', '/api/folder', {
|
|
214
|
+
datasetId: collectionId,
|
|
215
|
+
name,
|
|
216
|
+
...(path ? { path } : {}),
|
|
217
|
+
...(reuse ? { reuse: true } : {}),
|
|
218
|
+
});
|
|
219
|
+
return data.folder;
|
|
220
|
+
},
|
|
221
|
+
get: async (folderId) => {
|
|
222
|
+
const data = await this._fetch(`/api/folder/${folderId}`);
|
|
223
|
+
return data.folder;
|
|
224
|
+
},
|
|
225
|
+
update: async (folderId, updates) => {
|
|
226
|
+
const data = await this._fetchMethod('PATCH', `/api/folder/${folderId}`, updates);
|
|
227
|
+
return data.folder;
|
|
228
|
+
},
|
|
229
|
+
delete: async (folderId) => {
|
|
230
|
+
await this._fetchMethod('DELETE', `/api/folder/${folderId}`);
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
this.tags = {
|
|
234
|
+
list: async (collectionId) => {
|
|
235
|
+
const data = await this._fetch(`/api/dataset/${collectionId}/tags`);
|
|
236
|
+
return data.tags;
|
|
237
|
+
},
|
|
238
|
+
};
|
|
42
239
|
}
|
|
240
|
+
// ── Private helpers ──────────────────────────────────────────────────────
|
|
43
241
|
getHeaders() {
|
|
44
242
|
const headers = {
|
|
45
243
|
'Content-Type': 'application/json',
|
|
@@ -47,17 +245,47 @@ class CoreViz {
|
|
|
47
245
|
if (this.token) {
|
|
48
246
|
headers['Authorization'] = `Bearer ${this.token}`;
|
|
49
247
|
}
|
|
50
|
-
else {
|
|
51
|
-
headers['x-api-key'] = this.apiKey
|
|
248
|
+
else if (this.apiKey) {
|
|
249
|
+
headers['x-api-key'] = this.apiKey;
|
|
52
250
|
}
|
|
251
|
+
// If neither is set, rely on session cookies (browser same-origin requests).
|
|
53
252
|
return headers;
|
|
54
253
|
}
|
|
254
|
+
/** Resolve the current user's org ID (cached after first call) */
|
|
255
|
+
async _me() {
|
|
256
|
+
const data = await this._fetch('/api/me');
|
|
257
|
+
if (!this._orgIdCache)
|
|
258
|
+
this._orgIdCache = data.organizationId;
|
|
259
|
+
return data;
|
|
260
|
+
}
|
|
261
|
+
/** GET request helper for management endpoints */
|
|
262
|
+
async _fetch(path) {
|
|
263
|
+
const response = await fetch(`${this._baseUrl}${path}`, {
|
|
264
|
+
method: 'GET',
|
|
265
|
+
headers: this.getHeaders(),
|
|
266
|
+
});
|
|
267
|
+
return this.handleResponse(response);
|
|
268
|
+
}
|
|
269
|
+
/** Non-GET request helper for management endpoints */
|
|
270
|
+
async _fetchMethod(method, path, body) {
|
|
271
|
+
const response = await fetch(`${this._baseUrl}${path}`, {
|
|
272
|
+
method,
|
|
273
|
+
headers: this.getHeaders(),
|
|
274
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
275
|
+
});
|
|
276
|
+
if (response.status === 204)
|
|
277
|
+
return undefined;
|
|
278
|
+
return this.handleResponse(response);
|
|
279
|
+
}
|
|
55
280
|
async handleResponse(response) {
|
|
56
281
|
if (response.status === 402) {
|
|
57
282
|
throw new Error('Insufficient credits');
|
|
58
283
|
}
|
|
59
284
|
if (!response.ok) {
|
|
60
|
-
|
|
285
|
+
// Try to surface the server's error message from the response body.
|
|
286
|
+
const body = await response.json().catch(() => null);
|
|
287
|
+
const serverMessage = body?.error || body?.message;
|
|
288
|
+
throw new Error(serverMessage || `Request failed (${response.status})`);
|
|
61
289
|
}
|
|
62
290
|
const data = await response.json();
|
|
63
291
|
if (data.error) {
|
|
@@ -69,7 +297,7 @@ class CoreViz {
|
|
|
69
297
|
try {
|
|
70
298
|
const resizedImage = await (0, resize_1.resize)(image, 512, 512);
|
|
71
299
|
const headers = this.getHeaders();
|
|
72
|
-
const response = await fetch(
|
|
300
|
+
const response = await fetch(`${this._baseUrl}/api/ai/describe`, {
|
|
73
301
|
method: 'POST',
|
|
74
302
|
headers,
|
|
75
303
|
body: JSON.stringify({ image: resizedImage }),
|
|
@@ -85,7 +313,7 @@ class CoreViz {
|
|
|
85
313
|
try {
|
|
86
314
|
const resizedImage = await (0, resize_1.resize)(image, 1024, 1024);
|
|
87
315
|
const headers = this.getHeaders();
|
|
88
|
-
const response = await fetch(
|
|
316
|
+
const response = await fetch(`${this._baseUrl}/api/ai/edit`, {
|
|
89
317
|
method: 'POST',
|
|
90
318
|
headers,
|
|
91
319
|
body: JSON.stringify({
|
|
@@ -110,7 +338,7 @@ class CoreViz {
|
|
|
110
338
|
if (options.referenceImages && options.referenceImages.length > 0) {
|
|
111
339
|
resizedImages = await Promise.all(options.referenceImages.map(img => (0, resize_1.resize)(img, 1024, 1024)));
|
|
112
340
|
}
|
|
113
|
-
const response = await fetch(
|
|
341
|
+
const response = await fetch(`${this._baseUrl}/api/ai/generate`, {
|
|
114
342
|
method: 'POST',
|
|
115
343
|
headers,
|
|
116
344
|
body: JSON.stringify({
|
|
@@ -135,7 +363,7 @@ class CoreViz {
|
|
|
135
363
|
try {
|
|
136
364
|
const resizedImage = await (0, resize_1.resize)(image, 512, 512);
|
|
137
365
|
const headers = this.getHeaders();
|
|
138
|
-
const response = await fetch(
|
|
366
|
+
const response = await fetch(`${this._baseUrl}/api/ai/tag`, {
|
|
139
367
|
method: 'POST',
|
|
140
368
|
headers,
|
|
141
369
|
body: JSON.stringify({
|
|
@@ -289,7 +517,7 @@ Output:
|
|
|
289
517
|
else {
|
|
290
518
|
body.text = input;
|
|
291
519
|
}
|
|
292
|
-
const response = await fetch(
|
|
520
|
+
const response = await fetch(`${this._baseUrl}/api/ai/embed`, {
|
|
293
521
|
method: 'POST',
|
|
294
522
|
headers,
|
|
295
523
|
body: JSON.stringify(body),
|
package/dist/coreviz.native.d.ts
CHANGED
|
@@ -1,6 +1,123 @@
|
|
|
1
1
|
export interface CoreVizConfig {
|
|
2
2
|
apiKey?: string;
|
|
3
3
|
token?: string;
|
|
4
|
+
/** Override the API base URL (default: https://lab.coreviz.io) */
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface UserContext {
|
|
8
|
+
userId: string;
|
|
9
|
+
email: string;
|
|
10
|
+
name: string;
|
|
11
|
+
organizationId: string;
|
|
12
|
+
organizationName: string | null;
|
|
13
|
+
}
|
|
14
|
+
export interface Collection {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
icon?: string;
|
|
18
|
+
type: string;
|
|
19
|
+
organizationId: string;
|
|
20
|
+
}
|
|
21
|
+
export interface MediaObject {
|
|
22
|
+
id: string;
|
|
23
|
+
type: string;
|
|
24
|
+
label: string;
|
|
25
|
+
}
|
|
26
|
+
export interface MediaFrame {
|
|
27
|
+
id: string;
|
|
28
|
+
timestamp: number;
|
|
29
|
+
blob: string;
|
|
30
|
+
objects: MediaObject[];
|
|
31
|
+
}
|
|
32
|
+
export interface Media {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
type: 'image' | 'video' | 'folder';
|
|
36
|
+
blob: string | null;
|
|
37
|
+
path: string;
|
|
38
|
+
width?: number;
|
|
39
|
+
height?: number;
|
|
40
|
+
sizeBytes?: number;
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
frames?: MediaFrame[];
|
|
43
|
+
createdAt?: string;
|
|
44
|
+
_score?: number;
|
|
45
|
+
}
|
|
46
|
+
export interface Folder {
|
|
47
|
+
id: string;
|
|
48
|
+
name: string;
|
|
49
|
+
path: string;
|
|
50
|
+
datasetId: string;
|
|
51
|
+
}
|
|
52
|
+
export interface BrowseOptions {
|
|
53
|
+
path?: string;
|
|
54
|
+
limit?: number;
|
|
55
|
+
offset?: number;
|
|
56
|
+
type?: 'image' | 'video' | 'folder' | 'all';
|
|
57
|
+
dateFrom?: string;
|
|
58
|
+
dateTo?: string;
|
|
59
|
+
sortBy?: string;
|
|
60
|
+
sortDirection?: 'asc' | 'desc';
|
|
61
|
+
tagFilters?: Record<string, string[]>;
|
|
62
|
+
}
|
|
63
|
+
export interface BrowseResult {
|
|
64
|
+
media: Media[];
|
|
65
|
+
pagination: {
|
|
66
|
+
total: number;
|
|
67
|
+
limit: number;
|
|
68
|
+
offset: number;
|
|
69
|
+
hasMore: boolean;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export interface SearchResult {
|
|
73
|
+
mediaId: string;
|
|
74
|
+
mediaName: string;
|
|
75
|
+
mediaType: string;
|
|
76
|
+
blobUrl: string;
|
|
77
|
+
objects: MediaObject[];
|
|
78
|
+
rank: number;
|
|
79
|
+
caption?: string;
|
|
80
|
+
}
|
|
81
|
+
export interface SearchOptions {
|
|
82
|
+
limit?: number;
|
|
83
|
+
}
|
|
84
|
+
export interface SimilarityOptions {
|
|
85
|
+
limit?: number;
|
|
86
|
+
model?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface UploadOptions {
|
|
89
|
+
collectionId: string;
|
|
90
|
+
path?: string;
|
|
91
|
+
name?: string;
|
|
92
|
+
}
|
|
93
|
+
export interface UploadResult {
|
|
94
|
+
mediaId: string;
|
|
95
|
+
url: string;
|
|
96
|
+
message: string;
|
|
97
|
+
}
|
|
98
|
+
export interface CollectionsNamespace {
|
|
99
|
+
list(): Promise<Collection[]>;
|
|
100
|
+
create(name: string, icon?: string): Promise<Collection>;
|
|
101
|
+
}
|
|
102
|
+
export interface MediaNamespace {
|
|
103
|
+
browse(collectionId: string, options?: BrowseOptions): Promise<BrowseResult>;
|
|
104
|
+
search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
105
|
+
get(mediaId: string): Promise<Media>;
|
|
106
|
+
rename(mediaId: string, name: string): Promise<Media>;
|
|
107
|
+
move(mediaId: string, destinationPath: string): Promise<{
|
|
108
|
+
id: string;
|
|
109
|
+
newPath: string;
|
|
110
|
+
}>;
|
|
111
|
+
addTag(mediaId: string, label: string, value: string): Promise<void>;
|
|
112
|
+
removeTag(mediaId: string, label: string, value: string): Promise<void>;
|
|
113
|
+
findSimilar(collectionId: string, objectId: string, options?: SimilarityOptions): Promise<BrowseResult>;
|
|
114
|
+
upload(file: string | File | Blob, options: UploadOptions): Promise<UploadResult>;
|
|
115
|
+
}
|
|
116
|
+
export interface FoldersNamespace {
|
|
117
|
+
create(collectionId: string, name: string, path?: string): Promise<Folder>;
|
|
118
|
+
}
|
|
119
|
+
export interface TagsNamespace {
|
|
120
|
+
list(collectionId: string): Promise<Record<string, string[]>>;
|
|
4
121
|
}
|
|
5
122
|
export interface DescribeOptions {
|
|
6
123
|
}
|
|
@@ -35,8 +152,17 @@ export interface GenerateOptions {
|
|
|
35
152
|
export declare class CoreViz {
|
|
36
153
|
private apiKey?;
|
|
37
154
|
private token?;
|
|
155
|
+
private _baseUrl;
|
|
156
|
+
private _orgIdCache;
|
|
157
|
+
collections: CollectionsNamespace;
|
|
158
|
+
media: MediaNamespace;
|
|
159
|
+
folders: FoldersNamespace;
|
|
160
|
+
tags: TagsNamespace;
|
|
38
161
|
constructor(config?: CoreVizConfig);
|
|
39
162
|
private getHeaders;
|
|
163
|
+
private _me;
|
|
164
|
+
private _fetch;
|
|
165
|
+
private _fetchMethod;
|
|
40
166
|
private handleResponse;
|
|
41
167
|
describe(image: string, _options?: DescribeOptions): Promise<string>;
|
|
42
168
|
edit(image: string, options: EditOptions): Promise<string>;
|