hebbrix 2.2.1 → 2.3.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/dist/index.js CHANGED
@@ -25,7 +25,12 @@ __export(index_exports, {
25
25
  CollectionsResource: () => CollectionsResource,
26
26
  ConsolidationResource: () => ConsolidationResource,
27
27
  CorrectionsResource: () => CorrectionsResource,
28
+ EntitlementError: () => EntitlementError,
28
29
  HebbrixError: () => HebbrixError,
30
+ IndexingAbortedError: () => IndexingAbortedError,
31
+ IndexingTerminalError: () => IndexingTerminalError,
32
+ IndexingTimeoutError: () => IndexingTimeoutError,
33
+ IndexingWaitError: () => IndexingWaitError,
29
34
  MemoriesResource: () => MemoriesResource,
30
35
  MemoryClient: () => MemoryClient,
31
36
  MemoryJobsResource: () => MemoryJobsResource,
@@ -40,7 +45,6 @@ __export(index_exports, {
40
45
  TemporalResource: () => TemporalResource,
41
46
  ValidationError: () => ValidationError,
42
47
  WorkingMemoryResource: () => WorkingMemoryResource,
43
- WorldModelResource: () => WorldModelResource,
44
48
  enforceSearchSafety: () => enforceSearchSafety
45
49
  });
46
50
  module.exports = __toCommonJS(index_exports);
@@ -99,6 +103,128 @@ function enforceSearchSafety(response, rowsKey = "results") {
99
103
  return data;
100
104
  }
101
105
 
106
+ // src/errors.ts
107
+ var HebbrixError = class _HebbrixError extends Error {
108
+ constructor(message, statusCode, options = {}) {
109
+ super(message);
110
+ this.name = "HebbrixError";
111
+ this.statusCode = statusCode;
112
+ this.code = options.code;
113
+ this.requestId = options.requestId;
114
+ this.details = options.details;
115
+ Object.setPrototypeOf(this, _HebbrixError.prototype);
116
+ }
117
+ };
118
+ var EntitlementError = class _EntitlementError extends HebbrixError {
119
+ constructor(message, statusCode, options = {}) {
120
+ super(message, statusCode, options);
121
+ this.name = "EntitlementError";
122
+ Object.setPrototypeOf(this, _EntitlementError.prototype);
123
+ }
124
+ };
125
+ var IndexingWaitError = class _IndexingWaitError extends Error {
126
+ constructor(message, receipt, options = {}) {
127
+ super(message);
128
+ this.name = "IndexingWaitError";
129
+ this.receipt = { ...receipt };
130
+ this.memoryIds = [
131
+ ...new Set(
132
+ [
133
+ ...receipt.memory_ids || [],
134
+ receipt.memory_id,
135
+ receipt.id,
136
+ ...(receipt.results || []).map(
137
+ (row) => row.memory_id || row.id
138
+ )
139
+ ].filter(Boolean)
140
+ )
141
+ ];
142
+ this.jobId = receipt.job_id;
143
+ this.statusUrl = receipt.status_url || (this.memoryIds.length === 1 ? `/v1/memories/${encodeURIComponent(this.memoryIds[0])}` : this.jobId ? `/v1/memory-jobs/${encodeURIComponent(this.jobId)}` : void 0);
144
+ this.requestId = receipt.request_id;
145
+ this.outboxEventId = receipt.outbox_event_id;
146
+ this.indexingEventId = receipt.indexing_event_id || this.outboxEventId;
147
+ this.eventId = receipt.event_id || this.indexingEventId;
148
+ this.idempotencyReplay = receipt.idempotency_replay;
149
+ this.idempotencyKey = options.idempotencyKey || receipt.idempotency_key;
150
+ this.retryAfter = receipt.retry_after;
151
+ this.recovery = Object.fromEntries(
152
+ Object.entries({
153
+ memory_ids: this.memoryIds,
154
+ job_id: this.jobId,
155
+ status_url: this.statusUrl,
156
+ request_id: this.requestId,
157
+ outbox_event_id: this.outboxEventId,
158
+ indexing_event_id: this.indexingEventId,
159
+ event_id: this.eventId,
160
+ idempotency_key: this.idempotencyKey,
161
+ idempotency_replay: this.idempotencyReplay,
162
+ retry_after: this.retryAfter
163
+ }).filter(([, value]) => value !== void 0 && value !== null)
164
+ );
165
+ this.cause = options.cause;
166
+ Object.setPrototypeOf(this, _IndexingWaitError.prototype);
167
+ }
168
+ };
169
+ var IndexingTimeoutError = class _IndexingTimeoutError extends IndexingWaitError {
170
+ constructor(message, receipt, options = {}) {
171
+ super(message, receipt, options);
172
+ this.name = "IndexingTimeoutError";
173
+ Object.setPrototypeOf(this, _IndexingTimeoutError.prototype);
174
+ }
175
+ };
176
+ var IndexingAbortedError = class _IndexingAbortedError extends IndexingWaitError {
177
+ constructor(message, receipt, options = {}) {
178
+ super(message, receipt, options);
179
+ this.name = "IndexingAbortedError";
180
+ Object.setPrototypeOf(this, _IndexingAbortedError.prototype);
181
+ }
182
+ };
183
+ var IndexingTerminalError = class _IndexingTerminalError extends IndexingWaitError {
184
+ constructor(message, receipt, processingStatus, options = {}) {
185
+ super(message, receipt, options);
186
+ this.name = "IndexingTerminalError";
187
+ this.processingStatus = processingStatus;
188
+ Object.setPrototypeOf(this, _IndexingTerminalError.prototype);
189
+ }
190
+ };
191
+ var AuthenticationError = class _AuthenticationError extends HebbrixError {
192
+ constructor(message = "Authentication failed", options = {}) {
193
+ super(message, 401, options);
194
+ this.name = "AuthenticationError";
195
+ Object.setPrototypeOf(this, _AuthenticationError.prototype);
196
+ }
197
+ };
198
+ var ValidationError = class _ValidationError extends HebbrixError {
199
+ constructor(message, errors, options = {}) {
200
+ super(message, 422, options);
201
+ this.name = "ValidationError";
202
+ this.errors = errors;
203
+ Object.setPrototypeOf(this, _ValidationError.prototype);
204
+ }
205
+ };
206
+ var NotFoundError = class _NotFoundError extends HebbrixError {
207
+ constructor(message = "Resource not found", options = {}) {
208
+ super(message, 404, options);
209
+ this.name = "NotFoundError";
210
+ Object.setPrototypeOf(this, _NotFoundError.prototype);
211
+ }
212
+ };
213
+ var RateLimitError = class _RateLimitError extends HebbrixError {
214
+ constructor(message = "Rate limit exceeded", options = {}) {
215
+ super(message, 429, options);
216
+ this.name = "RateLimitError";
217
+ Object.setPrototypeOf(this, _RateLimitError.prototype);
218
+ }
219
+ };
220
+ var ServerError = class _ServerError extends HebbrixError {
221
+ constructor(message = "Internal server error", options = {}) {
222
+ super(message, 500, options);
223
+ this.name = "ServerError";
224
+ Object.setPrototypeOf(this, _ServerError.prototype);
225
+ }
226
+ };
227
+
102
228
  // src/resources.ts
103
229
  var BaseResource = class {
104
230
  constructor(client) {
@@ -175,29 +301,202 @@ var CollectionsResource = class extends BaseResource {
175
301
  };
176
302
  var MemoriesResource = class extends BaseResource {
177
303
  /**
178
- * Create a new memory
304
+ * Create one logical memory write. When `wait_for_index=true`, a durable
305
+ * pending receipt is polled without issuing a second create request.
179
306
  */
180
307
  async create(params) {
181
308
  if (!params.content?.trim() && !params.messages?.length) {
182
309
  throw new TypeError("content or messages must be provided");
183
310
  }
184
- const { idempotency_key, ...input } = params;
185
- return this.client.request("POST", "/v1/memories", {
186
- headers: idempotency_key ? { "Idempotency-Key": idempotency_key } : void 0,
187
- body: JSON.stringify({
188
- source_type: "text",
189
- metadata: {},
190
- infer: false,
191
- wait_for_index: false,
192
- ...input
193
- })
311
+ const {
312
+ idempotency_key,
313
+ signal,
314
+ index_timeout_ms,
315
+ index_poll_interval_ms,
316
+ ...input
317
+ } = params;
318
+ const receipt = await this.client.request(
319
+ "POST",
320
+ "/v1/memories",
321
+ {
322
+ headers: idempotency_key ? { "Idempotency-Key": idempotency_key } : void 0,
323
+ body: JSON.stringify({
324
+ source_type: "text",
325
+ metadata: {},
326
+ infer: false,
327
+ wait_for_index: false,
328
+ ...input
329
+ }),
330
+ signal
331
+ }
332
+ );
333
+ if (params.wait_for_index && !this.isSearchableCompletion(receipt)) {
334
+ return this.waitForSearchable(receipt, {
335
+ timeoutMs: index_timeout_ms,
336
+ pollIntervalMs: index_poll_interval_ms,
337
+ signal,
338
+ idempotencyKey: idempotency_key
339
+ });
340
+ }
341
+ return receipt;
342
+ }
343
+ /** Poll a single-write durable receipt until every accepted memory is searchable. */
344
+ async waitForSearchable(receipt, options = {}) {
345
+ if (this.isSearchableCompletion(receipt)) {
346
+ return receipt;
347
+ }
348
+ if (this.isTerminalStatus(receipt.processing_status)) {
349
+ const status = String(receipt.processing_status).toLowerCase();
350
+ throw new IndexingTerminalError(
351
+ `memory indexing reached terminal state ${status}`,
352
+ receipt,
353
+ status,
354
+ { idempotencyKey: options.idempotencyKey }
355
+ );
356
+ }
357
+ const ids = this.memoryIds(receipt);
358
+ if (!ids.length) {
359
+ throw new Error("memory receipt does not contain a durable memory id");
360
+ }
361
+ const timeoutMs = Math.max(0, options.timeoutMs ?? 6e4);
362
+ const pollIntervalMs = Math.max(50, options.pollIntervalMs ?? 500);
363
+ const deadline = Date.now() + timeoutMs;
364
+ const paths = ids.map(
365
+ (id, index) => index === 0 && receipt.status_url ? this.readinessPath(receipt.status_url, id) : `/v1/memories/${encodeURIComponent(id)}`
366
+ );
367
+ while (true) {
368
+ this.throwIfPollingAborted(receipt, options);
369
+ if (Date.now() >= deadline) {
370
+ throw new IndexingTimeoutError(
371
+ `memory was not searchable within ${timeoutMs}ms; the write is durable`,
372
+ receipt,
373
+ { idempotencyKey: options.idempotencyKey }
374
+ );
375
+ }
376
+ let rows;
377
+ try {
378
+ rows = await Promise.all(
379
+ paths.map(
380
+ (path) => this.client.request("GET", path, {
381
+ signal: options.signal
382
+ })
383
+ )
384
+ );
385
+ } catch (error) {
386
+ if (options.signal?.aborted) {
387
+ throw new IndexingAbortedError(
388
+ "memory readiness polling was aborted after the write became durable",
389
+ receipt,
390
+ { idempotencyKey: options.idempotencyKey, cause: error }
391
+ );
392
+ }
393
+ throw error;
394
+ }
395
+ const terminal = rows.find(
396
+ (row) => this.isTerminalStatus(row.processing_status)
397
+ );
398
+ if (terminal) {
399
+ const status = String(terminal.processing_status).toLowerCase();
400
+ throw new IndexingTerminalError(
401
+ `memory ${terminal.id} indexing reached terminal state ${status}`,
402
+ receipt,
403
+ status,
404
+ { idempotencyKey: options.idempotencyKey }
405
+ );
406
+ }
407
+ if (rows.every(
408
+ (row) => row.searchable === true && String(row.processing_status || "").toLowerCase() === "completed"
409
+ )) {
410
+ return {
411
+ ...receipt,
412
+ processing_status: "completed",
413
+ searchable: true,
414
+ results: receipt.results.map((result) => ({
415
+ ...result,
416
+ processing_status: "completed"
417
+ }))
418
+ };
419
+ }
420
+ const remainingMs = deadline - Date.now();
421
+ if (remainingMs <= 0) {
422
+ continue;
423
+ }
424
+ await this.pollingDelay(
425
+ Math.min(pollIntervalMs, remainingMs),
426
+ receipt,
427
+ options
428
+ );
429
+ }
430
+ }
431
+ memoryIds(receipt) {
432
+ return [
433
+ ...new Set(
434
+ (receipt.results || []).map((row) => row.memory_id || row.id).filter((id) => Boolean(id))
435
+ )
436
+ ];
437
+ }
438
+ isSearchableCompletion(receipt) {
439
+ return receipt.searchable === true && String(receipt.processing_status || "").toLowerCase() === "completed";
440
+ }
441
+ isTerminalStatus(status) {
442
+ return ["failed", "cancelled", "canceled"].includes(
443
+ String(status || "").toLowerCase()
444
+ );
445
+ }
446
+ readinessPath(statusUrl, memoryId) {
447
+ try {
448
+ const parsed = new URL(statusUrl, "https://status.hebbrix.invalid");
449
+ if (!["http:", "https:"].includes(parsed.protocol)) {
450
+ return `/v1/memories/${encodeURIComponent(memoryId)}`;
451
+ }
452
+ return `${parsed.pathname}${parsed.search}`;
453
+ } catch {
454
+ return `/v1/memories/${encodeURIComponent(memoryId)}`;
455
+ }
456
+ }
457
+ throwIfPollingAborted(receipt, options) {
458
+ if (options.signal?.aborted) {
459
+ throw new IndexingAbortedError(
460
+ "memory readiness polling was aborted after the write became durable",
461
+ receipt,
462
+ {
463
+ idempotencyKey: options.idempotencyKey,
464
+ cause: options.signal.reason
465
+ }
466
+ );
467
+ }
468
+ }
469
+ async pollingDelay(delayMs, receipt, options) {
470
+ await new Promise((resolve, reject) => {
471
+ const onAbort = () => {
472
+ clearTimeout(timer);
473
+ options.signal?.removeEventListener("abort", onAbort);
474
+ reject(
475
+ new IndexingAbortedError(
476
+ "memory readiness polling was aborted after the write became durable",
477
+ receipt,
478
+ {
479
+ idempotencyKey: options.idempotencyKey,
480
+ cause: options.signal?.reason
481
+ }
482
+ )
483
+ );
484
+ };
485
+ const timer = setTimeout(() => {
486
+ options.signal?.removeEventListener("abort", onAbort);
487
+ resolve();
488
+ }, delayMs);
489
+ options.signal?.addEventListener("abort", onAbort, { once: true });
490
+ if (options.signal?.aborted) {
491
+ onAbort();
492
+ }
194
493
  });
195
494
  }
196
495
  /**
197
496
  * Create up to 100 memories with one unambiguous readiness contract.
198
- * `wait_for_index=true` resolves only for a fully searchable batch; a server
199
- * deadline or indexing failure rejects the request instead of returning a
200
- * successful processing receipt.
497
+ * `wait_for_index=true` resolves only for a fully searchable batch. A durable
498
+ * server-side 202 is polled to the caller's deadline; expiry raises a typed
499
+ * `IndexingTimeoutError` carrying the original durable receipt.
201
500
  */
202
501
  async createBatch(params) {
203
502
  if (!params.memories?.length || params.memories.length > 100) {
@@ -206,7 +505,13 @@ var MemoriesResource = class extends BaseResource {
206
505
  if (params.memories.some((item) => !item.content?.trim())) {
207
506
  throw new TypeError("every batch memory must contain non-empty content");
208
507
  }
209
- const { idempotency_key, signal, ...body } = params;
508
+ const {
509
+ idempotency_key,
510
+ signal,
511
+ index_timeout_ms,
512
+ index_poll_interval_ms,
513
+ ...body
514
+ } = params;
210
515
  const receipt = await this.client.request(
211
516
  "POST",
212
517
  "/v1/memories/batch",
@@ -216,10 +521,12 @@ var MemoriesResource = class extends BaseResource {
216
521
  signal
217
522
  }
218
523
  );
219
- if (params.wait_for_index && !(receipt.searchable === true && receipt.processing_status === "completed")) {
220
- throw new Error(
221
- "wait_for_index batch response was not fully searchable; retry with the same Idempotency-Key"
222
- );
524
+ if (params.wait_for_index && !receipt.searchable) {
525
+ return this.waitForBatchSearchable(receipt, {
526
+ timeoutMs: index_timeout_ms,
527
+ pollIntervalMs: index_poll_interval_ms,
528
+ signal
529
+ });
223
530
  }
224
531
  return receipt;
225
532
  }
@@ -260,7 +567,10 @@ var MemoriesResource = class extends BaseResource {
260
567
  };
261
568
  }
262
569
  if (Date.now() >= deadline) {
263
- throw new Error(`batch was not searchable within ${timeoutMs}ms`);
570
+ throw new IndexingTimeoutError(
571
+ `batch was not searchable within ${timeoutMs}ms; the write is durable`,
572
+ receipt
573
+ );
264
574
  }
265
575
  await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
266
576
  }
@@ -454,8 +764,7 @@ var RLResource = class extends BaseResource {
454
764
  * Train the Memory Manager agent using RL
455
765
  */
456
766
  async trainMemoryManager(params) {
457
- return this.client.post("/rl/train/memory-manager", {
458
- collection_id: params.collection_id,
767
+ return this.client.post("/v1/rl/train/memory-manager", {
459
768
  num_episodes: params.num_episodes || 100,
460
769
  ...params
461
770
  });
@@ -464,8 +773,7 @@ var RLResource = class extends BaseResource {
464
773
  * Train the Answer Agent using RL
465
774
  */
466
775
  async trainAnswerAgent(params) {
467
- return this.client.post("/rl/train/answer-agent", {
468
- collection_id: params.collection_id,
776
+ return this.client.post("/v1/rl/train/answer-agent", {
469
777
  num_episodes: params.num_episodes || 100,
470
778
  ...params
471
779
  });
@@ -474,13 +782,13 @@ var RLResource = class extends BaseResource {
474
782
  * Get RL training metrics
475
783
  */
476
784
  async getMetrics() {
477
- return this.client.get("/rl/metrics");
785
+ return this.client.get("/v1/rl/metrics");
478
786
  }
479
787
  /**
480
788
  * Evaluate a trained RL agent
481
789
  */
482
790
  async evaluate(agentType, collectionId) {
483
- return this.client.post("/rl/evaluate", {
791
+ return this.client.post("/v1/rl/evaluate", {
484
792
  agent_type: agentType,
485
793
  collection_id: collectionId
486
794
  });
@@ -532,9 +840,12 @@ var ProceduralResource = class extends BaseResource {
532
840
  * Execute a procedure
533
841
  */
534
842
  async execute(procedureId, context) {
535
- const response = await this.client.post(`/v1/procedures/${procedureId}/execute`, {
536
- input_state: context || {}
537
- });
843
+ const response = await this.client.post(
844
+ `/v1/procedures/${procedureId}/execute`,
845
+ {
846
+ input_state: context || {}
847
+ }
848
+ );
538
849
  return response?.execution_result || response;
539
850
  }
540
851
  /**
@@ -551,7 +862,10 @@ var ProceduralResource = class extends BaseResource {
551
862
  body.action = { steps: params.action_sequence };
552
863
  }
553
864
  if (params.metadata !== void 0) body.parameters = params.metadata;
554
- const response = await this.client.patch(`/v1/procedures/${procedureId}`, body);
865
+ const response = await this.client.patch(
866
+ `/v1/procedures/${procedureId}`,
867
+ body
868
+ );
555
869
  return this.unwrapProcedure(response);
556
870
  }
557
871
  /**
@@ -566,12 +880,15 @@ var TemporalResource = class extends BaseResource {
566
880
  * Add a temporal fact to the knowledge graph
567
881
  */
568
882
  async addFact(params) {
569
- return this.client.post("/temporal/facts", {
883
+ return this.client.post("/v1/temporal/facts", {
570
884
  subject: params.subject,
885
+ subject_type: params.subject_type || "ENTITY",
571
886
  predicate: params.predicate,
572
887
  object: params.object,
888
+ object_type: params.object_type || "ENTITY",
573
889
  valid_from: params.valid_from,
574
890
  valid_until: params.valid_until,
891
+ observed_at: params.observed_at,
575
892
  confidence: params.confidence || 1,
576
893
  source_memory_id: params.source_memory_id,
577
894
  metadata: params.metadata || {}
@@ -581,33 +898,81 @@ var TemporalResource = class extends BaseResource {
581
898
  * Query temporal facts
582
899
  */
583
900
  async queryFacts(params) {
584
- return this.client.get("/temporal/facts", {
585
- subject: params?.subject,
586
- predicate: params?.predicate,
587
- object: params?.object,
588
- at_time: params?.at_time
901
+ if (!params.subject) {
902
+ throw new TypeError("subject is required by the temporal query contract");
903
+ }
904
+ let rows;
905
+ if (params.at_time) {
906
+ const response = await this.queryAtTime({
907
+ subject: params.subject,
908
+ predicate: params.predicate,
909
+ timestamp: params.at_time
910
+ });
911
+ rows = response.facts || [];
912
+ } else if (params.predicate) {
913
+ const response = await this.history(
914
+ params.subject,
915
+ params.predicate
916
+ );
917
+ rows = response.history || [];
918
+ } else {
919
+ throw new TypeError("predicate or at_time is required");
920
+ }
921
+ return params.object === void 0 ? rows : rows.filter((row) => row.object === params.object);
922
+ }
923
+ async queryAtTime(params) {
924
+ return this.client.post("/v1/temporal/facts/query-at-time", params);
925
+ }
926
+ async history(subject, predicate, limit = 50) {
927
+ return this.client.get("/v1/temporal/facts/history", {
928
+ subject,
929
+ predicate,
930
+ limit
931
+ });
932
+ }
933
+ async conflicts(subject, predicate) {
934
+ return this.client.get("/v1/temporal/facts/conflicts", {
935
+ subject,
936
+ predicate
937
+ });
938
+ }
939
+ async invalidate(subject, predicate, object) {
940
+ return this.client.post("/v1/temporal/facts/invalidate", {
941
+ subject,
942
+ predicate,
943
+ object
589
944
  });
590
945
  }
591
946
  /**
592
947
  * Query knowledge state at a specific point in time
593
948
  */
594
949
  async pointInTime(timestamp, entity) {
595
- return this.client.post("/temporal/point-in-time", {
950
+ if (!entity) {
951
+ throw new TypeError(
952
+ "entity is required and maps to the canonical subject"
953
+ );
954
+ }
955
+ return this.queryAtTime({
596
956
  timestamp,
597
- entity
957
+ subject: entity
598
958
  });
599
959
  }
600
960
  /** Permanently delete a tenant-scoped temporal fact by stable ID. */
601
961
  async deleteFact(factId) {
602
- return this.client.delete(`/temporal/facts/${factId}`);
962
+ return this.client.delete(`/v1/temporal/facts/${factId}`);
603
963
  }
604
964
  };
605
965
  var WorkingMemoryResource = class extends BaseResource {
966
+ constructor(client) {
967
+ super(client);
968
+ this.sessionId = `sdk-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
969
+ }
606
970
  /**
607
971
  * Add item to working memory buffer
608
972
  */
609
973
  async add(params) {
610
- return this.client.post("/working-memory", {
974
+ return this.client.post("/v1/working-memory/add", {
975
+ session_id: params.session_id || this.sessionId,
611
976
  role: params.role,
612
977
  content: params.content,
613
978
  metadata: params.metadata || {}
@@ -616,48 +981,40 @@ var WorkingMemoryResource = class extends BaseResource {
616
981
  /**
617
982
  * Get current working memory context
618
983
  */
619
- async getContext() {
620
- return this.client.get("/working-memory/context");
984
+ async getContext(sessionId = this.sessionId, includeCompressed = false) {
985
+ return this.client.get(`/v1/working-memory/context/${sessionId}`, {
986
+ include_compressed: includeCompressed
987
+ });
621
988
  }
622
989
  /**
623
990
  * Compress working memory buffer
624
991
  */
625
- async compress() {
626
- return this.client.post("/working-memory/compress");
992
+ async compress(sessionId = this.sessionId) {
993
+ return this.client.post(`/v1/working-memory/compress/${sessionId}`);
627
994
  }
628
995
  /**
629
996
  * Clear working memory buffer
630
997
  */
631
- async clear() {
632
- return this.client.delete("/working-memory");
998
+ async clear(sessionId = this.sessionId) {
999
+ return this.client.delete(`/v1/working-memory/clear/${sessionId}`);
633
1000
  }
634
1001
  };
635
1002
  var ConsolidationResource = class extends BaseResource {
636
1003
  /**
637
1004
  * Trigger memory consolidation
638
1005
  */
639
- async consolidate(collectionId, threshold = 100) {
640
- return this.client.post("/consolidation/consolidate", {
1006
+ async consolidate(collectionId, lookbackDays = 7, utilityThreshold = 0.3) {
1007
+ return this.client.post("/v1/consolidation/consolidate", {
641
1008
  collection_id: collectionId,
642
- threshold
1009
+ lookback_days: lookbackDays,
1010
+ utility_threshold: utilityThreshold
643
1011
  });
644
1012
  }
645
1013
  /**
646
1014
  * Get consolidation statistics
647
1015
  */
648
1016
  async getStats(collectionId) {
649
- return this.client.get("/consolidation/stats", {
650
- collection_id: collectionId
651
- });
652
- }
653
- /**
654
- * Archive old memories
655
- */
656
- async archive(collectionId, beforeDate) {
657
- return this.client.post("/consolidation/archive", {
658
- collection_id: collectionId,
659
- before_date: beforeDate
660
- });
1017
+ return this.client.get(`/v1/consolidation/stats/${collectionId}`);
661
1018
  }
662
1019
  };
663
1020
  var MemoryToolsResource = class extends BaseResource {
@@ -665,100 +1022,39 @@ var MemoryToolsResource = class extends BaseResource {
665
1022
  * Replace memory content
666
1023
  */
667
1024
  async replace(params) {
668
- return this.client.post("/memory-tools/replace", {
1025
+ return this.client.post("/v1/memory-tools/replace", {
669
1026
  memory_id: params.memory_id,
1027
+ old_content: params.old_content,
670
1028
  new_content: params.new_content,
671
- reason: params.reason
1029
+ collection_id: params.collection_id
672
1030
  });
673
1031
  }
674
1032
  /**
675
1033
  * Insert new memory at position
676
1034
  */
677
1035
  async insert(params) {
678
- return this.client.post("/memory-tools/insert", {
1036
+ const metadata = { ...params.metadata || {} };
1037
+ if (params.position !== void 0)
1038
+ metadata.requested_position = params.position;
1039
+ if (params.reason !== void 0) metadata.reason = params.reason;
1040
+ return this.client.post("/v1/memory-tools/insert", {
679
1041
  collection_id: params.collection_id,
680
1042
  content: params.content,
681
- position: params.position,
682
- reason: params.reason
1043
+ importance: params.importance ?? 0.5,
1044
+ metadata
683
1045
  });
684
1046
  }
685
1047
  /**
686
1048
  * Re-evaluate memory in light of new information
687
1049
  */
688
- async rethink(memoryId, query) {
689
- return this.client.post("/memory-tools/rethink", {
1050
+ async rethink(memoryId, collectionId) {
1051
+ return this.client.post("/v1/memory-tools/rethink", {
690
1052
  memory_id: memoryId,
691
- query
692
- });
693
- }
694
- };
695
- var WorldModelResource = class extends BaseResource {
696
- /**
697
- * Simulate retrieval without actually retrieving
698
- */
699
- async imagineRetrieval(query, collectionId) {
700
- return this.client.post("/world-model/imagine-retrieval", {
701
- query,
702
- collection_id: collectionId
703
- });
704
- }
705
- /**
706
- * Plan memory operations to achieve goal
707
- */
708
- async plan(goal, collectionId) {
709
- return this.client.post("/world-model/plan", {
710
- goal,
711
1053
  collection_id: collectionId
712
1054
  });
713
1055
  }
714
1056
  };
715
1057
 
716
- // src/errors.ts
717
- var HebbrixError = class _HebbrixError extends Error {
718
- constructor(message, statusCode) {
719
- super(message);
720
- this.name = "HebbrixError";
721
- this.statusCode = statusCode;
722
- Object.setPrototypeOf(this, _HebbrixError.prototype);
723
- }
724
- };
725
- var AuthenticationError = class _AuthenticationError extends HebbrixError {
726
- constructor(message = "Authentication failed") {
727
- super(message, 401);
728
- this.name = "AuthenticationError";
729
- Object.setPrototypeOf(this, _AuthenticationError.prototype);
730
- }
731
- };
732
- var ValidationError = class _ValidationError extends HebbrixError {
733
- constructor(message, errors) {
734
- super(message, 422);
735
- this.name = "ValidationError";
736
- this.errors = errors;
737
- Object.setPrototypeOf(this, _ValidationError.prototype);
738
- }
739
- };
740
- var NotFoundError = class _NotFoundError extends HebbrixError {
741
- constructor(message = "Resource not found") {
742
- super(message, 404);
743
- this.name = "NotFoundError";
744
- Object.setPrototypeOf(this, _NotFoundError.prototype);
745
- }
746
- };
747
- var RateLimitError = class _RateLimitError extends HebbrixError {
748
- constructor(message = "Rate limit exceeded") {
749
- super(message, 429);
750
- this.name = "RateLimitError";
751
- Object.setPrototypeOf(this, _RateLimitError.prototype);
752
- }
753
- };
754
- var ServerError = class _ServerError extends HebbrixError {
755
- constructor(message = "Internal server error") {
756
- super(message, 500);
757
- this.name = "ServerError";
758
- Object.setPrototypeOf(this, _ServerError.prototype);
759
- }
760
- };
761
-
762
1058
  // src/client.ts
763
1059
  var MemoryClient = class {
764
1060
  constructor(config = {}) {
@@ -778,13 +1074,12 @@ var MemoryClient = class {
778
1074
  this.workingMemory = new WorkingMemoryResource(this);
779
1075
  this.consolidation = new ConsolidationResource(this);
780
1076
  this.memoryTools = new MemoryToolsResource(this);
781
- this.worldModel = new WorldModelResource(this);
782
1077
  this.proofloop = new ProofLoopResource(this);
783
1078
  }
784
1079
  getHeaders() {
785
1080
  const headers = {
786
1081
  "Content-Type": "application/json",
787
- "User-Agent": "hebbrix-typescript/2.2.1"
1082
+ "User-Agent": "hebbrix-typescript/2.3.1"
788
1083
  };
789
1084
  if (this.apiKey) {
790
1085
  headers["Authorization"] = `Bearer ${this.apiKey}`;
@@ -793,26 +1088,42 @@ var MemoryClient = class {
793
1088
  }
794
1089
  handleError(response, data) {
795
1090
  const statusCode = response.status;
796
- const detail = data?.detail;
797
- const message = data?.error?.message || (typeof detail === "string" ? detail : detail?.message) || response.statusText;
1091
+ const envelope = data?.error || data?.detail || {};
1092
+ const nested = envelope?.message;
1093
+ const details = nested && typeof nested === "object" ? nested : envelope;
1094
+ const message = details?.message || (typeof nested === "string" ? nested : void 0) || response.statusText;
1095
+ const code = details?.code || envelope?.code;
1096
+ const requestId = details?.request_id || envelope?.request_id || response.headers.get("X-Request-ID") || void 0;
798
1097
  if (statusCode === 401) {
799
- throw new AuthenticationError(message);
1098
+ throw new AuthenticationError(message, { code, requestId, details });
800
1099
  } else if (statusCode === 404) {
801
- throw new NotFoundError(message);
1100
+ throw new NotFoundError(message, { code, requestId, details });
802
1101
  } else if (statusCode === 422) {
803
1102
  const errors = data?.error?.details || [];
804
- throw new ValidationError(message, errors);
1103
+ throw new ValidationError(message, errors, { code, requestId, details });
805
1104
  } else if (statusCode === 429) {
806
- throw new RateLimitError(message);
1105
+ throw new RateLimitError(message, { code, requestId, details });
807
1106
  } else if (statusCode >= 500) {
808
- throw new ServerError(message);
1107
+ throw new ServerError(message, { code, requestId, details });
1108
+ } else if ((statusCode === 402 || statusCode === 403) && (String(code || "").includes("ENTITLEMENT") || ["feature_not_available", "tier_upgrade_required"].includes(
1109
+ details?.error
1110
+ ))) {
1111
+ throw new EntitlementError(message, statusCode, {
1112
+ code,
1113
+ requestId,
1114
+ details
1115
+ });
809
1116
  } else {
810
- throw new HebbrixError(message, statusCode);
1117
+ throw new HebbrixError(message, statusCode, { code, requestId, details });
811
1118
  }
812
1119
  }
813
1120
  async request(method, path, options = {}) {
814
1121
  const url = `${this.baseUrl}${path}`;
815
- const { headers: requestHeaders, signal: requestSignal, ...requestOptions } = options;
1122
+ const {
1123
+ headers: requestHeaders,
1124
+ signal: requestSignal,
1125
+ ...requestOptions
1126
+ } = options;
816
1127
  const response = await fetch(url, {
817
1128
  ...requestOptions,
818
1129
  method,
@@ -839,6 +1150,21 @@ var MemoryClient = class {
839
1150
  if (!response.ok) {
840
1151
  this.handleError(response, data);
841
1152
  }
1153
+ if (data && typeof data === "object" && !Array.isArray(data)) {
1154
+ const requestId = response.headers.get("X-Request-ID");
1155
+ const statusUrl = response.headers.get("Location");
1156
+ const outboxEventId = response.headers.get("X-Hebbrix-Index-Event");
1157
+ const retryAfter = response.headers.get("Retry-After");
1158
+ const idempotencyReplay = response.headers.get("X-Idempotent-Replay");
1159
+ data = {
1160
+ ...data,
1161
+ ...data.request_id === void 0 && requestId ? { request_id: requestId } : {},
1162
+ ...data.status_url === void 0 && statusUrl ? { status_url: statusUrl } : {},
1163
+ ...data.outbox_event_id === void 0 && outboxEventId ? { outbox_event_id: outboxEventId } : {},
1164
+ ...data.retry_after === void 0 && retryAfter ? { retry_after: retryAfter } : {},
1165
+ ...data.idempotency_replay === void 0 && idempotencyReplay ? { idempotency_replay: idempotencyReplay.toLowerCase() === "true" } : {}
1166
+ };
1167
+ }
842
1168
  return data;
843
1169
  }
844
1170
  async get(path, params) {
@@ -889,7 +1215,12 @@ var MemoryClient = class {
889
1215
  CollectionsResource,
890
1216
  ConsolidationResource,
891
1217
  CorrectionsResource,
1218
+ EntitlementError,
892
1219
  HebbrixError,
1220
+ IndexingAbortedError,
1221
+ IndexingTerminalError,
1222
+ IndexingTimeoutError,
1223
+ IndexingWaitError,
893
1224
  MemoriesResource,
894
1225
  MemoryClient,
895
1226
  MemoryJobsResource,
@@ -904,6 +1235,5 @@ var MemoryClient = class {
904
1235
  TemporalResource,
905
1236
  ValidationError,
906
1237
  WorkingMemoryResource,
907
- WorldModelResource,
908
1238
  enforceSearchSafety
909
1239
  });