@vectorize-io/hindsight-client 0.2.1 → 0.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectorize-io/hindsight-client",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "description": "TypeScript client for Hindsight - Semantic memory system with personality-driven thinking",
5
5
  "main": "./dist/src/index.js",
6
6
  "types": "./dist/src/index.d.ts",
@@ -26,7 +26,7 @@
26
26
  "directory": "hindsight-clients/typescript"
27
27
  },
28
28
  "devDependencies": {
29
- "@hey-api/openapi-ts": "^0.88.0",
29
+ "@hey-api/openapi-ts": "0.88.0",
30
30
  "@types/jest": "^29.0.0",
31
31
  "@types/node": "^20.0.0",
32
32
  "jest": "^29.0.0",
package/src/index.ts CHANGED
@@ -62,6 +62,7 @@ export interface MemoryItemInput {
62
62
  metadata?: Record<string, string>;
63
63
  document_id?: string;
64
64
  entities?: EntityInput[];
65
+ tags?: string[];
65
66
  }
66
67
 
67
68
  export class HindsightClient {
@@ -78,6 +79,16 @@ export class HindsightClient {
78
79
  );
79
80
  }
80
81
 
82
+ /**
83
+ * Validates the API response and throws an error if the request failed.
84
+ */
85
+ private validateResponse<T>(response: { data?: T; error?: unknown }, operation: string): T {
86
+ if (!response.data) {
87
+ throw new Error(`${operation} failed: ${JSON.stringify(response.error || 'Unknown error')}`);
88
+ }
89
+ return response.data;
90
+ }
91
+
81
92
  /**
82
93
  * Retain a single memory for a bank.
83
94
  */
@@ -91,6 +102,8 @@ export class HindsightClient {
91
102
  documentId?: string;
92
103
  async?: boolean;
93
104
  entities?: EntityInput[];
105
+ /** Optional list of tags for this memory */
106
+ tags?: string[];
94
107
  }
95
108
  ): Promise<RetainResponse> {
96
109
  const item: {
@@ -100,6 +113,7 @@ export class HindsightClient {
100
113
  metadata?: Record<string, string>;
101
114
  document_id?: string;
102
115
  entities?: EntityInput[];
116
+ tags?: string[];
103
117
  } = { content };
104
118
  if (options?.timestamp) {
105
119
  item.timestamp =
@@ -119,6 +133,9 @@ export class HindsightClient {
119
133
  if (options?.entities) {
120
134
  item.entities = options.entities;
121
135
  }
136
+ if (options?.tags) {
137
+ item.tags = options.tags;
138
+ }
122
139
 
123
140
  const response = await sdk.retainMemories({
124
141
  client: this.client,
@@ -126,19 +143,20 @@ export class HindsightClient {
126
143
  body: { items: [item], async: options?.async },
127
144
  });
128
145
 
129
- return response.data!;
146
+ return this.validateResponse(response, 'retain');
130
147
  }
131
148
 
132
149
  /**
133
150
  * Retain multiple memories in batch.
134
151
  */
135
- async retainBatch(bankId: string, items: MemoryItemInput[], options?: { documentId?: string; async?: boolean }): Promise<RetainResponse> {
152
+ async retainBatch(bankId: string, items: MemoryItemInput[], options?: { documentId?: string; documentTags?: string[]; async?: boolean }): Promise<RetainResponse> {
136
153
  const processedItems = items.map((item) => ({
137
154
  content: item.content,
138
155
  context: item.context,
139
156
  metadata: item.metadata,
140
157
  document_id: item.document_id,
141
158
  entities: item.entities,
159
+ tags: item.tags,
142
160
  timestamp:
143
161
  item.timestamp instanceof Date
144
162
  ? item.timestamp.toISOString()
@@ -156,11 +174,12 @@ export class HindsightClient {
156
174
  path: { bank_id: bankId },
157
175
  body: {
158
176
  items: itemsWithDocId,
177
+ document_tags: options?.documentTags,
159
178
  async: options?.async,
160
179
  },
161
180
  });
162
181
 
163
- return response.data!;
182
+ return this.validateResponse(response, 'retainBatch');
164
183
  }
165
184
 
166
185
  /**
@@ -179,6 +198,10 @@ export class HindsightClient {
179
198
  maxEntityTokens?: number;
180
199
  includeChunks?: boolean;
181
200
  maxChunkTokens?: number;
201
+ /** Optional list of tags to filter memories by */
202
+ tags?: string[];
203
+ /** How to match tags: 'any' (OR, includes untagged), 'all' (AND, includes untagged), 'any_strict' (OR, excludes untagged), 'all_strict' (AND, excludes untagged). Default: 'any' */
204
+ tagsMatch?: 'any' | 'all' | 'any_strict' | 'all_strict';
182
205
  }
183
206
  ): Promise<RecallResponse> {
184
207
  const response = await sdk.recallMemories({
@@ -195,14 +218,12 @@ export class HindsightClient {
195
218
  entities: options?.includeEntities ? { max_tokens: options?.maxEntityTokens ?? 500 } : undefined,
196
219
  chunks: options?.includeChunks ? { max_tokens: options?.maxChunkTokens ?? 8192 } : undefined,
197
220
  },
221
+ tags: options?.tags,
222
+ tags_match: options?.tagsMatch,
198
223
  },
199
224
  });
200
225
 
201
- if (!response.data) {
202
- throw new Error(`API returned no data: ${JSON.stringify(response.error || 'Unknown error')}`);
203
- }
204
-
205
- return response.data;
226
+ return this.validateResponse(response, 'recall');
206
227
  }
207
228
 
208
229
  /**
@@ -211,7 +232,14 @@ export class HindsightClient {
211
232
  async reflect(
212
233
  bankId: string,
213
234
  query: string,
214
- options?: { context?: string; budget?: Budget }
235
+ options?: {
236
+ context?: string;
237
+ budget?: Budget;
238
+ /** Optional list of tags to filter memories by */
239
+ tags?: string[];
240
+ /** How to match tags: 'any' (OR, includes untagged), 'all' (AND, includes untagged), 'any_strict' (OR, excludes untagged), 'all_strict' (AND, excludes untagged). Default: 'any' */
241
+ tagsMatch?: 'any' | 'all' | 'any_strict' | 'all_strict';
242
+ }
215
243
  ): Promise<ReflectResponse> {
216
244
  const response = await sdk.reflect({
217
245
  client: this.client,
@@ -220,10 +248,12 @@ export class HindsightClient {
220
248
  query,
221
249
  context: options?.context,
222
250
  budget: options?.budget || 'low',
251
+ tags: options?.tags,
252
+ tags_match: options?.tagsMatch,
223
253
  },
224
254
  });
225
255
 
226
- return response.data!;
256
+ return this.validateResponse(response, 'reflect');
227
257
  }
228
258
 
229
259
  /**
@@ -244,7 +274,7 @@ export class HindsightClient {
244
274
  },
245
275
  });
246
276
 
247
- return response.data!;
277
+ return this.validateResponse(response, 'listMemories');
248
278
  }
249
279
 
250
280
  /**
@@ -264,7 +294,7 @@ export class HindsightClient {
264
294
  },
265
295
  });
266
296
 
267
- return response.data!;
297
+ return this.validateResponse(response, 'createBank');
268
298
  }
269
299
 
270
300
  /**
@@ -276,7 +306,239 @@ export class HindsightClient {
276
306
  path: { bank_id: bankId },
277
307
  });
278
308
 
279
- return response.data!;
309
+ return this.validateResponse(response, 'getBankProfile');
310
+ }
311
+
312
+ /**
313
+ * Set or update the mission for a memory bank.
314
+ */
315
+ async setMission(bankId: string, mission: string): Promise<BankProfileResponse> {
316
+ const response = await sdk.createOrUpdateBank({
317
+ client: this.client,
318
+ path: { bank_id: bankId },
319
+ body: { mission },
320
+ });
321
+
322
+ return this.validateResponse(response, 'setMission');
323
+ }
324
+
325
+ /**
326
+ * Delete a bank.
327
+ */
328
+ async deleteBank(bankId: string): Promise<void> {
329
+ const response = await sdk.deleteBank({
330
+ client: this.client,
331
+ path: { bank_id: bankId },
332
+ });
333
+ if (response.error) {
334
+ throw new Error(`deleteBank failed: ${JSON.stringify(response.error)}`);
335
+ }
336
+ }
337
+
338
+ // Directive methods
339
+
340
+ /**
341
+ * Create a directive (hard rule for reflect).
342
+ */
343
+ async createDirective(
344
+ bankId: string,
345
+ name: string,
346
+ content: string,
347
+ options?: {
348
+ priority?: number;
349
+ isActive?: boolean;
350
+ tags?: string[];
351
+ }
352
+ ): Promise<any> {
353
+ const response = await sdk.createDirective({
354
+ client: this.client,
355
+ path: { bank_id: bankId },
356
+ body: {
357
+ name,
358
+ content,
359
+ priority: options?.priority ?? 0,
360
+ is_active: options?.isActive ?? true,
361
+ tags: options?.tags,
362
+ },
363
+ });
364
+
365
+ return this.validateResponse(response, 'createDirective');
366
+ }
367
+
368
+ /**
369
+ * List all directives in a bank.
370
+ */
371
+ async listDirectives(bankId: string, options?: { tags?: string[] }): Promise<any> {
372
+ const response = await sdk.listDirectives({
373
+ client: this.client,
374
+ path: { bank_id: bankId },
375
+ query: { tags: options?.tags },
376
+ });
377
+
378
+ return this.validateResponse(response, 'listDirectives');
379
+ }
380
+
381
+ /**
382
+ * Get a specific directive.
383
+ */
384
+ async getDirective(bankId: string, directiveId: string): Promise<any> {
385
+ const response = await sdk.getDirective({
386
+ client: this.client,
387
+ path: { bank_id: bankId, directive_id: directiveId },
388
+ });
389
+
390
+ return this.validateResponse(response, 'getDirective');
391
+ }
392
+
393
+ /**
394
+ * Update a directive.
395
+ */
396
+ async updateDirective(
397
+ bankId: string,
398
+ directiveId: string,
399
+ options: {
400
+ name?: string;
401
+ content?: string;
402
+ priority?: number;
403
+ isActive?: boolean;
404
+ tags?: string[];
405
+ }
406
+ ): Promise<any> {
407
+ const response = await sdk.updateDirective({
408
+ client: this.client,
409
+ path: { bank_id: bankId, directive_id: directiveId },
410
+ body: {
411
+ name: options.name,
412
+ content: options.content,
413
+ priority: options.priority,
414
+ is_active: options.isActive,
415
+ tags: options.tags,
416
+ },
417
+ });
418
+
419
+ return this.validateResponse(response, 'updateDirective');
420
+ }
421
+
422
+ /**
423
+ * Delete a directive.
424
+ */
425
+ async deleteDirective(bankId: string, directiveId: string): Promise<void> {
426
+ const response = await sdk.deleteDirective({
427
+ client: this.client,
428
+ path: { bank_id: bankId, directive_id: directiveId },
429
+ });
430
+ if (response.error) {
431
+ throw new Error(`deleteDirective failed: ${JSON.stringify(response.error)}`);
432
+ }
433
+ }
434
+
435
+ // Mental Model methods
436
+
437
+ /**
438
+ * Create a mental model (runs reflect in background).
439
+ */
440
+ async createMentalModel(
441
+ bankId: string,
442
+ name: string,
443
+ sourceQuery: string,
444
+ options?: {
445
+ tags?: string[];
446
+ maxTokens?: number;
447
+ trigger?: { refreshAfterConsolidation?: boolean };
448
+ }
449
+ ): Promise<any> {
450
+ const response = await sdk.createMentalModel({
451
+ client: this.client,
452
+ path: { bank_id: bankId },
453
+ body: {
454
+ name,
455
+ source_query: sourceQuery,
456
+ tags: options?.tags,
457
+ max_tokens: options?.maxTokens,
458
+ trigger: options?.trigger ? { refresh_after_consolidation: options.trigger.refreshAfterConsolidation } : undefined,
459
+ },
460
+ });
461
+
462
+ return this.validateResponse(response, 'createMentalModel');
463
+ }
464
+
465
+ /**
466
+ * List all mental models in a bank.
467
+ */
468
+ async listMentalModels(bankId: string, options?: { tags?: string[] }): Promise<any> {
469
+ const response = await sdk.listMentalModels({
470
+ client: this.client,
471
+ path: { bank_id: bankId },
472
+ query: { tags: options?.tags },
473
+ });
474
+
475
+ return this.validateResponse(response, 'listMentalModels');
476
+ }
477
+
478
+ /**
479
+ * Get a specific mental model.
480
+ */
481
+ async getMentalModel(bankId: string, mentalModelId: string): Promise<any> {
482
+ const response = await sdk.getMentalModel({
483
+ client: this.client,
484
+ path: { bank_id: bankId, mental_model_id: mentalModelId },
485
+ });
486
+
487
+ return this.validateResponse(response, 'getMentalModel');
488
+ }
489
+
490
+ /**
491
+ * Refresh a mental model to update with current knowledge.
492
+ */
493
+ async refreshMentalModel(bankId: string, mentalModelId: string): Promise<any> {
494
+ const response = await sdk.refreshMentalModel({
495
+ client: this.client,
496
+ path: { bank_id: bankId, mental_model_id: mentalModelId },
497
+ });
498
+
499
+ return this.validateResponse(response, 'refreshMentalModel');
500
+ }
501
+
502
+ /**
503
+ * Update a mental model's metadata.
504
+ */
505
+ async updateMentalModel(
506
+ bankId: string,
507
+ mentalModelId: string,
508
+ options: {
509
+ name?: string;
510
+ sourceQuery?: string;
511
+ tags?: string[];
512
+ maxTokens?: number;
513
+ trigger?: { refreshAfterConsolidation?: boolean };
514
+ }
515
+ ): Promise<any> {
516
+ const response = await sdk.updateMentalModel({
517
+ client: this.client,
518
+ path: { bank_id: bankId, mental_model_id: mentalModelId },
519
+ body: {
520
+ name: options.name,
521
+ source_query: options.sourceQuery,
522
+ tags: options.tags,
523
+ max_tokens: options.maxTokens,
524
+ trigger: options.trigger ? { refresh_after_consolidation: options.trigger.refreshAfterConsolidation } : undefined,
525
+ },
526
+ });
527
+
528
+ return this.validateResponse(response, 'updateMentalModel');
529
+ }
530
+
531
+ /**
532
+ * Delete a mental model.
533
+ */
534
+ async deleteMentalModel(bankId: string, mentalModelId: string): Promise<void> {
535
+ const response = await sdk.deleteMentalModel({
536
+ client: this.client,
537
+ path: { bank_id: bankId, mental_model_id: mentalModelId },
538
+ });
539
+ if (response.error) {
540
+ throw new Error(`deleteMentalModel failed: ${JSON.stringify(response.error)}`);
541
+ }
280
542
  }
281
543
  }
282
544