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.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
|
|
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 {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
|
152
|
-
*
|
|
153
|
-
*
|
|
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 {
|
|
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 && !
|
|
173
|
-
|
|
174
|
-
|
|
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
|
|
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(
|
|
489
|
-
|
|
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(
|
|
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
|
-
|
|
538
|
-
subject
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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,
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
635
|
-
|
|
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,
|
|
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.
|
|
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
|
|
750
|
-
const
|
|
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 {
|
|
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
|
};
|