hyperspace-sdk-ts 3.1.6 → 3.1.7

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 CHANGED
@@ -42,10 +42,10 @@ async function main() {
42
42
  await client.deleteCollection(collection).catch(() => {});
43
43
  await client.createCollection(collection, {
44
44
  components: [
45
- { name: "primary", metric: "cosine", full_dimension: 3, weight: 1.0 }
45
+ { name: "primary", metric: "cosine", fullDimension: 3, weight: 1.0 }
46
46
  ],
47
- cascade_pipeline: []
48
- });
47
+ cascadePipeline: []
48
+ }, '', 0.02, 'medium_plus');
49
49
 
50
50
  await client.insert(1, [0.1, 0.2, 0.3], { source: "demo" }, collection);
51
51
  await client.insert(2, [0.2, 0.1, 0.4], { source: "demo" }, collection);
package/dist/client.d.ts CHANGED
@@ -163,7 +163,8 @@ export declare class HyperspaceClient {
163
163
  private _projectSingleBlock;
164
164
  private _projectCollectionVector;
165
165
  private _encryptFilters;
166
- createCollection(name: string, schema: CollectionSchema, encryptionKey?: string, noiseSigma?: number): Promise<boolean>;
166
+ createCollection(name: string, schema: CollectionSchema, encryptionKey?: string, noiseSigma?: number, quantization?: string): Promise<boolean>;
167
+ private createCollectionGrpc;
167
168
  deleteCollection(name: string): Promise<boolean>;
168
169
  freezeCollection(name: string): Promise<string>;
169
170
  unfreezeCollection(name: string): Promise<string>;
@@ -254,5 +255,8 @@ export declare class HyperspaceClient {
254
255
  exploreGraph(startId: number, maxDepth?: number, maxNodes?: number, collection?: string): Promise<any>;
255
256
  predictMomentum(trajectoryIds: number[], steps?: number, collection?: string, curvature?: number): Promise<number[]>;
256
257
  getTrustScore(trajectoryIds: number[], collection?: string, curvature?: number): Promise<number>;
258
+ startRun(sessionId: string, taskDescription: string): Promise<boolean>;
259
+ stepRun(sessionId: string, x: number, y: number, metadata?: any): Promise<boolean>;
260
+ endRun(sessionId: string, status: string, finalScore?: number, lyapunovStability?: number): Promise<boolean>;
257
261
  close(): void;
258
262
  }
package/dist/client.js CHANGED
@@ -298,7 +298,10 @@ class HyperspaceClient {
298
298
  this.collectionMetrics = {};
299
299
  this.collectionNoiseSigmas = {};
300
300
  this.collectionSchemas = {};
301
- this.host = host;
301
+ const cleanHost = host.replace(/^https?:\/\//, '').replace(/\/$/, '');
302
+ const isSecure = cleanHost.endsWith(':443') || (!cleanHost.includes('localhost') && !cleanHost.includes('127.0.0.1') && !cleanHost.includes(':50051') && !cleanHost.includes(':50050') && cleanHost.includes('.'));
303
+ const formattedHost = isSecure && !cleanHost.includes(':') ? `${cleanHost}:443` : cleanHost;
304
+ this.host = formattedHost;
302
305
  this.apiKey = apiKey;
303
306
  this.userId = userId;
304
307
  const options = {
@@ -310,7 +313,8 @@ class HyperspaceClient {
310
313
  'grpc.http2.min_time_between_pings_ms': 10000,
311
314
  'grpc.http2.min_ping_interval_without_data_ms': 5000,
312
315
  };
313
- this.client = new hyperspace_grpc_pb_1.DatabaseClient(host, grpc.credentials.createInsecure(), options);
316
+ const creds = isSecure ? grpc.credentials.createSsl() : grpc.credentials.createInsecure();
317
+ this.client = new hyperspace_grpc_pb_1.DatabaseClient(formattedHost, creds, options);
314
318
  this.metadata = new grpc.Metadata();
315
319
  if (apiKey) {
316
320
  this.metadata.add('x-api-key', apiKey);
@@ -531,11 +535,46 @@ class HyperspaceClient {
531
535
  });
532
536
  }
533
537
  // ... (create/delete unchanged) ...
534
- createCollection(name, schema, encryptionKey = '', noiseSigma = 0.02) {
538
+ createCollection(name, schema, encryptionKey = '', noiseSigma = 0.02, quantization) {
535
539
  const metric = (schema.components && schema.components[0]) ? schema.components[0].metric : "l2";
536
540
  if (encryptionKey) {
537
541
  this.registerCollectionKey(name, encryptionKey, metric, noiseSigma, schema);
538
542
  }
543
+ if (quantization) {
544
+ const isYarSaaS = this.host.includes('yar.ink') || (!this.host.includes('localhost') && !this.host.includes('127.0.0.1'));
545
+ const hostOnly = this.host.split(':')[0];
546
+ const url = isYarSaaS ? 'https://the.yar.ink/api/collections' : `http://${hostOnly}:50050/api/collections`;
547
+ const comp = schema.components && schema.components[0];
548
+ const payload = {
549
+ name,
550
+ dimension: comp ? comp.fullDimension : 1024,
551
+ metric: comp ? comp.metric : "l2",
552
+ quantization,
553
+ };
554
+ if (schema.cascadePipeline && schema.cascadePipeline.length > 0) {
555
+ payload.mrl_cutoff_dimension = schema.cascadePipeline[0].cutoffDimension;
556
+ payload.mrl_rerank_top_k = schema.cascadePipeline[0].rerankTopK || 100;
557
+ }
558
+ return fetch(url, {
559
+ method: 'POST',
560
+ headers: {
561
+ 'Content-Type': 'application/json',
562
+ ...(this.apiKey ? { 'x-api-key': this.apiKey, 'Authorization': `Bearer ${this.apiKey}` } : {}),
563
+ ...(this.userId ? { 'x-hyperspace-user-id': this.userId } : {}),
564
+ },
565
+ body: JSON.stringify(payload),
566
+ })
567
+ .then(async (r) => {
568
+ if (r.ok) {
569
+ return true;
570
+ }
571
+ return this.createCollectionGrpc(name, schema);
572
+ })
573
+ .catch(() => this.createCollectionGrpc(name, schema));
574
+ }
575
+ return this.createCollectionGrpc(name, schema);
576
+ }
577
+ createCollectionGrpc(name, schema) {
539
578
  return new Promise((resolve, reject) => {
540
579
  const req = new hyperspace_pb_1.CreateCollectionRequest();
541
580
  req.setName(name);
@@ -549,7 +588,7 @@ class HyperspaceClient {
549
588
  return comp;
550
589
  });
551
590
  protoSchema.setComponentsList(components);
552
- const pipeline = schema.cascadePipeline.map(l => {
591
+ const pipeline = (schema.cascadePipeline || []).map(l => {
553
592
  const layer = new hyperspace_pb.MrlLayer();
554
593
  layer.setComponentName(l.componentName);
555
594
  layer.setCutoffDimension(l.cutoffDimension);
@@ -759,19 +798,70 @@ class HyperspaceClient {
759
798
  return reject(err);
760
799
  resolve(resp.getSuccess());
761
800
  });
801
+ }).catch(async (err) => {
802
+ const errStr = (err ? String(err.message || '') + ' ' + String(err.details || '') : '');
803
+ const isUnavail = err && (err.code === 14 || err.code === 12 || err.code === 9 ||
804
+ errStr.includes('UNIMPLEMENTED') ||
805
+ errStr.includes('Embedding engine disabled') ||
806
+ errStr.includes('embedding model') ||
807
+ errStr.includes('FAILED_PRECONDITION') ||
808
+ errStr.includes('502') ||
809
+ errStr.includes('UNAVAILABLE'));
810
+ if (isUnavail) {
811
+ const vec = await this.vectorize(text, 'hybrid');
812
+ return this.insert(id, vec, meta, collection, durability, undefined, Buffer.from(text, 'utf-8'));
813
+ }
814
+ throw err;
762
815
  });
763
816
  }
764
- vectorize(text, metric = 'l2') {
765
- return new Promise((resolve, reject) => {
766
- const req = new hyperspace_pb_1.VectorizeRequest();
767
- req.setText(text);
768
- req.setMetric(metric);
769
- this.client.vectorize(req, this.metadata, (err, resp) => {
770
- if (err)
771
- return reject(err);
772
- resolve(resp.getVectorList());
817
+ async vectorize(text, metric = 'l2') {
818
+ if (this.embedder) {
819
+ return Promise.resolve(this.embedder.encode(text));
820
+ }
821
+ try {
822
+ return await new Promise((resolve, reject) => {
823
+ const req = new hyperspace_pb_1.VectorizeRequest();
824
+ req.setText(text);
825
+ req.setMetric(metric);
826
+ this.client.vectorize(req, this.metadata, (err, resp) => {
827
+ if (err)
828
+ return reject(err);
829
+ resolve(resp.getVectorList());
830
+ });
773
831
  });
774
- });
832
+ }
833
+ catch (grpcErr) {
834
+ const urls = [
835
+ 'https://the.yar.ink/v1/embeddings',
836
+ `http://${this.host.split(':')[0]}:8080/v1/embeddings`
837
+ ];
838
+ const apiKey = process.env.CDE_API_KEY || ((this.apiKey && this.apiKey.startsWith('sk_')) ? this.apiKey : '') || process.env.HYPERSPACE_API_KEY || '';
839
+ for (const url of urls) {
840
+ try {
841
+ const res = await fetch(url, {
842
+ method: 'POST',
843
+ headers: {
844
+ 'Content-Type': 'application/json',
845
+ 'Authorization': `Bearer ${apiKey}`
846
+ },
847
+ body: JSON.stringify({
848
+ model: 'v5_Light',
849
+ input: text
850
+ })
851
+ });
852
+ if (res.ok) {
853
+ const json = await res.json();
854
+ if (json.data && json.data[0] && json.data[0].embedding) {
855
+ return json.data[0].embedding;
856
+ }
857
+ }
858
+ }
859
+ catch (httpErr) {
860
+ // try next
861
+ }
862
+ }
863
+ throw grpcErr;
864
+ }
775
865
  }
776
866
  batchInsert(items, collection = '', durability = hyperspace_pb_1.DurabilityLevel.DEFAULT_LEVEL) {
777
867
  return new Promise((resolve, reject) => {
@@ -985,6 +1075,20 @@ class HyperspaceClient {
985
1075
  });
986
1076
  resolve(results);
987
1077
  });
1078
+ }).catch(async (err) => {
1079
+ const errStr = (err ? String(err.message || '') + ' ' + String(err.details || '') : '');
1080
+ const isUnavail = err && (err.code === 14 || err.code === 12 || err.code === 9 ||
1081
+ errStr.includes('UNIMPLEMENTED') ||
1082
+ errStr.includes('Embedding engine disabled') ||
1083
+ errStr.includes('embedding model') ||
1084
+ errStr.includes('FAILED_PRECONDITION') ||
1085
+ errStr.includes('502') ||
1086
+ errStr.includes('UNAVAILABLE'));
1087
+ if (isUnavail) {
1088
+ const vec = await this.vectorize(text, 'hybrid');
1089
+ return this.search(vec, topK, collection, options);
1090
+ }
1091
+ throw err;
988
1092
  });
989
1093
  }
990
1094
  searchBatch(vectors, topK, collection = '') {
@@ -1496,6 +1600,73 @@ class HyperspaceClient {
1496
1600
  return 1.0;
1497
1601
  }
1498
1602
  }
1603
+ async startRun(sessionId, taskDescription) {
1604
+ const ip = this.host.split(':')[0];
1605
+ const url = `http://${ip}:50050/api/admin/runs/start`;
1606
+ const headers = { 'Content-Type': 'application/json' };
1607
+ if (this.apiKey)
1608
+ headers['x-api-key'] = this.apiKey;
1609
+ if (this.userId)
1610
+ headers['x-hyperspace-user-id'] = this.userId;
1611
+ const res = await fetch(url, {
1612
+ method: 'POST',
1613
+ headers,
1614
+ body: JSON.stringify({
1615
+ session_id: sessionId,
1616
+ task_description: taskDescription
1617
+ })
1618
+ });
1619
+ if (!res.ok) {
1620
+ throw new Error(`Failed to start run: ${res.statusText} (${await res.text()})`);
1621
+ }
1622
+ return res.status === 200;
1623
+ }
1624
+ async stepRun(sessionId, x, y, metadata) {
1625
+ const ip = this.host.split(':')[0];
1626
+ const url = `http://${ip}:50050/api/admin/runs/step`;
1627
+ const headers = { 'Content-Type': 'application/json' };
1628
+ if (this.apiKey)
1629
+ headers['x-api-key'] = this.apiKey;
1630
+ if (this.userId)
1631
+ headers['x-hyperspace-user-id'] = this.userId;
1632
+ const res = await fetch(url, {
1633
+ method: 'POST',
1634
+ headers,
1635
+ body: JSON.stringify({
1636
+ session_id: sessionId,
1637
+ x,
1638
+ y,
1639
+ metadata
1640
+ })
1641
+ });
1642
+ if (!res.ok) {
1643
+ throw new Error(`Failed to record run step: ${res.statusText} (${await res.text()})`);
1644
+ }
1645
+ return res.status === 200;
1646
+ }
1647
+ async endRun(sessionId, status, finalScore, lyapunovStability) {
1648
+ const ip = this.host.split(':')[0];
1649
+ const url = `http://${ip}:50050/api/admin/runs/end`;
1650
+ const headers = { 'Content-Type': 'application/json' };
1651
+ if (this.apiKey)
1652
+ headers['x-api-key'] = this.apiKey;
1653
+ if (this.userId)
1654
+ headers['x-hyperspace-user-id'] = this.userId;
1655
+ const res = await fetch(url, {
1656
+ method: 'POST',
1657
+ headers,
1658
+ body: JSON.stringify({
1659
+ session_id: sessionId,
1660
+ status,
1661
+ final_score: finalScore,
1662
+ lyapunov_stability: lyapunovStability
1663
+ })
1664
+ });
1665
+ if (!res.ok) {
1666
+ throw new Error(`Failed to end run: ${res.statusText} (${await res.text()})`);
1667
+ }
1668
+ return res.status === 200;
1669
+ }
1499
1670
  close() {
1500
1671
  this.client.close();
1501
1672
  }
package/dist/math.d.ts CHANGED
@@ -26,10 +26,11 @@ export declare function projectToHyperboloid(v: number[]): number[];
26
26
  * Returns a value in [0, 1) where values approaching 1 imply high chaos (hallucination).
27
27
  */
28
28
  export declare function localEntropy(candidate: number[], neighbors: number[][], c?: number): number;
29
+ /** Computes hybrid distance (Lorentz H³² over 0..33 + Euclidean over 33..801). */
30
+ export declare function hybridDistance(u: number[], v: number[]): number;
29
31
  /**
30
- * Evaluates if a trajectory of vectors (e.g. Chain of Thought) converges to an attractor.
31
- * Calculates the average energy derivative (Lyapunov function derivative).
32
- * Negative values indicate convergence (stable), positive indicate divergence (chaos/hallucination).
32
+ * Evaluates if a trajectory of vectors (e.g. Chain of Thought) converges toward a solution goal attractor.
33
+ * Negative values indicate distance contraction (stable convergence), positive indicate goal divergence (hallucination).
33
34
  */
34
35
  export declare function lyapunovConvergence(trajectory: number[][], c?: number): number;
35
36
  /**
package/dist/math.js CHANGED
@@ -18,6 +18,7 @@ exports.lorentzToPoincare = lorentzToPoincare;
18
18
  exports.poincareToLorentz = poincareToLorentz;
19
19
  exports.projectToHyperboloid = projectToHyperboloid;
20
20
  exports.localEntropy = localEntropy;
21
+ exports.hybridDistance = hybridDistance;
21
22
  exports.lyapunovConvergence = lyapunovConvergence;
22
23
  exports.koopmanExtrapolate = koopmanExtrapolate;
23
24
  exports.contextResonance = contextResonance;
@@ -199,22 +200,48 @@ function localEntropy(candidate, neighbors, c = 1.0) {
199
200
  const meanDeviation = totalDeviation / neighbors.length;
200
201
  return 1.0 - Math.exp(-meanDeviation);
201
202
  }
203
+ /** Computes hybrid distance (Lorentz H³² over 0..33 + Euclidean over 33..801). */
204
+ function hybridDistance(u, v) {
205
+ if (u.length >= 801 && v.length >= 801) {
206
+ let mink = -u[0] * v[0];
207
+ for (let i = 1; i < 33; i++)
208
+ mink += u[i] * v[i];
209
+ const lorDist = Math.acosh(Math.max(1.0, -mink));
210
+ let eucSq = 0.0;
211
+ for (let i = 33; i < u.length; i++) {
212
+ const diff = u[i] - v[i];
213
+ eucSq += diff * diff;
214
+ }
215
+ return lorDist + Math.sqrt(eucSq);
216
+ }
217
+ else {
218
+ let sumSq = 0.0;
219
+ for (let i = 0; i < u.length; i++) {
220
+ const diff = u[i] - v[i];
221
+ sumSq += diff * diff;
222
+ }
223
+ return Math.sqrt(sumSq);
224
+ }
225
+ }
202
226
  /**
203
- * Evaluates if a trajectory of vectors (e.g. Chain of Thought) converges to an attractor.
204
- * Calculates the average energy derivative (Lyapunov function derivative).
205
- * Negative values indicate convergence (stable), positive indicate divergence (chaos/hallucination).
227
+ * Evaluates if a trajectory of vectors (e.g. Chain of Thought) converges toward a solution goal attractor.
228
+ * Negative values indicate distance contraction (stable convergence), positive indicate goal divergence (hallucination).
206
229
  */
207
230
  function lyapunovConvergence(trajectory, c = 1.0) {
208
231
  if (trajectory.length < 3)
209
232
  throw new Error("Need at least 3 points");
210
- const attractor = frechetMean(trajectory, c, 32, 1e-6);
211
- let vDiffSum = 0.0;
212
- for (let i = 0; i < trajectory.length - 1; i++) {
213
- const vt0 = norm(logMap(attractor, trajectory[i], c));
214
- const vt1 = norm(logMap(attractor, trajectory[i + 1], c));
215
- vDiffSum += (vt1 - vt0);
233
+ const goal = trajectory[trajectory.length - 1];
234
+ let lyapSum = 0.0;
235
+ let count = 0;
236
+ for (let i = 0; i < trajectory.length - 2; i++) {
237
+ const d0 = hybridDistance(trajectory[i], goal);
238
+ const d1 = hybridDistance(trajectory[i + 1], goal);
239
+ if (d0 > 1e-12) {
240
+ lyapSum += (d1 - d0) / d0;
241
+ count++;
242
+ }
216
243
  }
217
- return vDiffSum / (trajectory.length - 1);
244
+ return count > 0 ? lyapSum / count : 0.0;
218
245
  }
219
246
  /**
220
247
  * Extrapolates the trajectory in linear space (Koopman linearization) by tracking the