@ecodrix/erix-client 1.0.2 → 1.0.4
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 +82 -1
- package/dist/index.js +94 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
|
24
24
|
[key: string]: JsonValue;
|
|
25
25
|
};
|
|
26
26
|
export interface ErixClientOptions {
|
|
27
|
-
/** Full URL of the deployed erix-store instance, e.g. https://erix
|
|
27
|
+
/** Full URL of the deployed erix-store instance, e.g. https://api.erix.ecodrix.com */
|
|
28
28
|
baseUrl: string;
|
|
29
29
|
/** Shared secret generated at deploy time — must match ERIX_API_KEY on the server */
|
|
30
30
|
apiKey: string;
|
|
@@ -73,6 +73,12 @@ export interface CacheSetOptions {
|
|
|
73
73
|
*/
|
|
74
74
|
staleFor?: number;
|
|
75
75
|
}
|
|
76
|
+
export interface SemanticGetResult<T = JsonValue> {
|
|
77
|
+
value: T;
|
|
78
|
+
key: string;
|
|
79
|
+
similarity: number;
|
|
80
|
+
isExact: boolean;
|
|
81
|
+
}
|
|
76
82
|
export interface QueueEventHandlers<T = JsonValue> {
|
|
77
83
|
onAdded?: (job: JobV2<T>) => void;
|
|
78
84
|
onActive?: (job: JobV2<T>) => void;
|
|
@@ -208,6 +214,81 @@ export declare class ErixClient {
|
|
|
208
214
|
/** Get cache statistics (hit rate, size, evictions) */
|
|
209
215
|
stats: () => Promise<unknown>;
|
|
210
216
|
};
|
|
217
|
+
semantic: {
|
|
218
|
+
/**
|
|
219
|
+
* Store a value with its embedding for similarity lookups.
|
|
220
|
+
* @param key Unique cache key
|
|
221
|
+
* @param text Text to embed (the query/question this entry answers)
|
|
222
|
+
* @param value The value to cache
|
|
223
|
+
* @param ttlMs Optional TTL in milliseconds
|
|
224
|
+
* @param tags Optional tags for bulk invalidation
|
|
225
|
+
*/
|
|
226
|
+
set: (key: string, text: string, value: JsonValue, ttlMs?: number, tags?: string[]) => Promise<void>;
|
|
227
|
+
/**
|
|
228
|
+
* Exact key lookup in semantic cache.
|
|
229
|
+
*/
|
|
230
|
+
get: <T = JsonValue>(key: string) => Promise<T | null>;
|
|
231
|
+
/**
|
|
232
|
+
* Find the most similar cached entry to a query string.
|
|
233
|
+
* Returns null if no entry exceeds the similarity threshold.
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* // Stored: "What are your pricing plans?" → { starter: '$29', pro: '$99' }
|
|
237
|
+
* // Query: "How much does it cost?"
|
|
238
|
+
* const result = await client.semantic.search("How much does it cost?");
|
|
239
|
+
* // → { value: {...}, similarity: 0.97, isExact: false }
|
|
240
|
+
*/
|
|
241
|
+
search: <T = JsonValue>(query: string, threshold?: number) => Promise<SemanticGetResult<T> | null>;
|
|
242
|
+
/** Invalidate all semantic cache entries with a specific tag */
|
|
243
|
+
invalidateByTag: (tag: string) => Promise<number>;
|
|
244
|
+
/** Delete a single semantic cache entry */
|
|
245
|
+
del: (key: string) => Promise<void>;
|
|
246
|
+
/** Get semantic cache stats */
|
|
247
|
+
stats: () => Promise<{
|
|
248
|
+
success: boolean;
|
|
249
|
+
size: number;
|
|
250
|
+
keys: string[];
|
|
251
|
+
}>;
|
|
252
|
+
};
|
|
253
|
+
analytics: {
|
|
254
|
+
/**
|
|
255
|
+
* Get live usage counts for this tenant (from in-memory buffer).
|
|
256
|
+
* Updated in real time — no waiting for the 10s DB flush.
|
|
257
|
+
*/
|
|
258
|
+
usage: () => Promise<Record<string, number>>;
|
|
259
|
+
/**
|
|
260
|
+
* Get anomaly detector stats — mean, stddev, and sample count
|
|
261
|
+
* for each monitored metric of this tenant.
|
|
262
|
+
*/
|
|
263
|
+
anomalies: () => Promise<{
|
|
264
|
+
success: boolean;
|
|
265
|
+
metrics: Array<{
|
|
266
|
+
metric: string;
|
|
267
|
+
mean: number;
|
|
268
|
+
stddev: number;
|
|
269
|
+
n: number;
|
|
270
|
+
}>;
|
|
271
|
+
}>;
|
|
272
|
+
/**
|
|
273
|
+
* Subscribe to real-time anomaly alerts via SSE.
|
|
274
|
+
* The server fires an event whenever a metric exceeds 3σ.
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* const sub = client.analytics.subscribeAlerts((alert) => {
|
|
278
|
+
* console.log(`ALERT: ${alert.message}`);
|
|
279
|
+
* });
|
|
280
|
+
* sub.close();
|
|
281
|
+
*/
|
|
282
|
+
subscribeAlerts: (onAlert: (alert: {
|
|
283
|
+
metric: string;
|
|
284
|
+
current: number;
|
|
285
|
+
mean: number;
|
|
286
|
+
zScore: number;
|
|
287
|
+
message: string;
|
|
288
|
+
}) => void, onError?: (err: Error) => void) => {
|
|
289
|
+
close: () => void;
|
|
290
|
+
};
|
|
291
|
+
};
|
|
211
292
|
/**
|
|
212
293
|
* Opens a persistent SSE connection and dispatches named events to a handler.
|
|
213
294
|
* Returns a controller with `.close()` to terminate the connection.
|
package/dist/index.js
CHANGED
|
@@ -227,6 +227,100 @@ export class ErixClient {
|
|
|
227
227
|
return res.stats;
|
|
228
228
|
},
|
|
229
229
|
};
|
|
230
|
+
// ─── Semantic Cache (AI layer) ────────────────────────────────────────
|
|
231
|
+
this.semantic = {
|
|
232
|
+
/**
|
|
233
|
+
* Store a value with its embedding for similarity lookups.
|
|
234
|
+
* @param key Unique cache key
|
|
235
|
+
* @param text Text to embed (the query/question this entry answers)
|
|
236
|
+
* @param value The value to cache
|
|
237
|
+
* @param ttlMs Optional TTL in milliseconds
|
|
238
|
+
* @param tags Optional tags for bulk invalidation
|
|
239
|
+
*/
|
|
240
|
+
set: async (key, text, value, ttlMs, tags) => {
|
|
241
|
+
await this.req("POST", `/semantic/${encodeURIComponent(key)}`, {
|
|
242
|
+
text,
|
|
243
|
+
value,
|
|
244
|
+
ttlMs,
|
|
245
|
+
tags,
|
|
246
|
+
});
|
|
247
|
+
},
|
|
248
|
+
/**
|
|
249
|
+
* Exact key lookup in semantic cache.
|
|
250
|
+
*/
|
|
251
|
+
get: async (key) => {
|
|
252
|
+
try {
|
|
253
|
+
const res = await this.req("GET", `/semantic/${encodeURIComponent(key)}`);
|
|
254
|
+
return res.value ?? null;
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
/**
|
|
261
|
+
* Find the most similar cached entry to a query string.
|
|
262
|
+
* Returns null if no entry exceeds the similarity threshold.
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* // Stored: "What are your pricing plans?" → { starter: '$29', pro: '$99' }
|
|
266
|
+
* // Query: "How much does it cost?"
|
|
267
|
+
* const result = await client.semantic.search("How much does it cost?");
|
|
268
|
+
* // → { value: {...}, similarity: 0.97, isExact: false }
|
|
269
|
+
*/
|
|
270
|
+
search: async (query, threshold) => {
|
|
271
|
+
try {
|
|
272
|
+
const res = await this.req("POST", "/semantic/search", { query, threshold });
|
|
273
|
+
return res;
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
/** Invalidate all semantic cache entries with a specific tag */
|
|
280
|
+
invalidateByTag: async (tag) => {
|
|
281
|
+
const res = await this.req("DELETE", `/semantic/tags/${encodeURIComponent(tag)}`);
|
|
282
|
+
return res.count;
|
|
283
|
+
},
|
|
284
|
+
/** Delete a single semantic cache entry */
|
|
285
|
+
del: async (key) => {
|
|
286
|
+
await this.req("DELETE", `/semantic/${encodeURIComponent(key)}`);
|
|
287
|
+
},
|
|
288
|
+
/** Get semantic cache stats */
|
|
289
|
+
stats: async () => {
|
|
290
|
+
return this.req("GET", "/semantic/_stats");
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
// ─── Analytics ────────────────────────────────────────────────────────
|
|
294
|
+
this.analytics = {
|
|
295
|
+
/**
|
|
296
|
+
* Get live usage counts for this tenant (from in-memory buffer).
|
|
297
|
+
* Updated in real time — no waiting for the 10s DB flush.
|
|
298
|
+
*/
|
|
299
|
+
usage: async () => {
|
|
300
|
+
const res = await this.req("GET", "/analytics/usage");
|
|
301
|
+
return res.usage;
|
|
302
|
+
},
|
|
303
|
+
/**
|
|
304
|
+
* Get anomaly detector stats — mean, stddev, and sample count
|
|
305
|
+
* for each monitored metric of this tenant.
|
|
306
|
+
*/
|
|
307
|
+
anomalies: async () => {
|
|
308
|
+
return this.req("GET", "/analytics/anomalies");
|
|
309
|
+
},
|
|
310
|
+
/**
|
|
311
|
+
* Subscribe to real-time anomaly alerts via SSE.
|
|
312
|
+
* The server fires an event whenever a metric exceeds 3σ.
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* const sub = client.analytics.subscribeAlerts((alert) => {
|
|
316
|
+
* console.log(`ALERT: ${alert.message}`);
|
|
317
|
+
* });
|
|
318
|
+
* sub.close();
|
|
319
|
+
*/
|
|
320
|
+
subscribeAlerts: (onAlert, onError) => {
|
|
321
|
+
return this.openEventStream("/analytics/anomalies/stream", (_event, data) => onAlert(data), onError);
|
|
322
|
+
},
|
|
323
|
+
};
|
|
230
324
|
this.baseUrl = options.baseUrl.replace(/\/$/, ""); // strip trailing slash
|
|
231
325
|
this.timeoutMs = options.timeoutMs ?? 5000;
|
|
232
326
|
this.headers = {
|
package/package.json
CHANGED