hebbrix 2.2.0 → 2.2.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 +27 -0
- package/README.md +16 -0
- package/dist/index.d.mts +59 -4
- package/dist/index.d.ts +59 -4
- package/dist/index.js +130 -21
- package/dist/index.mjs +130 -21
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 2.2.1 — 2026-08-26
|
|
4
|
+
|
|
5
|
+
- Preserve bearer authentication, content type, user agent, idempotency, and
|
|
6
|
+
caller-supplied headers on every request.
|
|
7
|
+
- Handle `204`, empty, and non-JSON successful responses without attempting an
|
|
8
|
+
unconditional JSON parse.
|
|
9
|
+
- Preserve valid evidence-bound search rows during a degraded or abstaining
|
|
10
|
+
server response while retaining the safety metadata; malformed and explicit
|
|
11
|
+
no-match envelopes still fail closed.
|
|
12
|
+
- Preserve caller-provided abort signals while retaining the default timeout.
|
|
13
|
+
- Add `temporal.deleteFact(factId)` for tenant-scoped, idempotent cleanup of
|
|
14
|
+
facts created through the temporal API.
|
|
15
|
+
- Align procedure create/list/get/update/execute/delete with the canonical
|
|
16
|
+
`/v1/procedures` REST and OpenAPI contract, including empty `204` deletion.
|
|
17
|
+
- Add explicit synchronous/asynchronous batch readiness receipts and
|
|
18
|
+
`waitForBatchSearchable`, which polls every accepted memory, propagates
|
|
19
|
+
terminal failures, respects deadlines, and supports cancellation.
|
|
20
|
+
|
|
21
|
+
The supported server/SDK release pair is published by the server OpenAPI
|
|
22
|
+
document in `info.x-hebbrix-sdk-compatibility`. Patch releases preserve the
|
|
23
|
+
public API within the same major version.
|
|
24
|
+
|
|
25
|
+
## 2.2.0
|
|
26
|
+
|
|
27
|
+
- Added the GA scoped memory, corrections, search proof, and ProofLoop surface.
|
package/README.md
CHANGED
|
@@ -50,8 +50,22 @@ const main = async () => {
|
|
|
50
50
|
collection_id: collection.id,
|
|
51
51
|
content: 'User prefers dark mode and loves TypeScript',
|
|
52
52
|
importance: 0.9,
|
|
53
|
+
wait_for_index: true,
|
|
53
54
|
});
|
|
54
55
|
|
|
56
|
+
// Batch writes have an explicit two-mode contract. With wait_for_index=true,
|
|
57
|
+
// success means every item is searchable; a server deadline rejects with a
|
|
58
|
+
// retryable error instead of returning a misleading successful 202.
|
|
59
|
+
const batch = await client.memories.createBatch({
|
|
60
|
+
memories: [{ content: 'First fact' }, { content: 'Second fact' }],
|
|
61
|
+
collection_id: collection.id,
|
|
62
|
+
wait_for_index: true,
|
|
63
|
+
idempotency_key: 'import-42',
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// For fire-and-forget batches, poll every item (with timeout/cancellation):
|
|
67
|
+
// await client.memories.waitForBatchSearchable(batch, { signal });
|
|
68
|
+
|
|
55
69
|
// Search memories
|
|
56
70
|
const results = await client.search({
|
|
57
71
|
query: 'What programming language does user like?',
|
|
@@ -322,6 +336,8 @@ const updated = await client.procedural.update(procedure.id, {
|
|
|
322
336
|
|
|
323
337
|
// Delete procedure
|
|
324
338
|
await client.procedural.delete(procedure.id);
|
|
339
|
+
// DELETE is tenant-scoped and idempotent: deleted, absent, and foreign IDs all
|
|
340
|
+
// return 204 without revealing whether another tenant owns the identifier.
|
|
325
341
|
```
|
|
326
342
|
|
|
327
343
|
### 8. Temporal Knowledge Graphs
|
package/dist/index.d.mts
CHANGED
|
@@ -175,6 +175,45 @@ interface MemoryAddResponse {
|
|
|
175
175
|
updated_count: number;
|
|
176
176
|
skipped_count: number;
|
|
177
177
|
}
|
|
178
|
+
interface BatchMemoryItemParams {
|
|
179
|
+
content: string;
|
|
180
|
+
collection_id?: string;
|
|
181
|
+
importance?: number;
|
|
182
|
+
user_id?: string;
|
|
183
|
+
agent_id?: string;
|
|
184
|
+
run_id?: string;
|
|
185
|
+
tags?: string[];
|
|
186
|
+
metadata?: Record<string, any>;
|
|
187
|
+
}
|
|
188
|
+
interface BatchMemoryCreateParams {
|
|
189
|
+
memories: BatchMemoryItemParams[];
|
|
190
|
+
collection_id?: string;
|
|
191
|
+
user_id?: string;
|
|
192
|
+
agent_id?: string;
|
|
193
|
+
run_id?: string;
|
|
194
|
+
app_id?: string;
|
|
195
|
+
namespace?: string;
|
|
196
|
+
wait_for_index?: boolean;
|
|
197
|
+
/** Stable retry key sent as the Idempotency-Key transport header. */
|
|
198
|
+
idempotency_key?: string;
|
|
199
|
+
/** Optional caller cancellation signal; it is never serialized. */
|
|
200
|
+
signal?: AbortSignal;
|
|
201
|
+
}
|
|
202
|
+
interface BatchMemoryResponse {
|
|
203
|
+
created: number;
|
|
204
|
+
failed: number;
|
|
205
|
+
memory_ids: string[];
|
|
206
|
+
errors: string[];
|
|
207
|
+
results: Array<{
|
|
208
|
+
id: string;
|
|
209
|
+
memory_id?: string;
|
|
210
|
+
processing_status: string;
|
|
211
|
+
}>;
|
|
212
|
+
processing_status: string;
|
|
213
|
+
searchable: boolean;
|
|
214
|
+
outbox_event_id?: string;
|
|
215
|
+
status_url?: string;
|
|
216
|
+
}
|
|
178
217
|
interface UpdateMemoryParams {
|
|
179
218
|
content?: string;
|
|
180
219
|
importance?: number;
|
|
@@ -324,6 +363,19 @@ declare class MemoriesResource extends BaseResource {
|
|
|
324
363
|
* Create a new memory
|
|
325
364
|
*/
|
|
326
365
|
create(params: CreateMemoryParams): Promise<MemoryAddResponse>;
|
|
366
|
+
/**
|
|
367
|
+
* Create up to 100 memories with one unambiguous readiness contract.
|
|
368
|
+
* `wait_for_index=true` resolves only for a fully searchable batch; a server
|
|
369
|
+
* deadline or indexing failure rejects the request instead of returning a
|
|
370
|
+
* successful processing receipt.
|
|
371
|
+
*/
|
|
372
|
+
createBatch(params: BatchMemoryCreateParams): Promise<BatchMemoryResponse>;
|
|
373
|
+
/** Poll every item in an asynchronous batch receipt until it is searchable. */
|
|
374
|
+
waitForBatchSearchable(receipt: BatchMemoryResponse, options?: {
|
|
375
|
+
timeoutMs?: number;
|
|
376
|
+
pollIntervalMs?: number;
|
|
377
|
+
signal?: AbortSignal;
|
|
378
|
+
}): Promise<BatchMemoryResponse>;
|
|
327
379
|
/**
|
|
328
380
|
* List memories
|
|
329
381
|
*/
|
|
@@ -429,6 +481,7 @@ declare class RLResource extends BaseResource {
|
|
|
429
481
|
evaluate(agentType: string, collectionId?: string): Promise<any>;
|
|
430
482
|
}
|
|
431
483
|
declare class ProceduralResource extends BaseResource {
|
|
484
|
+
private unwrapProcedure;
|
|
432
485
|
/**
|
|
433
486
|
* Create a new procedure
|
|
434
487
|
*/
|
|
@@ -500,6 +553,8 @@ declare class TemporalResource extends BaseResource {
|
|
|
500
553
|
* Query knowledge state at a specific point in time
|
|
501
554
|
*/
|
|
502
555
|
pointInTime(timestamp: string, entity?: string): Promise<any>;
|
|
556
|
+
/** Permanently delete a tenant-scoped temporal fact by stable ID. */
|
|
557
|
+
deleteFact(factId: string): Promise<any>;
|
|
503
558
|
}
|
|
504
559
|
declare class WorkingMemoryResource extends BaseResource {
|
|
505
560
|
/**
|
|
@@ -640,10 +695,10 @@ interface SafetyEnvelope {
|
|
|
640
695
|
}
|
|
641
696
|
/**
|
|
642
697
|
* Validate the API-owned grounding receipt before exposing evidence to an agent.
|
|
643
|
-
* A malformed
|
|
644
|
-
*
|
|
645
|
-
*
|
|
698
|
+
* A malformed or explicit no-match response is converted into one deterministic
|
|
699
|
+
* no-match envelope. Degraded, evidence-bound rows remain visible together with
|
|
700
|
+
* the API's abstention signal so the SDK cannot introduce a false negative.
|
|
646
701
|
*/
|
|
647
702
|
declare function enforceSearchSafety<T extends object>(response: T, rowsKey?: "results" | "sources"): T & SafetyEnvelope;
|
|
648
703
|
|
|
649
|
-
export { type APIKeyResponse, AuthResource, type AuthResponse, AuthenticationError, type ClientConfig, type Collection, CollectionsResource, ConsolidationResource, type CorrectionCreateParams, type CorrectionSearchParams, CorrectionsResource, type CreateCollectionParams, type CreateMemoryParams, type CursorPage, type EvidenceClaim, type GroundingReceipt, HebbrixError, type ListParams, MemoriesResource, type Memory, type MemoryAddResponse, type MemoryAddResult, MemoryClient, type MemoryJobReceipt, MemoryJobsResource, type MemoryListParams, MemoryToolsResource, type MemoryWithMetadata, NotFoundError, ProceduralResource, type ProofContext, type ProofLoopCandidate, type ProofLoopDecisionParams, type ProofLoopMetricParams, ProofLoopResource, RLResource, RateLimitError, type ReasonParams, type ReasoningResponse, type ReasoningSource, type SafetyEnvelope, type SearchParams, SearchResource, type SearchResponse, type SearchResult, ServerError, TemporalResource, type UpdateCollectionParams, type UpdateMemoryParams, type User, ValidationError, WorkingMemoryResource, WorldModelResource, enforceSearchSafety };
|
|
704
|
+
export { type APIKeyResponse, AuthResource, type AuthResponse, AuthenticationError, type BatchMemoryCreateParams, type BatchMemoryItemParams, type BatchMemoryResponse, type ClientConfig, type Collection, CollectionsResource, ConsolidationResource, type CorrectionCreateParams, type CorrectionSearchParams, CorrectionsResource, type CreateCollectionParams, type CreateMemoryParams, type CursorPage, type EvidenceClaim, type GroundingReceipt, HebbrixError, type ListParams, MemoriesResource, type Memory, type MemoryAddResponse, type MemoryAddResult, MemoryClient, type MemoryJobReceipt, MemoryJobsResource, type MemoryListParams, MemoryToolsResource, type MemoryWithMetadata, NotFoundError, ProceduralResource, type ProofContext, type ProofLoopCandidate, type ProofLoopDecisionParams, type ProofLoopMetricParams, ProofLoopResource, RLResource, RateLimitError, type ReasonParams, type ReasoningResponse, type ReasoningSource, type SafetyEnvelope, type SearchParams, SearchResource, type SearchResponse, type SearchResult, ServerError, TemporalResource, type UpdateCollectionParams, type UpdateMemoryParams, type User, ValidationError, WorkingMemoryResource, WorldModelResource, enforceSearchSafety };
|
package/dist/index.d.ts
CHANGED
|
@@ -175,6 +175,45 @@ interface MemoryAddResponse {
|
|
|
175
175
|
updated_count: number;
|
|
176
176
|
skipped_count: number;
|
|
177
177
|
}
|
|
178
|
+
interface BatchMemoryItemParams {
|
|
179
|
+
content: string;
|
|
180
|
+
collection_id?: string;
|
|
181
|
+
importance?: number;
|
|
182
|
+
user_id?: string;
|
|
183
|
+
agent_id?: string;
|
|
184
|
+
run_id?: string;
|
|
185
|
+
tags?: string[];
|
|
186
|
+
metadata?: Record<string, any>;
|
|
187
|
+
}
|
|
188
|
+
interface BatchMemoryCreateParams {
|
|
189
|
+
memories: BatchMemoryItemParams[];
|
|
190
|
+
collection_id?: string;
|
|
191
|
+
user_id?: string;
|
|
192
|
+
agent_id?: string;
|
|
193
|
+
run_id?: string;
|
|
194
|
+
app_id?: string;
|
|
195
|
+
namespace?: string;
|
|
196
|
+
wait_for_index?: boolean;
|
|
197
|
+
/** Stable retry key sent as the Idempotency-Key transport header. */
|
|
198
|
+
idempotency_key?: string;
|
|
199
|
+
/** Optional caller cancellation signal; it is never serialized. */
|
|
200
|
+
signal?: AbortSignal;
|
|
201
|
+
}
|
|
202
|
+
interface BatchMemoryResponse {
|
|
203
|
+
created: number;
|
|
204
|
+
failed: number;
|
|
205
|
+
memory_ids: string[];
|
|
206
|
+
errors: string[];
|
|
207
|
+
results: Array<{
|
|
208
|
+
id: string;
|
|
209
|
+
memory_id?: string;
|
|
210
|
+
processing_status: string;
|
|
211
|
+
}>;
|
|
212
|
+
processing_status: string;
|
|
213
|
+
searchable: boolean;
|
|
214
|
+
outbox_event_id?: string;
|
|
215
|
+
status_url?: string;
|
|
216
|
+
}
|
|
178
217
|
interface UpdateMemoryParams {
|
|
179
218
|
content?: string;
|
|
180
219
|
importance?: number;
|
|
@@ -324,6 +363,19 @@ declare class MemoriesResource extends BaseResource {
|
|
|
324
363
|
* Create a new memory
|
|
325
364
|
*/
|
|
326
365
|
create(params: CreateMemoryParams): Promise<MemoryAddResponse>;
|
|
366
|
+
/**
|
|
367
|
+
* Create up to 100 memories with one unambiguous readiness contract.
|
|
368
|
+
* `wait_for_index=true` resolves only for a fully searchable batch; a server
|
|
369
|
+
* deadline or indexing failure rejects the request instead of returning a
|
|
370
|
+
* successful processing receipt.
|
|
371
|
+
*/
|
|
372
|
+
createBatch(params: BatchMemoryCreateParams): Promise<BatchMemoryResponse>;
|
|
373
|
+
/** Poll every item in an asynchronous batch receipt until it is searchable. */
|
|
374
|
+
waitForBatchSearchable(receipt: BatchMemoryResponse, options?: {
|
|
375
|
+
timeoutMs?: number;
|
|
376
|
+
pollIntervalMs?: number;
|
|
377
|
+
signal?: AbortSignal;
|
|
378
|
+
}): Promise<BatchMemoryResponse>;
|
|
327
379
|
/**
|
|
328
380
|
* List memories
|
|
329
381
|
*/
|
|
@@ -429,6 +481,7 @@ declare class RLResource extends BaseResource {
|
|
|
429
481
|
evaluate(agentType: string, collectionId?: string): Promise<any>;
|
|
430
482
|
}
|
|
431
483
|
declare class ProceduralResource extends BaseResource {
|
|
484
|
+
private unwrapProcedure;
|
|
432
485
|
/**
|
|
433
486
|
* Create a new procedure
|
|
434
487
|
*/
|
|
@@ -500,6 +553,8 @@ declare class TemporalResource extends BaseResource {
|
|
|
500
553
|
* Query knowledge state at a specific point in time
|
|
501
554
|
*/
|
|
502
555
|
pointInTime(timestamp: string, entity?: string): Promise<any>;
|
|
556
|
+
/** Permanently delete a tenant-scoped temporal fact by stable ID. */
|
|
557
|
+
deleteFact(factId: string): Promise<any>;
|
|
503
558
|
}
|
|
504
559
|
declare class WorkingMemoryResource extends BaseResource {
|
|
505
560
|
/**
|
|
@@ -640,10 +695,10 @@ interface SafetyEnvelope {
|
|
|
640
695
|
}
|
|
641
696
|
/**
|
|
642
697
|
* Validate the API-owned grounding receipt before exposing evidence to an agent.
|
|
643
|
-
* A malformed
|
|
644
|
-
*
|
|
645
|
-
*
|
|
698
|
+
* A malformed or explicit no-match response is converted into one deterministic
|
|
699
|
+
* no-match envelope. Degraded, evidence-bound rows remain visible together with
|
|
700
|
+
* the API's abstention signal so the SDK cannot introduce a false negative.
|
|
646
701
|
*/
|
|
647
702
|
declare function enforceSearchSafety<T extends object>(response: T, rowsKey?: "results" | "sources"): T & SafetyEnvelope;
|
|
648
703
|
|
|
649
|
-
export { type APIKeyResponse, AuthResource, type AuthResponse, AuthenticationError, type ClientConfig, type Collection, CollectionsResource, ConsolidationResource, type CorrectionCreateParams, type CorrectionSearchParams, CorrectionsResource, type CreateCollectionParams, type CreateMemoryParams, type CursorPage, type EvidenceClaim, type GroundingReceipt, HebbrixError, type ListParams, MemoriesResource, type Memory, type MemoryAddResponse, type MemoryAddResult, MemoryClient, type MemoryJobReceipt, MemoryJobsResource, type MemoryListParams, MemoryToolsResource, type MemoryWithMetadata, NotFoundError, ProceduralResource, type ProofContext, type ProofLoopCandidate, type ProofLoopDecisionParams, type ProofLoopMetricParams, ProofLoopResource, RLResource, RateLimitError, type ReasonParams, type ReasoningResponse, type ReasoningSource, type SafetyEnvelope, type SearchParams, SearchResource, type SearchResponse, type SearchResult, ServerError, TemporalResource, type UpdateCollectionParams, type UpdateMemoryParams, type User, ValidationError, WorkingMemoryResource, WorldModelResource, enforceSearchSafety };
|
|
704
|
+
export { type APIKeyResponse, AuthResource, type AuthResponse, AuthenticationError, type BatchMemoryCreateParams, type BatchMemoryItemParams, type BatchMemoryResponse, type ClientConfig, type Collection, CollectionsResource, ConsolidationResource, type CorrectionCreateParams, type CorrectionSearchParams, CorrectionsResource, type CreateCollectionParams, type CreateMemoryParams, type CursorPage, type EvidenceClaim, type GroundingReceipt, HebbrixError, type ListParams, MemoriesResource, type Memory, type MemoryAddResponse, type MemoryAddResult, MemoryClient, type MemoryJobReceipt, MemoryJobsResource, type MemoryListParams, MemoryToolsResource, type MemoryWithMetadata, NotFoundError, ProceduralResource, type ProofContext, type ProofLoopCandidate, type ProofLoopDecisionParams, type ProofLoopMetricParams, ProofLoopResource, RLResource, RateLimitError, type ReasonParams, type ReasoningResponse, type ReasoningSource, type SafetyEnvelope, type SearchParams, SearchResource, type SearchResponse, type SearchResult, ServerError, TemporalResource, type UpdateCollectionParams, type UpdateMemoryParams, type User, ValidationError, WorkingMemoryResource, WorldModelResource, enforceSearchSafety };
|
package/dist/index.js
CHANGED
|
@@ -81,7 +81,7 @@ function enforceSearchSafety(response, rowsKey = "results") {
|
|
|
81
81
|
reason = "no_match_contains_evidence";
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
-
if (reason || data.
|
|
84
|
+
if (reason || data.no_match === true) {
|
|
85
85
|
data[rowsKey] = [];
|
|
86
86
|
if (rowsKey === "results") data.total = 0;
|
|
87
87
|
data.no_match = true;
|
|
@@ -93,6 +93,8 @@ function enforceSearchSafety(response, rowsKey = "results") {
|
|
|
93
93
|
data.sdk_safety_reason = reason;
|
|
94
94
|
data.grounding = { status: "no_grounded_match", reason };
|
|
95
95
|
}
|
|
96
|
+
} else if (data.degraded === true || data.abstain_recommended === true) {
|
|
97
|
+
data.sdk_safety_reason = "degraded_evidence_preserved";
|
|
96
98
|
}
|
|
97
99
|
return data;
|
|
98
100
|
}
|
|
@@ -191,6 +193,78 @@ var MemoriesResource = class extends BaseResource {
|
|
|
191
193
|
})
|
|
192
194
|
});
|
|
193
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Create up to 100 memories with one unambiguous readiness contract.
|
|
198
|
+
* `wait_for_index=true` resolves only for a fully searchable batch; a server
|
|
199
|
+
* deadline or indexing failure rejects the request instead of returning a
|
|
200
|
+
* successful processing receipt.
|
|
201
|
+
*/
|
|
202
|
+
async createBatch(params) {
|
|
203
|
+
if (!params.memories?.length || params.memories.length > 100) {
|
|
204
|
+
throw new TypeError("memories must contain between 1 and 100 items");
|
|
205
|
+
}
|
|
206
|
+
if (params.memories.some((item) => !item.content?.trim())) {
|
|
207
|
+
throw new TypeError("every batch memory must contain non-empty content");
|
|
208
|
+
}
|
|
209
|
+
const { idempotency_key, signal, ...body } = params;
|
|
210
|
+
const receipt = await this.client.request(
|
|
211
|
+
"POST",
|
|
212
|
+
"/v1/memories/batch",
|
|
213
|
+
{
|
|
214
|
+
headers: idempotency_key ? { "Idempotency-Key": idempotency_key } : void 0,
|
|
215
|
+
body: JSON.stringify({ wait_for_index: false, ...body }),
|
|
216
|
+
signal
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
if (params.wait_for_index && !(receipt.searchable === true && receipt.processing_status === "completed")) {
|
|
220
|
+
throw new Error(
|
|
221
|
+
"wait_for_index batch response was not fully searchable; retry with the same Idempotency-Key"
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
return receipt;
|
|
225
|
+
}
|
|
226
|
+
/** Poll every item in an asynchronous batch receipt until it is searchable. */
|
|
227
|
+
async waitForBatchSearchable(receipt, options = {}) {
|
|
228
|
+
const ids = [...new Set(receipt.memory_ids || [])];
|
|
229
|
+
if (!ids.length) {
|
|
230
|
+
throw new Error("batch receipt does not contain memory_ids");
|
|
231
|
+
}
|
|
232
|
+
const timeoutMs = Math.max(0, options.timeoutMs ?? 6e4);
|
|
233
|
+
const pollIntervalMs = Math.max(50, options.pollIntervalMs ?? 500);
|
|
234
|
+
const deadline = Date.now() + timeoutMs;
|
|
235
|
+
while (true) {
|
|
236
|
+
if (options.signal?.aborted) {
|
|
237
|
+
throw options.signal.reason || new Error("batch readiness polling was aborted");
|
|
238
|
+
}
|
|
239
|
+
const rows = await Promise.all(ids.map((id) => this.get(id)));
|
|
240
|
+
const terminal = rows.find(
|
|
241
|
+
(row) => ["failed", "cancelled", "canceled"].includes(
|
|
242
|
+
String(row.processing_status || "").toLowerCase()
|
|
243
|
+
)
|
|
244
|
+
);
|
|
245
|
+
if (terminal) {
|
|
246
|
+
throw new Error(
|
|
247
|
+
`memory ${terminal.id} indexing reached terminal state ${terminal.processing_status}`
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
if (rows.every((row) => row.searchable === true)) {
|
|
251
|
+
return {
|
|
252
|
+
...receipt,
|
|
253
|
+
processing_status: "completed",
|
|
254
|
+
searchable: true,
|
|
255
|
+
results: ids.map((id) => ({
|
|
256
|
+
id,
|
|
257
|
+
memory_id: id,
|
|
258
|
+
processing_status: "completed"
|
|
259
|
+
}))
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
if (Date.now() >= deadline) {
|
|
263
|
+
throw new Error(`batch was not searchable within ${timeoutMs}ms`);
|
|
264
|
+
}
|
|
265
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
266
|
+
}
|
|
267
|
+
}
|
|
194
268
|
/**
|
|
195
269
|
* List memories
|
|
196
270
|
*/
|
|
@@ -413,56 +487,78 @@ var RLResource = class extends BaseResource {
|
|
|
413
487
|
}
|
|
414
488
|
};
|
|
415
489
|
var ProceduralResource = class extends BaseResource {
|
|
490
|
+
unwrapProcedure(response) {
|
|
491
|
+
if (response?.procedure) return response.procedure;
|
|
492
|
+
if (response?.procedure_id && !response?.id) {
|
|
493
|
+
return { ...response, id: response.procedure_id };
|
|
494
|
+
}
|
|
495
|
+
return response;
|
|
496
|
+
}
|
|
416
497
|
/**
|
|
417
498
|
* Create a new procedure
|
|
418
499
|
*/
|
|
419
500
|
async create(params) {
|
|
420
|
-
|
|
501
|
+
const response = await this.client.post("/v1/procedures", {
|
|
421
502
|
name: params.name,
|
|
422
503
|
description: params.description,
|
|
423
|
-
|
|
424
|
-
|
|
504
|
+
condition: { expression: params.trigger_condition },
|
|
505
|
+
action: { steps: params.action_sequence },
|
|
425
506
|
collection_id: params.collection_id,
|
|
426
507
|
category: params.category,
|
|
427
|
-
|
|
508
|
+
parameters: params.metadata || {}
|
|
428
509
|
});
|
|
510
|
+
return this.unwrapProcedure(response);
|
|
429
511
|
}
|
|
430
512
|
/**
|
|
431
513
|
* List procedures
|
|
432
514
|
*/
|
|
433
515
|
async list(params) {
|
|
434
|
-
|
|
516
|
+
const response = await this.client.get("/v1/procedures", {
|
|
435
517
|
collection_id: params?.collection_id,
|
|
436
518
|
category: params?.category,
|
|
437
519
|
skip: params?.skip || 0,
|
|
438
520
|
limit: params?.limit || 100
|
|
439
521
|
});
|
|
522
|
+
return Array.isArray(response) ? response : response?.procedures || [];
|
|
440
523
|
}
|
|
441
524
|
/**
|
|
442
525
|
* Get a specific procedure
|
|
443
526
|
*/
|
|
444
527
|
async get(procedureId) {
|
|
445
|
-
|
|
528
|
+
const response = await this.client.get(`/v1/procedures/${procedureId}`);
|
|
529
|
+
return this.unwrapProcedure(response);
|
|
446
530
|
}
|
|
447
531
|
/**
|
|
448
532
|
* Execute a procedure
|
|
449
533
|
*/
|
|
450
534
|
async execute(procedureId, context) {
|
|
451
|
-
|
|
452
|
-
|
|
535
|
+
const response = await this.client.post(`/v1/procedures/${procedureId}/execute`, {
|
|
536
|
+
input_state: context || {}
|
|
453
537
|
});
|
|
538
|
+
return response?.execution_result || response;
|
|
454
539
|
}
|
|
455
540
|
/**
|
|
456
541
|
* Update a procedure
|
|
457
542
|
*/
|
|
458
543
|
async update(procedureId, params) {
|
|
459
|
-
|
|
544
|
+
const body = {};
|
|
545
|
+
if (params.name !== void 0) body.name = params.name;
|
|
546
|
+
if (params.description !== void 0) body.description = params.description;
|
|
547
|
+
if (params.trigger_condition !== void 0) {
|
|
548
|
+
body.condition = { expression: params.trigger_condition };
|
|
549
|
+
}
|
|
550
|
+
if (params.action_sequence !== void 0) {
|
|
551
|
+
body.action = { steps: params.action_sequence };
|
|
552
|
+
}
|
|
553
|
+
if (params.metadata !== void 0) body.parameters = params.metadata;
|
|
554
|
+
const response = await this.client.patch(`/v1/procedures/${procedureId}`, body);
|
|
555
|
+
return this.unwrapProcedure(response);
|
|
460
556
|
}
|
|
461
557
|
/**
|
|
462
558
|
* Delete a procedure
|
|
463
559
|
*/
|
|
464
560
|
async delete(procedureId) {
|
|
465
|
-
await this.client.delete(`/
|
|
561
|
+
await this.client.delete(`/v1/procedures/${procedureId}`);
|
|
466
562
|
}
|
|
467
563
|
};
|
|
468
564
|
var TemporalResource = class extends BaseResource {
|
|
@@ -501,6 +597,10 @@ var TemporalResource = class extends BaseResource {
|
|
|
501
597
|
entity
|
|
502
598
|
});
|
|
503
599
|
}
|
|
600
|
+
/** Permanently delete a tenant-scoped temporal fact by stable ID. */
|
|
601
|
+
async deleteFact(factId) {
|
|
602
|
+
return this.client.delete(`/temporal/facts/${factId}`);
|
|
603
|
+
}
|
|
504
604
|
};
|
|
505
605
|
var WorkingMemoryResource = class extends BaseResource {
|
|
506
606
|
/**
|
|
@@ -684,7 +784,7 @@ var MemoryClient = class {
|
|
|
684
784
|
getHeaders() {
|
|
685
785
|
const headers = {
|
|
686
786
|
"Content-Type": "application/json",
|
|
687
|
-
"User-Agent": "hebbrix-typescript/2.2.
|
|
787
|
+
"User-Agent": "hebbrix-typescript/2.2.1"
|
|
688
788
|
};
|
|
689
789
|
if (this.apiKey) {
|
|
690
790
|
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
@@ -693,7 +793,8 @@ var MemoryClient = class {
|
|
|
693
793
|
}
|
|
694
794
|
handleError(response, data) {
|
|
695
795
|
const statusCode = response.status;
|
|
696
|
-
const
|
|
796
|
+
const detail = data?.detail;
|
|
797
|
+
const message = data?.error?.message || (typeof detail === "string" ? detail : detail?.message) || response.statusText;
|
|
697
798
|
if (statusCode === 401) {
|
|
698
799
|
throw new AuthenticationError(message);
|
|
699
800
|
} else if (statusCode === 404) {
|
|
@@ -711,21 +812,29 @@ var MemoryClient = class {
|
|
|
711
812
|
}
|
|
712
813
|
async request(method, path, options = {}) {
|
|
713
814
|
const url = `${this.baseUrl}${path}`;
|
|
815
|
+
const { headers: requestHeaders, signal: requestSignal, ...requestOptions } = options;
|
|
714
816
|
const response = await fetch(url, {
|
|
817
|
+
...requestOptions,
|
|
715
818
|
method,
|
|
716
819
|
headers: {
|
|
717
820
|
...this.getHeaders(),
|
|
718
|
-
...
|
|
821
|
+
...requestHeaders || {}
|
|
719
822
|
},
|
|
720
|
-
|
|
721
|
-
signal: AbortSignal.timeout(this.timeout)
|
|
823
|
+
signal: requestSignal || AbortSignal.timeout(this.timeout)
|
|
722
824
|
});
|
|
723
|
-
let data;
|
|
825
|
+
let data = void 0;
|
|
724
826
|
const contentType = response.headers.get("content-type");
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
827
|
+
const responseText = await response.text();
|
|
828
|
+
if (responseText) {
|
|
829
|
+
if (contentType?.includes("application/json")) {
|
|
830
|
+
try {
|
|
831
|
+
data = JSON.parse(responseText);
|
|
832
|
+
} catch {
|
|
833
|
+
data = { detail: responseText };
|
|
834
|
+
}
|
|
835
|
+
} else {
|
|
836
|
+
data = responseText;
|
|
837
|
+
}
|
|
729
838
|
}
|
|
730
839
|
if (!response.ok) {
|
|
731
840
|
this.handleError(response, data);
|
package/dist/index.mjs
CHANGED
|
@@ -34,7 +34,7 @@ function enforceSearchSafety(response, rowsKey = "results") {
|
|
|
34
34
|
reason = "no_match_contains_evidence";
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
if (reason || data.
|
|
37
|
+
if (reason || data.no_match === true) {
|
|
38
38
|
data[rowsKey] = [];
|
|
39
39
|
if (rowsKey === "results") data.total = 0;
|
|
40
40
|
data.no_match = true;
|
|
@@ -46,6 +46,8 @@ function enforceSearchSafety(response, rowsKey = "results") {
|
|
|
46
46
|
data.sdk_safety_reason = reason;
|
|
47
47
|
data.grounding = { status: "no_grounded_match", reason };
|
|
48
48
|
}
|
|
49
|
+
} else if (data.degraded === true || data.abstain_recommended === true) {
|
|
50
|
+
data.sdk_safety_reason = "degraded_evidence_preserved";
|
|
49
51
|
}
|
|
50
52
|
return data;
|
|
51
53
|
}
|
|
@@ -144,6 +146,78 @@ var MemoriesResource = class extends BaseResource {
|
|
|
144
146
|
})
|
|
145
147
|
});
|
|
146
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* 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.
|
|
154
|
+
*/
|
|
155
|
+
async createBatch(params) {
|
|
156
|
+
if (!params.memories?.length || params.memories.length > 100) {
|
|
157
|
+
throw new TypeError("memories must contain between 1 and 100 items");
|
|
158
|
+
}
|
|
159
|
+
if (params.memories.some((item) => !item.content?.trim())) {
|
|
160
|
+
throw new TypeError("every batch memory must contain non-empty content");
|
|
161
|
+
}
|
|
162
|
+
const { idempotency_key, signal, ...body } = params;
|
|
163
|
+
const receipt = await this.client.request(
|
|
164
|
+
"POST",
|
|
165
|
+
"/v1/memories/batch",
|
|
166
|
+
{
|
|
167
|
+
headers: idempotency_key ? { "Idempotency-Key": idempotency_key } : void 0,
|
|
168
|
+
body: JSON.stringify({ wait_for_index: false, ...body }),
|
|
169
|
+
signal
|
|
170
|
+
}
|
|
171
|
+
);
|
|
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
|
+
);
|
|
176
|
+
}
|
|
177
|
+
return receipt;
|
|
178
|
+
}
|
|
179
|
+
/** Poll every item in an asynchronous batch receipt until it is searchable. */
|
|
180
|
+
async waitForBatchSearchable(receipt, options = {}) {
|
|
181
|
+
const ids = [...new Set(receipt.memory_ids || [])];
|
|
182
|
+
if (!ids.length) {
|
|
183
|
+
throw new Error("batch receipt does not contain memory_ids");
|
|
184
|
+
}
|
|
185
|
+
const timeoutMs = Math.max(0, options.timeoutMs ?? 6e4);
|
|
186
|
+
const pollIntervalMs = Math.max(50, options.pollIntervalMs ?? 500);
|
|
187
|
+
const deadline = Date.now() + timeoutMs;
|
|
188
|
+
while (true) {
|
|
189
|
+
if (options.signal?.aborted) {
|
|
190
|
+
throw options.signal.reason || new Error("batch readiness polling was aborted");
|
|
191
|
+
}
|
|
192
|
+
const rows = await Promise.all(ids.map((id) => this.get(id)));
|
|
193
|
+
const terminal = rows.find(
|
|
194
|
+
(row) => ["failed", "cancelled", "canceled"].includes(
|
|
195
|
+
String(row.processing_status || "").toLowerCase()
|
|
196
|
+
)
|
|
197
|
+
);
|
|
198
|
+
if (terminal) {
|
|
199
|
+
throw new Error(
|
|
200
|
+
`memory ${terminal.id} indexing reached terminal state ${terminal.processing_status}`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
if (rows.every((row) => row.searchable === true)) {
|
|
204
|
+
return {
|
|
205
|
+
...receipt,
|
|
206
|
+
processing_status: "completed",
|
|
207
|
+
searchable: true,
|
|
208
|
+
results: ids.map((id) => ({
|
|
209
|
+
id,
|
|
210
|
+
memory_id: id,
|
|
211
|
+
processing_status: "completed"
|
|
212
|
+
}))
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
if (Date.now() >= deadline) {
|
|
216
|
+
throw new Error(`batch was not searchable within ${timeoutMs}ms`);
|
|
217
|
+
}
|
|
218
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
147
221
|
/**
|
|
148
222
|
* List memories
|
|
149
223
|
*/
|
|
@@ -366,56 +440,78 @@ var RLResource = class extends BaseResource {
|
|
|
366
440
|
}
|
|
367
441
|
};
|
|
368
442
|
var ProceduralResource = class extends BaseResource {
|
|
443
|
+
unwrapProcedure(response) {
|
|
444
|
+
if (response?.procedure) return response.procedure;
|
|
445
|
+
if (response?.procedure_id && !response?.id) {
|
|
446
|
+
return { ...response, id: response.procedure_id };
|
|
447
|
+
}
|
|
448
|
+
return response;
|
|
449
|
+
}
|
|
369
450
|
/**
|
|
370
451
|
* Create a new procedure
|
|
371
452
|
*/
|
|
372
453
|
async create(params) {
|
|
373
|
-
|
|
454
|
+
const response = await this.client.post("/v1/procedures", {
|
|
374
455
|
name: params.name,
|
|
375
456
|
description: params.description,
|
|
376
|
-
|
|
377
|
-
|
|
457
|
+
condition: { expression: params.trigger_condition },
|
|
458
|
+
action: { steps: params.action_sequence },
|
|
378
459
|
collection_id: params.collection_id,
|
|
379
460
|
category: params.category,
|
|
380
|
-
|
|
461
|
+
parameters: params.metadata || {}
|
|
381
462
|
});
|
|
463
|
+
return this.unwrapProcedure(response);
|
|
382
464
|
}
|
|
383
465
|
/**
|
|
384
466
|
* List procedures
|
|
385
467
|
*/
|
|
386
468
|
async list(params) {
|
|
387
|
-
|
|
469
|
+
const response = await this.client.get("/v1/procedures", {
|
|
388
470
|
collection_id: params?.collection_id,
|
|
389
471
|
category: params?.category,
|
|
390
472
|
skip: params?.skip || 0,
|
|
391
473
|
limit: params?.limit || 100
|
|
392
474
|
});
|
|
475
|
+
return Array.isArray(response) ? response : response?.procedures || [];
|
|
393
476
|
}
|
|
394
477
|
/**
|
|
395
478
|
* Get a specific procedure
|
|
396
479
|
*/
|
|
397
480
|
async get(procedureId) {
|
|
398
|
-
|
|
481
|
+
const response = await this.client.get(`/v1/procedures/${procedureId}`);
|
|
482
|
+
return this.unwrapProcedure(response);
|
|
399
483
|
}
|
|
400
484
|
/**
|
|
401
485
|
* Execute a procedure
|
|
402
486
|
*/
|
|
403
487
|
async execute(procedureId, context) {
|
|
404
|
-
|
|
405
|
-
|
|
488
|
+
const response = await this.client.post(`/v1/procedures/${procedureId}/execute`, {
|
|
489
|
+
input_state: context || {}
|
|
406
490
|
});
|
|
491
|
+
return response?.execution_result || response;
|
|
407
492
|
}
|
|
408
493
|
/**
|
|
409
494
|
* Update a procedure
|
|
410
495
|
*/
|
|
411
496
|
async update(procedureId, params) {
|
|
412
|
-
|
|
497
|
+
const body = {};
|
|
498
|
+
if (params.name !== void 0) body.name = params.name;
|
|
499
|
+
if (params.description !== void 0) body.description = params.description;
|
|
500
|
+
if (params.trigger_condition !== void 0) {
|
|
501
|
+
body.condition = { expression: params.trigger_condition };
|
|
502
|
+
}
|
|
503
|
+
if (params.action_sequence !== void 0) {
|
|
504
|
+
body.action = { steps: params.action_sequence };
|
|
505
|
+
}
|
|
506
|
+
if (params.metadata !== void 0) body.parameters = params.metadata;
|
|
507
|
+
const response = await this.client.patch(`/v1/procedures/${procedureId}`, body);
|
|
508
|
+
return this.unwrapProcedure(response);
|
|
413
509
|
}
|
|
414
510
|
/**
|
|
415
511
|
* Delete a procedure
|
|
416
512
|
*/
|
|
417
513
|
async delete(procedureId) {
|
|
418
|
-
await this.client.delete(`/
|
|
514
|
+
await this.client.delete(`/v1/procedures/${procedureId}`);
|
|
419
515
|
}
|
|
420
516
|
};
|
|
421
517
|
var TemporalResource = class extends BaseResource {
|
|
@@ -454,6 +550,10 @@ var TemporalResource = class extends BaseResource {
|
|
|
454
550
|
entity
|
|
455
551
|
});
|
|
456
552
|
}
|
|
553
|
+
/** Permanently delete a tenant-scoped temporal fact by stable ID. */
|
|
554
|
+
async deleteFact(factId) {
|
|
555
|
+
return this.client.delete(`/temporal/facts/${factId}`);
|
|
556
|
+
}
|
|
457
557
|
};
|
|
458
558
|
var WorkingMemoryResource = class extends BaseResource {
|
|
459
559
|
/**
|
|
@@ -637,7 +737,7 @@ var MemoryClient = class {
|
|
|
637
737
|
getHeaders() {
|
|
638
738
|
const headers = {
|
|
639
739
|
"Content-Type": "application/json",
|
|
640
|
-
"User-Agent": "hebbrix-typescript/2.2.
|
|
740
|
+
"User-Agent": "hebbrix-typescript/2.2.1"
|
|
641
741
|
};
|
|
642
742
|
if (this.apiKey) {
|
|
643
743
|
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
@@ -646,7 +746,8 @@ var MemoryClient = class {
|
|
|
646
746
|
}
|
|
647
747
|
handleError(response, data) {
|
|
648
748
|
const statusCode = response.status;
|
|
649
|
-
const
|
|
749
|
+
const detail = data?.detail;
|
|
750
|
+
const message = data?.error?.message || (typeof detail === "string" ? detail : detail?.message) || response.statusText;
|
|
650
751
|
if (statusCode === 401) {
|
|
651
752
|
throw new AuthenticationError(message);
|
|
652
753
|
} else if (statusCode === 404) {
|
|
@@ -664,21 +765,29 @@ var MemoryClient = class {
|
|
|
664
765
|
}
|
|
665
766
|
async request(method, path, options = {}) {
|
|
666
767
|
const url = `${this.baseUrl}${path}`;
|
|
768
|
+
const { headers: requestHeaders, signal: requestSignal, ...requestOptions } = options;
|
|
667
769
|
const response = await fetch(url, {
|
|
770
|
+
...requestOptions,
|
|
668
771
|
method,
|
|
669
772
|
headers: {
|
|
670
773
|
...this.getHeaders(),
|
|
671
|
-
...
|
|
774
|
+
...requestHeaders || {}
|
|
672
775
|
},
|
|
673
|
-
|
|
674
|
-
signal: AbortSignal.timeout(this.timeout)
|
|
776
|
+
signal: requestSignal || AbortSignal.timeout(this.timeout)
|
|
675
777
|
});
|
|
676
|
-
let data;
|
|
778
|
+
let data = void 0;
|
|
677
779
|
const contentType = response.headers.get("content-type");
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
780
|
+
const responseText = await response.text();
|
|
781
|
+
if (responseText) {
|
|
782
|
+
if (contentType?.includes("application/json")) {
|
|
783
|
+
try {
|
|
784
|
+
data = JSON.parse(responseText);
|
|
785
|
+
} catch {
|
|
786
|
+
data = { detail: responseText };
|
|
787
|
+
}
|
|
788
|
+
} else {
|
|
789
|
+
data = responseText;
|
|
790
|
+
}
|
|
682
791
|
}
|
|
683
792
|
if (!response.ok) {
|
|
684
793
|
this.handleError(response, data);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hebbrix",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Advanced Memory API for AI Agents with Reinforcement Learning - TypeScript/JavaScript SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
|
-
"README.md"
|
|
17
|
+
"README.md",
|
|
18
|
+
"CHANGELOG.md"
|
|
18
19
|
],
|
|
19
20
|
"scripts": {
|
|
20
21
|
"build": "tsup src/index.ts --format cjs,esm --dts",
|