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.mjs CHANGED
@@ -52,6 +52,128 @@ function enforceSearchSafety(response, rowsKey = "results") {
52
52
  return data;
53
53
  }
54
54
 
55
+ // src/errors.ts
56
+ var HebbrixError = class _HebbrixError extends Error {
57
+ constructor(message, statusCode, options = {}) {
58
+ super(message);
59
+ this.name = "HebbrixError";
60
+ this.statusCode = statusCode;
61
+ this.code = options.code;
62
+ this.requestId = options.requestId;
63
+ this.details = options.details;
64
+ Object.setPrototypeOf(this, _HebbrixError.prototype);
65
+ }
66
+ };
67
+ var EntitlementError = class _EntitlementError extends HebbrixError {
68
+ constructor(message, statusCode, options = {}) {
69
+ super(message, statusCode, options);
70
+ this.name = "EntitlementError";
71
+ Object.setPrototypeOf(this, _EntitlementError.prototype);
72
+ }
73
+ };
74
+ var IndexingWaitError = class _IndexingWaitError extends Error {
75
+ constructor(message, receipt, options = {}) {
76
+ super(message);
77
+ this.name = "IndexingWaitError";
78
+ this.receipt = { ...receipt };
79
+ this.memoryIds = [
80
+ ...new Set(
81
+ [
82
+ ...receipt.memory_ids || [],
83
+ receipt.memory_id,
84
+ receipt.id,
85
+ ...(receipt.results || []).map(
86
+ (row) => row.memory_id || row.id
87
+ )
88
+ ].filter(Boolean)
89
+ )
90
+ ];
91
+ this.jobId = receipt.job_id;
92
+ 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);
93
+ this.requestId = receipt.request_id;
94
+ this.outboxEventId = receipt.outbox_event_id;
95
+ this.indexingEventId = receipt.indexing_event_id || this.outboxEventId;
96
+ this.eventId = receipt.event_id || this.indexingEventId;
97
+ this.idempotencyReplay = receipt.idempotency_replay;
98
+ this.idempotencyKey = options.idempotencyKey || receipt.idempotency_key;
99
+ this.retryAfter = receipt.retry_after;
100
+ this.recovery = Object.fromEntries(
101
+ Object.entries({
102
+ memory_ids: this.memoryIds,
103
+ job_id: this.jobId,
104
+ status_url: this.statusUrl,
105
+ request_id: this.requestId,
106
+ outbox_event_id: this.outboxEventId,
107
+ indexing_event_id: this.indexingEventId,
108
+ event_id: this.eventId,
109
+ idempotency_key: this.idempotencyKey,
110
+ idempotency_replay: this.idempotencyReplay,
111
+ retry_after: this.retryAfter
112
+ }).filter(([, value]) => value !== void 0 && value !== null)
113
+ );
114
+ this.cause = options.cause;
115
+ Object.setPrototypeOf(this, _IndexingWaitError.prototype);
116
+ }
117
+ };
118
+ var IndexingTimeoutError = class _IndexingTimeoutError extends IndexingWaitError {
119
+ constructor(message, receipt, options = {}) {
120
+ super(message, receipt, options);
121
+ this.name = "IndexingTimeoutError";
122
+ Object.setPrototypeOf(this, _IndexingTimeoutError.prototype);
123
+ }
124
+ };
125
+ var IndexingAbortedError = class _IndexingAbortedError extends IndexingWaitError {
126
+ constructor(message, receipt, options = {}) {
127
+ super(message, receipt, options);
128
+ this.name = "IndexingAbortedError";
129
+ Object.setPrototypeOf(this, _IndexingAbortedError.prototype);
130
+ }
131
+ };
132
+ var IndexingTerminalError = class _IndexingTerminalError extends IndexingWaitError {
133
+ constructor(message, receipt, processingStatus, options = {}) {
134
+ super(message, receipt, options);
135
+ this.name = "IndexingTerminalError";
136
+ this.processingStatus = processingStatus;
137
+ Object.setPrototypeOf(this, _IndexingTerminalError.prototype);
138
+ }
139
+ };
140
+ var AuthenticationError = class _AuthenticationError extends HebbrixError {
141
+ constructor(message = "Authentication failed", options = {}) {
142
+ super(message, 401, options);
143
+ this.name = "AuthenticationError";
144
+ Object.setPrototypeOf(this, _AuthenticationError.prototype);
145
+ }
146
+ };
147
+ var ValidationError = class _ValidationError extends HebbrixError {
148
+ constructor(message, errors, options = {}) {
149
+ super(message, 422, options);
150
+ this.name = "ValidationError";
151
+ this.errors = errors;
152
+ Object.setPrototypeOf(this, _ValidationError.prototype);
153
+ }
154
+ };
155
+ var NotFoundError = class _NotFoundError extends HebbrixError {
156
+ constructor(message = "Resource not found", options = {}) {
157
+ super(message, 404, options);
158
+ this.name = "NotFoundError";
159
+ Object.setPrototypeOf(this, _NotFoundError.prototype);
160
+ }
161
+ };
162
+ var RateLimitError = class _RateLimitError extends HebbrixError {
163
+ constructor(message = "Rate limit exceeded", options = {}) {
164
+ super(message, 429, options);
165
+ this.name = "RateLimitError";
166
+ Object.setPrototypeOf(this, _RateLimitError.prototype);
167
+ }
168
+ };
169
+ var ServerError = class _ServerError extends HebbrixError {
170
+ constructor(message = "Internal server error", options = {}) {
171
+ super(message, 500, options);
172
+ this.name = "ServerError";
173
+ Object.setPrototypeOf(this, _ServerError.prototype);
174
+ }
175
+ };
176
+
55
177
  // src/resources.ts
56
178
  var BaseResource = class {
57
179
  constructor(client) {
@@ -128,29 +250,202 @@ var CollectionsResource = class extends BaseResource {
128
250
  };
129
251
  var MemoriesResource = class extends BaseResource {
130
252
  /**
131
- * Create a new memory
253
+ * Create one logical memory write. When `wait_for_index=true`, a durable
254
+ * pending receipt is polled without issuing a second create request.
132
255
  */
133
256
  async create(params) {
134
257
  if (!params.content?.trim() && !params.messages?.length) {
135
258
  throw new TypeError("content or messages must be provided");
136
259
  }
137
- const { idempotency_key, ...input } = params;
138
- return this.client.request("POST", "/v1/memories", {
139
- headers: idempotency_key ? { "Idempotency-Key": idempotency_key } : void 0,
140
- body: JSON.stringify({
141
- source_type: "text",
142
- metadata: {},
143
- infer: false,
144
- wait_for_index: false,
145
- ...input
146
- })
260
+ const {
261
+ idempotency_key,
262
+ signal,
263
+ index_timeout_ms,
264
+ index_poll_interval_ms,
265
+ ...input
266
+ } = params;
267
+ const receipt = await this.client.request(
268
+ "POST",
269
+ "/v1/memories",
270
+ {
271
+ headers: idempotency_key ? { "Idempotency-Key": idempotency_key } : void 0,
272
+ body: JSON.stringify({
273
+ source_type: "text",
274
+ metadata: {},
275
+ infer: false,
276
+ wait_for_index: false,
277
+ ...input
278
+ }),
279
+ signal
280
+ }
281
+ );
282
+ if (params.wait_for_index && !this.isSearchableCompletion(receipt)) {
283
+ return this.waitForSearchable(receipt, {
284
+ timeoutMs: index_timeout_ms,
285
+ pollIntervalMs: index_poll_interval_ms,
286
+ signal,
287
+ idempotencyKey: idempotency_key
288
+ });
289
+ }
290
+ return receipt;
291
+ }
292
+ /** Poll a single-write durable receipt until every accepted memory is searchable. */
293
+ async waitForSearchable(receipt, options = {}) {
294
+ if (this.isSearchableCompletion(receipt)) {
295
+ return receipt;
296
+ }
297
+ if (this.isTerminalStatus(receipt.processing_status)) {
298
+ const status = String(receipt.processing_status).toLowerCase();
299
+ throw new IndexingTerminalError(
300
+ `memory indexing reached terminal state ${status}`,
301
+ receipt,
302
+ status,
303
+ { idempotencyKey: options.idempotencyKey }
304
+ );
305
+ }
306
+ const ids = this.memoryIds(receipt);
307
+ if (!ids.length) {
308
+ throw new Error("memory receipt does not contain a durable memory id");
309
+ }
310
+ const timeoutMs = Math.max(0, options.timeoutMs ?? 6e4);
311
+ const pollIntervalMs = Math.max(50, options.pollIntervalMs ?? 500);
312
+ const deadline = Date.now() + timeoutMs;
313
+ const paths = ids.map(
314
+ (id, index) => index === 0 && receipt.status_url ? this.readinessPath(receipt.status_url, id) : `/v1/memories/${encodeURIComponent(id)}`
315
+ );
316
+ while (true) {
317
+ this.throwIfPollingAborted(receipt, options);
318
+ if (Date.now() >= deadline) {
319
+ throw new IndexingTimeoutError(
320
+ `memory was not searchable within ${timeoutMs}ms; the write is durable`,
321
+ receipt,
322
+ { idempotencyKey: options.idempotencyKey }
323
+ );
324
+ }
325
+ let rows;
326
+ try {
327
+ rows = await Promise.all(
328
+ paths.map(
329
+ (path) => this.client.request("GET", path, {
330
+ signal: options.signal
331
+ })
332
+ )
333
+ );
334
+ } catch (error) {
335
+ if (options.signal?.aborted) {
336
+ throw new IndexingAbortedError(
337
+ "memory readiness polling was aborted after the write became durable",
338
+ receipt,
339
+ { idempotencyKey: options.idempotencyKey, cause: error }
340
+ );
341
+ }
342
+ throw error;
343
+ }
344
+ const terminal = rows.find(
345
+ (row) => this.isTerminalStatus(row.processing_status)
346
+ );
347
+ if (terminal) {
348
+ const status = String(terminal.processing_status).toLowerCase();
349
+ throw new IndexingTerminalError(
350
+ `memory ${terminal.id} indexing reached terminal state ${status}`,
351
+ receipt,
352
+ status,
353
+ { idempotencyKey: options.idempotencyKey }
354
+ );
355
+ }
356
+ if (rows.every(
357
+ (row) => row.searchable === true && String(row.processing_status || "").toLowerCase() === "completed"
358
+ )) {
359
+ return {
360
+ ...receipt,
361
+ processing_status: "completed",
362
+ searchable: true,
363
+ results: receipt.results.map((result) => ({
364
+ ...result,
365
+ processing_status: "completed"
366
+ }))
367
+ };
368
+ }
369
+ const remainingMs = deadline - Date.now();
370
+ if (remainingMs <= 0) {
371
+ continue;
372
+ }
373
+ await this.pollingDelay(
374
+ Math.min(pollIntervalMs, remainingMs),
375
+ receipt,
376
+ options
377
+ );
378
+ }
379
+ }
380
+ memoryIds(receipt) {
381
+ return [
382
+ ...new Set(
383
+ (receipt.results || []).map((row) => row.memory_id || row.id).filter((id) => Boolean(id))
384
+ )
385
+ ];
386
+ }
387
+ isSearchableCompletion(receipt) {
388
+ return receipt.searchable === true && String(receipt.processing_status || "").toLowerCase() === "completed";
389
+ }
390
+ isTerminalStatus(status) {
391
+ return ["failed", "cancelled", "canceled"].includes(
392
+ String(status || "").toLowerCase()
393
+ );
394
+ }
395
+ readinessPath(statusUrl, memoryId) {
396
+ try {
397
+ const parsed = new URL(statusUrl, "https://status.hebbrix.invalid");
398
+ if (!["http:", "https:"].includes(parsed.protocol)) {
399
+ return `/v1/memories/${encodeURIComponent(memoryId)}`;
400
+ }
401
+ return `${parsed.pathname}${parsed.search}`;
402
+ } catch {
403
+ return `/v1/memories/${encodeURIComponent(memoryId)}`;
404
+ }
405
+ }
406
+ throwIfPollingAborted(receipt, options) {
407
+ if (options.signal?.aborted) {
408
+ throw new IndexingAbortedError(
409
+ "memory readiness polling was aborted after the write became durable",
410
+ receipt,
411
+ {
412
+ idempotencyKey: options.idempotencyKey,
413
+ cause: options.signal.reason
414
+ }
415
+ );
416
+ }
417
+ }
418
+ async pollingDelay(delayMs, receipt, options) {
419
+ await new Promise((resolve, reject) => {
420
+ const onAbort = () => {
421
+ clearTimeout(timer);
422
+ options.signal?.removeEventListener("abort", onAbort);
423
+ reject(
424
+ new IndexingAbortedError(
425
+ "memory readiness polling was aborted after the write became durable",
426
+ receipt,
427
+ {
428
+ idempotencyKey: options.idempotencyKey,
429
+ cause: options.signal?.reason
430
+ }
431
+ )
432
+ );
433
+ };
434
+ const timer = setTimeout(() => {
435
+ options.signal?.removeEventListener("abort", onAbort);
436
+ resolve();
437
+ }, delayMs);
438
+ options.signal?.addEventListener("abort", onAbort, { once: true });
439
+ if (options.signal?.aborted) {
440
+ onAbort();
441
+ }
147
442
  });
148
443
  }
149
444
  /**
150
445
  * Create up to 100 memories with one unambiguous readiness contract.
151
- * `wait_for_index=true` resolves only for a fully searchable batch; a server
152
- * deadline or indexing failure rejects the request instead of returning a
153
- * successful processing receipt.
446
+ * `wait_for_index=true` resolves only for a fully searchable batch. A durable
447
+ * server-side 202 is polled to the caller's deadline; expiry raises a typed
448
+ * `IndexingTimeoutError` carrying the original durable receipt.
154
449
  */
155
450
  async createBatch(params) {
156
451
  if (!params.memories?.length || params.memories.length > 100) {
@@ -159,7 +454,13 @@ var MemoriesResource = class extends BaseResource {
159
454
  if (params.memories.some((item) => !item.content?.trim())) {
160
455
  throw new TypeError("every batch memory must contain non-empty content");
161
456
  }
162
- const { idempotency_key, signal, ...body } = params;
457
+ const {
458
+ idempotency_key,
459
+ signal,
460
+ index_timeout_ms,
461
+ index_poll_interval_ms,
462
+ ...body
463
+ } = params;
163
464
  const receipt = await this.client.request(
164
465
  "POST",
165
466
  "/v1/memories/batch",
@@ -169,10 +470,12 @@ var MemoriesResource = class extends BaseResource {
169
470
  signal
170
471
  }
171
472
  );
172
- if (params.wait_for_index && !(receipt.searchable === true && receipt.processing_status === "completed")) {
173
- throw new Error(
174
- "wait_for_index batch response was not fully searchable; retry with the same Idempotency-Key"
175
- );
473
+ if (params.wait_for_index && !receipt.searchable) {
474
+ return this.waitForBatchSearchable(receipt, {
475
+ timeoutMs: index_timeout_ms,
476
+ pollIntervalMs: index_poll_interval_ms,
477
+ signal
478
+ });
176
479
  }
177
480
  return receipt;
178
481
  }
@@ -213,7 +516,10 @@ var MemoriesResource = class extends BaseResource {
213
516
  };
214
517
  }
215
518
  if (Date.now() >= deadline) {
216
- throw new Error(`batch was not searchable within ${timeoutMs}ms`);
519
+ throw new IndexingTimeoutError(
520
+ `batch was not searchable within ${timeoutMs}ms; the write is durable`,
521
+ receipt
522
+ );
217
523
  }
218
524
  await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
219
525
  }
@@ -407,8 +713,7 @@ var RLResource = class extends BaseResource {
407
713
  * Train the Memory Manager agent using RL
408
714
  */
409
715
  async trainMemoryManager(params) {
410
- return this.client.post("/rl/train/memory-manager", {
411
- collection_id: params.collection_id,
716
+ return this.client.post("/v1/rl/train/memory-manager", {
412
717
  num_episodes: params.num_episodes || 100,
413
718
  ...params
414
719
  });
@@ -417,8 +722,7 @@ var RLResource = class extends BaseResource {
417
722
  * Train the Answer Agent using RL
418
723
  */
419
724
  async trainAnswerAgent(params) {
420
- return this.client.post("/rl/train/answer-agent", {
421
- collection_id: params.collection_id,
725
+ return this.client.post("/v1/rl/train/answer-agent", {
422
726
  num_episodes: params.num_episodes || 100,
423
727
  ...params
424
728
  });
@@ -427,13 +731,13 @@ var RLResource = class extends BaseResource {
427
731
  * Get RL training metrics
428
732
  */
429
733
  async getMetrics() {
430
- return this.client.get("/rl/metrics");
734
+ return this.client.get("/v1/rl/metrics");
431
735
  }
432
736
  /**
433
737
  * Evaluate a trained RL agent
434
738
  */
435
739
  async evaluate(agentType, collectionId) {
436
- return this.client.post("/rl/evaluate", {
740
+ return this.client.post("/v1/rl/evaluate", {
437
741
  agent_type: agentType,
438
742
  collection_id: collectionId
439
743
  });
@@ -485,9 +789,12 @@ var ProceduralResource = class extends BaseResource {
485
789
  * Execute a procedure
486
790
  */
487
791
  async execute(procedureId, context) {
488
- const response = await this.client.post(`/v1/procedures/${procedureId}/execute`, {
489
- input_state: context || {}
490
- });
792
+ const response = await this.client.post(
793
+ `/v1/procedures/${procedureId}/execute`,
794
+ {
795
+ input_state: context || {}
796
+ }
797
+ );
491
798
  return response?.execution_result || response;
492
799
  }
493
800
  /**
@@ -504,7 +811,10 @@ var ProceduralResource = class extends BaseResource {
504
811
  body.action = { steps: params.action_sequence };
505
812
  }
506
813
  if (params.metadata !== void 0) body.parameters = params.metadata;
507
- const response = await this.client.patch(`/v1/procedures/${procedureId}`, body);
814
+ const response = await this.client.patch(
815
+ `/v1/procedures/${procedureId}`,
816
+ body
817
+ );
508
818
  return this.unwrapProcedure(response);
509
819
  }
510
820
  /**
@@ -519,12 +829,15 @@ var TemporalResource = class extends BaseResource {
519
829
  * Add a temporal fact to the knowledge graph
520
830
  */
521
831
  async addFact(params) {
522
- return this.client.post("/temporal/facts", {
832
+ return this.client.post("/v1/temporal/facts", {
523
833
  subject: params.subject,
834
+ subject_type: params.subject_type || "ENTITY",
524
835
  predicate: params.predicate,
525
836
  object: params.object,
837
+ object_type: params.object_type || "ENTITY",
526
838
  valid_from: params.valid_from,
527
839
  valid_until: params.valid_until,
840
+ observed_at: params.observed_at,
528
841
  confidence: params.confidence || 1,
529
842
  source_memory_id: params.source_memory_id,
530
843
  metadata: params.metadata || {}
@@ -534,33 +847,81 @@ var TemporalResource = class extends BaseResource {
534
847
  * Query temporal facts
535
848
  */
536
849
  async queryFacts(params) {
537
- return this.client.get("/temporal/facts", {
538
- subject: params?.subject,
539
- predicate: params?.predicate,
540
- object: params?.object,
541
- at_time: params?.at_time
850
+ if (!params.subject) {
851
+ throw new TypeError("subject is required by the temporal query contract");
852
+ }
853
+ let rows;
854
+ if (params.at_time) {
855
+ const response = await this.queryAtTime({
856
+ subject: params.subject,
857
+ predicate: params.predicate,
858
+ timestamp: params.at_time
859
+ });
860
+ rows = response.facts || [];
861
+ } else if (params.predicate) {
862
+ const response = await this.history(
863
+ params.subject,
864
+ params.predicate
865
+ );
866
+ rows = response.history || [];
867
+ } else {
868
+ throw new TypeError("predicate or at_time is required");
869
+ }
870
+ return params.object === void 0 ? rows : rows.filter((row) => row.object === params.object);
871
+ }
872
+ async queryAtTime(params) {
873
+ return this.client.post("/v1/temporal/facts/query-at-time", params);
874
+ }
875
+ async history(subject, predicate, limit = 50) {
876
+ return this.client.get("/v1/temporal/facts/history", {
877
+ subject,
878
+ predicate,
879
+ limit
880
+ });
881
+ }
882
+ async conflicts(subject, predicate) {
883
+ return this.client.get("/v1/temporal/facts/conflicts", {
884
+ subject,
885
+ predicate
886
+ });
887
+ }
888
+ async invalidate(subject, predicate, object) {
889
+ return this.client.post("/v1/temporal/facts/invalidate", {
890
+ subject,
891
+ predicate,
892
+ object
542
893
  });
543
894
  }
544
895
  /**
545
896
  * Query knowledge state at a specific point in time
546
897
  */
547
898
  async pointInTime(timestamp, entity) {
548
- return this.client.post("/temporal/point-in-time", {
899
+ if (!entity) {
900
+ throw new TypeError(
901
+ "entity is required and maps to the canonical subject"
902
+ );
903
+ }
904
+ return this.queryAtTime({
549
905
  timestamp,
550
- entity
906
+ subject: entity
551
907
  });
552
908
  }
553
909
  /** Permanently delete a tenant-scoped temporal fact by stable ID. */
554
910
  async deleteFact(factId) {
555
- return this.client.delete(`/temporal/facts/${factId}`);
911
+ return this.client.delete(`/v1/temporal/facts/${factId}`);
556
912
  }
557
913
  };
558
914
  var WorkingMemoryResource = class extends BaseResource {
915
+ constructor(client) {
916
+ super(client);
917
+ this.sessionId = `sdk-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
918
+ }
559
919
  /**
560
920
  * Add item to working memory buffer
561
921
  */
562
922
  async add(params) {
563
- return this.client.post("/working-memory", {
923
+ return this.client.post("/v1/working-memory/add", {
924
+ session_id: params.session_id || this.sessionId,
564
925
  role: params.role,
565
926
  content: params.content,
566
927
  metadata: params.metadata || {}
@@ -569,48 +930,40 @@ var WorkingMemoryResource = class extends BaseResource {
569
930
  /**
570
931
  * Get current working memory context
571
932
  */
572
- async getContext() {
573
- return this.client.get("/working-memory/context");
933
+ async getContext(sessionId = this.sessionId, includeCompressed = false) {
934
+ return this.client.get(`/v1/working-memory/context/${sessionId}`, {
935
+ include_compressed: includeCompressed
936
+ });
574
937
  }
575
938
  /**
576
939
  * Compress working memory buffer
577
940
  */
578
- async compress() {
579
- return this.client.post("/working-memory/compress");
941
+ async compress(sessionId = this.sessionId) {
942
+ return this.client.post(`/v1/working-memory/compress/${sessionId}`);
580
943
  }
581
944
  /**
582
945
  * Clear working memory buffer
583
946
  */
584
- async clear() {
585
- return this.client.delete("/working-memory");
947
+ async clear(sessionId = this.sessionId) {
948
+ return this.client.delete(`/v1/working-memory/clear/${sessionId}`);
586
949
  }
587
950
  };
588
951
  var ConsolidationResource = class extends BaseResource {
589
952
  /**
590
953
  * Trigger memory consolidation
591
954
  */
592
- async consolidate(collectionId, threshold = 100) {
593
- return this.client.post("/consolidation/consolidate", {
955
+ async consolidate(collectionId, lookbackDays = 7, utilityThreshold = 0.3) {
956
+ return this.client.post("/v1/consolidation/consolidate", {
594
957
  collection_id: collectionId,
595
- threshold
958
+ lookback_days: lookbackDays,
959
+ utility_threshold: utilityThreshold
596
960
  });
597
961
  }
598
962
  /**
599
963
  * Get consolidation statistics
600
964
  */
601
965
  async getStats(collectionId) {
602
- return this.client.get("/consolidation/stats", {
603
- collection_id: collectionId
604
- });
605
- }
606
- /**
607
- * Archive old memories
608
- */
609
- async archive(collectionId, beforeDate) {
610
- return this.client.post("/consolidation/archive", {
611
- collection_id: collectionId,
612
- before_date: beforeDate
613
- });
966
+ return this.client.get(`/v1/consolidation/stats/${collectionId}`);
614
967
  }
615
968
  };
616
969
  var MemoryToolsResource = class extends BaseResource {
@@ -618,100 +971,39 @@ var MemoryToolsResource = class extends BaseResource {
618
971
  * Replace memory content
619
972
  */
620
973
  async replace(params) {
621
- return this.client.post("/memory-tools/replace", {
974
+ return this.client.post("/v1/memory-tools/replace", {
622
975
  memory_id: params.memory_id,
976
+ old_content: params.old_content,
623
977
  new_content: params.new_content,
624
- reason: params.reason
978
+ collection_id: params.collection_id
625
979
  });
626
980
  }
627
981
  /**
628
982
  * Insert new memory at position
629
983
  */
630
984
  async insert(params) {
631
- return this.client.post("/memory-tools/insert", {
985
+ const metadata = { ...params.metadata || {} };
986
+ if (params.position !== void 0)
987
+ metadata.requested_position = params.position;
988
+ if (params.reason !== void 0) metadata.reason = params.reason;
989
+ return this.client.post("/v1/memory-tools/insert", {
632
990
  collection_id: params.collection_id,
633
991
  content: params.content,
634
- position: params.position,
635
- reason: params.reason
992
+ importance: params.importance ?? 0.5,
993
+ metadata
636
994
  });
637
995
  }
638
996
  /**
639
997
  * Re-evaluate memory in light of new information
640
998
  */
641
- async rethink(memoryId, query) {
642
- return this.client.post("/memory-tools/rethink", {
999
+ async rethink(memoryId, collectionId) {
1000
+ return this.client.post("/v1/memory-tools/rethink", {
643
1001
  memory_id: memoryId,
644
- query
645
- });
646
- }
647
- };
648
- var WorldModelResource = class extends BaseResource {
649
- /**
650
- * Simulate retrieval without actually retrieving
651
- */
652
- async imagineRetrieval(query, collectionId) {
653
- return this.client.post("/world-model/imagine-retrieval", {
654
- query,
655
- collection_id: collectionId
656
- });
657
- }
658
- /**
659
- * Plan memory operations to achieve goal
660
- */
661
- async plan(goal, collectionId) {
662
- return this.client.post("/world-model/plan", {
663
- goal,
664
1002
  collection_id: collectionId
665
1003
  });
666
1004
  }
667
1005
  };
668
1006
 
669
- // src/errors.ts
670
- var HebbrixError = class _HebbrixError extends Error {
671
- constructor(message, statusCode) {
672
- super(message);
673
- this.name = "HebbrixError";
674
- this.statusCode = statusCode;
675
- Object.setPrototypeOf(this, _HebbrixError.prototype);
676
- }
677
- };
678
- var AuthenticationError = class _AuthenticationError extends HebbrixError {
679
- constructor(message = "Authentication failed") {
680
- super(message, 401);
681
- this.name = "AuthenticationError";
682
- Object.setPrototypeOf(this, _AuthenticationError.prototype);
683
- }
684
- };
685
- var ValidationError = class _ValidationError extends HebbrixError {
686
- constructor(message, errors) {
687
- super(message, 422);
688
- this.name = "ValidationError";
689
- this.errors = errors;
690
- Object.setPrototypeOf(this, _ValidationError.prototype);
691
- }
692
- };
693
- var NotFoundError = class _NotFoundError extends HebbrixError {
694
- constructor(message = "Resource not found") {
695
- super(message, 404);
696
- this.name = "NotFoundError";
697
- Object.setPrototypeOf(this, _NotFoundError.prototype);
698
- }
699
- };
700
- var RateLimitError = class _RateLimitError extends HebbrixError {
701
- constructor(message = "Rate limit exceeded") {
702
- super(message, 429);
703
- this.name = "RateLimitError";
704
- Object.setPrototypeOf(this, _RateLimitError.prototype);
705
- }
706
- };
707
- var ServerError = class _ServerError extends HebbrixError {
708
- constructor(message = "Internal server error") {
709
- super(message, 500);
710
- this.name = "ServerError";
711
- Object.setPrototypeOf(this, _ServerError.prototype);
712
- }
713
- };
714
-
715
1007
  // src/client.ts
716
1008
  var MemoryClient = class {
717
1009
  constructor(config = {}) {
@@ -731,13 +1023,12 @@ var MemoryClient = class {
731
1023
  this.workingMemory = new WorkingMemoryResource(this);
732
1024
  this.consolidation = new ConsolidationResource(this);
733
1025
  this.memoryTools = new MemoryToolsResource(this);
734
- this.worldModel = new WorldModelResource(this);
735
1026
  this.proofloop = new ProofLoopResource(this);
736
1027
  }
737
1028
  getHeaders() {
738
1029
  const headers = {
739
1030
  "Content-Type": "application/json",
740
- "User-Agent": "hebbrix-typescript/2.2.1"
1031
+ "User-Agent": "hebbrix-typescript/2.3.1"
741
1032
  };
742
1033
  if (this.apiKey) {
743
1034
  headers["Authorization"] = `Bearer ${this.apiKey}`;
@@ -746,26 +1037,42 @@ var MemoryClient = class {
746
1037
  }
747
1038
  handleError(response, data) {
748
1039
  const statusCode = response.status;
749
- const detail = data?.detail;
750
- const message = data?.error?.message || (typeof detail === "string" ? detail : detail?.message) || response.statusText;
1040
+ const envelope = data?.error || data?.detail || {};
1041
+ const nested = envelope?.message;
1042
+ const details = nested && typeof nested === "object" ? nested : envelope;
1043
+ const message = details?.message || (typeof nested === "string" ? nested : void 0) || response.statusText;
1044
+ const code = details?.code || envelope?.code;
1045
+ const requestId = details?.request_id || envelope?.request_id || response.headers.get("X-Request-ID") || void 0;
751
1046
  if (statusCode === 401) {
752
- throw new AuthenticationError(message);
1047
+ throw new AuthenticationError(message, { code, requestId, details });
753
1048
  } else if (statusCode === 404) {
754
- throw new NotFoundError(message);
1049
+ throw new NotFoundError(message, { code, requestId, details });
755
1050
  } else if (statusCode === 422) {
756
1051
  const errors = data?.error?.details || [];
757
- throw new ValidationError(message, errors);
1052
+ throw new ValidationError(message, errors, { code, requestId, details });
758
1053
  } else if (statusCode === 429) {
759
- throw new RateLimitError(message);
1054
+ throw new RateLimitError(message, { code, requestId, details });
760
1055
  } else if (statusCode >= 500) {
761
- throw new ServerError(message);
1056
+ throw new ServerError(message, { code, requestId, details });
1057
+ } else if ((statusCode === 402 || statusCode === 403) && (String(code || "").includes("ENTITLEMENT") || ["feature_not_available", "tier_upgrade_required"].includes(
1058
+ details?.error
1059
+ ))) {
1060
+ throw new EntitlementError(message, statusCode, {
1061
+ code,
1062
+ requestId,
1063
+ details
1064
+ });
762
1065
  } else {
763
- throw new HebbrixError(message, statusCode);
1066
+ throw new HebbrixError(message, statusCode, { code, requestId, details });
764
1067
  }
765
1068
  }
766
1069
  async request(method, path, options = {}) {
767
1070
  const url = `${this.baseUrl}${path}`;
768
- const { headers: requestHeaders, signal: requestSignal, ...requestOptions } = options;
1071
+ const {
1072
+ headers: requestHeaders,
1073
+ signal: requestSignal,
1074
+ ...requestOptions
1075
+ } = options;
769
1076
  const response = await fetch(url, {
770
1077
  ...requestOptions,
771
1078
  method,
@@ -792,6 +1099,21 @@ var MemoryClient = class {
792
1099
  if (!response.ok) {
793
1100
  this.handleError(response, data);
794
1101
  }
1102
+ if (data && typeof data === "object" && !Array.isArray(data)) {
1103
+ const requestId = response.headers.get("X-Request-ID");
1104
+ const statusUrl = response.headers.get("Location");
1105
+ const outboxEventId = response.headers.get("X-Hebbrix-Index-Event");
1106
+ const retryAfter = response.headers.get("Retry-After");
1107
+ const idempotencyReplay = response.headers.get("X-Idempotent-Replay");
1108
+ data = {
1109
+ ...data,
1110
+ ...data.request_id === void 0 && requestId ? { request_id: requestId } : {},
1111
+ ...data.status_url === void 0 && statusUrl ? { status_url: statusUrl } : {},
1112
+ ...data.outbox_event_id === void 0 && outboxEventId ? { outbox_event_id: outboxEventId } : {},
1113
+ ...data.retry_after === void 0 && retryAfter ? { retry_after: retryAfter } : {},
1114
+ ...data.idempotency_replay === void 0 && idempotencyReplay ? { idempotency_replay: idempotencyReplay.toLowerCase() === "true" } : {}
1115
+ };
1116
+ }
795
1117
  return data;
796
1118
  }
797
1119
  async get(path, params) {
@@ -841,7 +1163,12 @@ export {
841
1163
  CollectionsResource,
842
1164
  ConsolidationResource,
843
1165
  CorrectionsResource,
1166
+ EntitlementError,
844
1167
  HebbrixError,
1168
+ IndexingAbortedError,
1169
+ IndexingTerminalError,
1170
+ IndexingTimeoutError,
1171
+ IndexingWaitError,
845
1172
  MemoriesResource,
846
1173
  MemoryClient,
847
1174
  MemoryJobsResource,
@@ -856,6 +1183,5 @@ export {
856
1183
  TemporalResource,
857
1184
  ValidationError,
858
1185
  WorkingMemoryResource,
859
- WorldModelResource,
860
1186
  enforceSearchSafety
861
1187
  };