@simpleplatform/sdk 1.0.3 → 1.1.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/ai.d.ts CHANGED
@@ -157,6 +157,21 @@ export interface AITranscribeOptions extends Omit<AICommonOptions, 'prompt'> {
157
157
  */
158
158
  summarize?: boolean;
159
159
  }
160
+ /**
161
+ * Options for searching faces within the Face Engine.
162
+ */
163
+ export interface AIFaceSearchOptions {
164
+ /**
165
+ * Maximum number of matches to return.
166
+ * Defaults to 5.
167
+ */
168
+ maxFaces?: number;
169
+ /**
170
+ * Minimum similarity percentage (0-100) required for a match.
171
+ * Defaults to 85.0.
172
+ */
173
+ similarityThreshold?: number;
174
+ }
160
175
  /**
161
176
  * The response structure from a successful AI `extract` or `summarize` operation.
162
177
  */
@@ -236,4 +251,38 @@ export declare function summarize(input: DocumentHandle | object | string, optio
236
251
  * // Returns: { language: "en", summary: "...", participants: ["Participant 1", "Participant 2"] }
237
252
  */
238
253
  export declare function transcribe(input: DocumentHandle, options: AITranscribeOptions, context: Context): Promise<AIExecutionResult>;
254
+ /**
255
+ * Enrolls a face for a subject. The face is associated with the given `subjectId`
256
+ * within the tenant's secure collection.
257
+ *
258
+ * @param subjectId A unique identifier for the subject (e.g., employee ID, user ID).
259
+ * @param image The image containing the face to enroll. Can be a base64 string or a DocumentHandle.
260
+ * @param context The execution context provided by the host.
261
+ * @returns A promise that resolves to an object containing the enrolled `face_id`.
262
+ * @throws Will throw an error if the operation fails or inputs are invalid.
263
+ */
264
+ export declare function enrollFace(subjectId: string, image: DocumentHandle | string, context: Context): Promise<{
265
+ face_id: string;
266
+ }>;
267
+ /**
268
+ * Searches for faces matching the provided image within the tenant's collection.
269
+ *
270
+ * @param image The image to search for. Can be a base64 string or a DocumentHandle.
271
+ * @param options Configuration for the search operation (e.g., maxFaces, similarityThreshold).
272
+ * @param context The execution context provided by the host.
273
+ * @returns A promise that resolves to a list of matching faces and their confidence scores.
274
+ * @throws Will throw an error if the operation fails or inputs are invalid.
275
+ */
276
+ export declare function searchFace(image: DocumentHandle | string, options: AIFaceSearchOptions | undefined, context: Context): Promise<any>;
277
+ /**
278
+ * Deletes one or more faces from the tenant's collection by their face IDs.
279
+ *
280
+ * @param faceIds An array of face IDs to delete.
281
+ * @param context The execution context provided by the host.
282
+ * @returns A promise that resolves to an object indicating the IDs of successfully deleted faces.
283
+ * @throws Will throw an error if the operation fails.
284
+ */
285
+ export declare function deleteFace(faceIds: string[], context: Context): Promise<{
286
+ deleted: string[];
287
+ }>;
239
288
  export {};
package/dist/ai.js CHANGED
@@ -263,3 +263,109 @@ export async function transcribe(input, options, context) {
263
263
  schema,
264
264
  }, context);
265
265
  }
266
+ // ============================================================================
267
+ // Face Recognition API
268
+ // ============================================================================
269
+ let _collectionEnsured = false;
270
+ /**
271
+ * Internal helper to ensure the face collection exists before making face operations.
272
+ * Caches the result per Javascript isolate execution to minimize RPC overhead over
273
+ * sequential calls in the same logic.
274
+ */
275
+ async function _ensureFaceCollection(context) {
276
+ if (_collectionEnsured)
277
+ return;
278
+ const response = await hostExecute('action:ai/face/ensure-collection', {}, context);
279
+ if (!response.ok) {
280
+ throw new Error(response.error?.message || 'Failed to ensure face collection.');
281
+ }
282
+ _collectionEnsured = true;
283
+ }
284
+ /**
285
+ * Enrolls a face for a subject. The face is associated with the given `subjectId`
286
+ * within the tenant's secure collection.
287
+ *
288
+ * @param subjectId A unique identifier for the subject (e.g., employee ID, user ID).
289
+ * @param image The image containing the face to enroll. Can be a base64 string or a DocumentHandle.
290
+ * @param context The execution context provided by the host.
291
+ * @returns A promise that resolves to an object containing the enrolled `face_id`.
292
+ * @throws Will throw an error if the operation fails or inputs are invalid.
293
+ */
294
+ export async function enrollFace(subjectId, image, context) {
295
+ if (!subjectId) {
296
+ throw new Error('The `subjectId` parameter is required for `enrollFace`.');
297
+ }
298
+ if (!image) {
299
+ throw new Error('The `image` parameter is required for `enrollFace`.');
300
+ }
301
+ // Ensure the tenant's collection is ready before enrolling
302
+ await _ensureFaceCollection(context);
303
+ // Upload pending documents if given handles
304
+ const processedImage = await _uploadPendingFiles(image, context);
305
+ const payload = {
306
+ image: processedImage,
307
+ subject_id: subjectId,
308
+ };
309
+ const response = await hostExecute('action:ai/face/enroll', payload, context);
310
+ if (!response.ok) {
311
+ throw new Error(response.error?.message || 'Face enrollment failed.');
312
+ }
313
+ return response.data;
314
+ }
315
+ /**
316
+ * Searches for faces matching the provided image within the tenant's collection.
317
+ *
318
+ * @param image The image to search for. Can be a base64 string or a DocumentHandle.
319
+ * @param options Configuration for the search operation (e.g., maxFaces, similarityThreshold).
320
+ * @param context The execution context provided by the host.
321
+ * @returns A promise that resolves to a list of matching faces and their confidence scores.
322
+ * @throws Will throw an error if the operation fails or inputs are invalid.
323
+ */
324
+ export async function searchFace(image, options = {}, context) {
325
+ if (!image) {
326
+ throw new Error('The `image` parameter is required for `searchFace`.');
327
+ }
328
+ // Ensure collection exists before searching
329
+ await _ensureFaceCollection(context);
330
+ const processedImage = await _uploadPendingFiles(image, context);
331
+ // Map JS property names to Elixir convention if needed, though they are passed as options
332
+ // and parsed correctly in simple_logic if expected.
333
+ // The simple_ai FaceEngine expects snake_case for options like max_faces or similarity_threshold.
334
+ const mappedOptions = {};
335
+ if (options.maxFaces !== undefined)
336
+ mappedOptions.max_faces = options.maxFaces;
337
+ if (options.similarityThreshold !== undefined)
338
+ mappedOptions.similarity_threshold = options.similarityThreshold;
339
+ const payload = {
340
+ image: processedImage,
341
+ options: mappedOptions,
342
+ };
343
+ const response = await hostExecute('action:ai/face/search', payload, context);
344
+ if (!response.ok) {
345
+ throw new Error(response.error?.message || 'Face search failed.');
346
+ }
347
+ return response.data;
348
+ }
349
+ /**
350
+ * Deletes one or more faces from the tenant's collection by their face IDs.
351
+ *
352
+ * @param faceIds An array of face IDs to delete.
353
+ * @param context The execution context provided by the host.
354
+ * @returns A promise that resolves to an object indicating the IDs of successfully deleted faces.
355
+ * @throws Will throw an error if the operation fails.
356
+ */
357
+ export async function deleteFace(faceIds, context) {
358
+ if (!faceIds || !Array.isArray(faceIds) || faceIds.length === 0) {
359
+ throw new Error('The `faceIds` parameter must be a non-empty array for `deleteFace`.');
360
+ }
361
+ await _ensureFaceCollection(context);
362
+ const payload = {
363
+ face_ids: faceIds,
364
+ };
365
+ const response = await hostExecute('action:ai/face/delete', payload, context);
366
+ if (!response.ok) {
367
+ throw new Error(response.error?.message || 'Face deletion failed.');
368
+ }
369
+ // Ensure consistent return format
370
+ return { deleted: Array.isArray(response.data) ? response.data : response.data?.deleted || [] };
371
+ }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { Context, SimpleRequest, SimpleResponse } from './types';
2
1
  import './internal/global';
2
+ import type { Context, SimpleRequest, SimpleResponse } from './types';
3
3
  export * from './storage';
4
4
  export * from './types';
5
5
  /**
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
- import * as host from './host';
1
+ /* eslint-disable perfectionist/sort-imports */
2
2
  import './internal/global';
3
+ import * as host from './host';
3
4
  export * from './storage';
4
5
  export * from './types';
5
6
  /**
@@ -11,22 +11,21 @@ const pendingHostRequests = new Map()
11
11
 
12
12
  // eslint-disable-next-line no-restricted-globals
13
13
  self.addEventListener('message', (event) => {
14
- const message = event && event.data
15
- if (
16
- typeof message !== 'object'
17
- || message === null
18
- || message.type !== 'host_response'
19
- ) {
14
+ const message = event.data
15
+ if (message.type !== 'host_response')
20
16
  return
21
- }
22
17
 
23
18
  const pending = pendingHostRequests.get(message.requestId)
24
19
  if (!pending)
25
20
  return
26
21
 
22
+ const errorMsg = typeof message.response.error === 'object' && message.response.error?.message
23
+ ? message.response.error.message
24
+ : message.response.error ?? 'Unknown host error'
25
+
27
26
  message.response.ok
28
27
  ? pending.resolve(message.response)
29
- : pending.reject(new Error(message.response.error ?? 'Unknown host error'))
28
+ : pending.reject(new Error(errorMsg))
30
29
 
31
30
  pendingHostRequests.delete(message.requestId)
32
31
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simpleplatform/sdk",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "description": "Simple Platform Typescript SDK",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://docs.simple.dev",
@@ -61,10 +61,10 @@
61
61
  "dist"
62
62
  ],
63
63
  "dependencies": {
64
- "esbuild": "0.27.2"
64
+ "esbuild": "0.27.3"
65
65
  },
66
66
  "devDependencies": {
67
- "@types/node": "25.1.0",
67
+ "@types/node": "25.3.3",
68
68
  "typescript": "5.9.3"
69
69
  },
70
70
  "scripts": {