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/CHANGELOG.md +22 -0
- package/README.md +78 -743
- package/dist/index.d.mts +144 -38
- package/dist/index.d.ts +144 -38
- package/dist/index.js +477 -147
- package/dist/index.mjs +472 -146
- package/package.json +4 -4
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
|
|
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 {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
|
199
|
-
*
|
|
200
|
-
*
|
|
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 {
|
|
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 && !
|
|
220
|
-
|
|
221
|
-
|
|
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
|
|
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(
|
|
536
|
-
|
|
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(
|
|
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
|
-
|
|
585
|
-
subject
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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,
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
682
|
-
|
|
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,
|
|
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.
|
|
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
|
|
797
|
-
const
|
|
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 {
|
|
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
|
});
|