From 44c79258621960a8d3a564308b58cbd085d1dd80 Mon Sep 17 00:00:00 2001 From: Dakera Ops Date: Thu, 28 May 2026 06:39:40 +0000 Subject: [PATCH] =?UTF-8?q?feat(DAK-5508):=20add=20storeMemoriesBatch()=20?= =?UTF-8?q?=E2=80=94=20parity=20with=20dakera-rs=20v0.11.57?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds batch memory store support to the JavaScript SDK, matching the Rust SDK which shipped this in v0.11.57. Hits POST /v1/memories/store/batch. - New interfaces: BatchStoreMemoryItem, BatchStoreMemoryRequest, BatchStoreMemoryResponse, BatchStoredMemory in types.ts - New method: client.storeMemoriesBatch() - Exports added to index.ts - 1 new unit test covering happy path (POST endpoint, response shape) - Updates @types/node, eslint, typescript-eslint, vitest, fixes brace-expansion vuln - Bumps version to 0.11.57 Co-Authored-By: Claude Sonnet 4.6 --- README.md | 2 +- package-lock.json | 6 ++--- package.json | 2 +- src/client.test.ts | 38 +++++++++++++++++++++++++++ src/client.ts | 25 ++++++++++++++++++ src/index.ts | 4 +++ src/types.ts | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 136 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2f78972..7e45435 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,7 @@ const client = new DakeraClient({ // Cloud (early access) const client = new DakeraClient({ - baseUrl: 'http://localhost:3000', + baseUrl: 'http://:3000', apiKey: 'your-key', }); diff --git a/package-lock.json b/package-lock.json index b4647eb..6cd3b30 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1837,9 +1837,9 @@ } }, "node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 97c3424..1a2cde5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dakera-ai/dakera", - "version": "0.11.56", + "version": "0.11.57", "description": "TypeScript/JavaScript SDK for Dakera AI memory platform", "main": "dist/index.js", "module": "dist/index.mjs", diff --git a/src/client.test.ts b/src/client.test.ts index 28cfeb6..3b3e6bf 100644 --- a/src/client.test.ts +++ b/src/client.test.ts @@ -576,6 +576,44 @@ describe('DakeraClient', () => { }); }); + // --------------------------------------------------------------------------- + // DAK-5508: Batch Store Memory + // --------------------------------------------------------------------------- + + describe('storeMemoriesBatch', () => { + it('POSTs to /v1/memories/store/batch and returns BatchStoreMemoryResponse', async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + status: 200, + headers: new Headers({ 'content-type': 'application/json' }), + json: async () => ({ + stored: [ + { id: 'mem-1', content: 'Dark mode', agent_id: 'agent-1', tags: [], importance: 0.8, created_at: 1700000000 }, + { id: 'mem-2', content: 'Berlin user', agent_id: 'agent-1', tags: [], importance: 0.7, created_at: 1700000001 }, + ], + stored_count: 2, + total_embedding_time_ms: 42, + }), + }); + + const resp = await client.storeMemoriesBatch({ + agent_id: 'agent-1', + memories: [ + { content: 'Dark mode', importance: 0.8 }, + { content: 'Berlin user', importance: 0.7 }, + ], + }); + + expect(resp.stored_count).toBe(2); + expect(resp.stored).toHaveLength(2); + expect(resp.stored[0].id).toBe('mem-1'); + expect(resp.total_embedding_time_ms).toBe(42); + const [url, init] = mockFetch.mock.calls[0]; + expect(url).toContain('/v1/memories/store/batch'); + expect(init?.method).toBe('POST'); + }); + }); + // --------------------------------------------------------------------------- // OPS-1: Rate-Limit Headers (v0.7.0) // --------------------------------------------------------------------------- diff --git a/src/client.ts b/src/client.ts index a5b834b..3aa3499 100644 --- a/src/client.ts +++ b/src/client.ts @@ -120,6 +120,8 @@ import type { BatchRecallResponse, BatchForgetRequest, BatchForgetResponse, + BatchStoreMemoryRequest, + BatchStoreMemoryResponse, RateLimitHeaders, AutoPilotStatusResponse, AutoPilotConfigRequest, @@ -1537,6 +1539,29 @@ export class DakeraClient { return this.request('DELETE', '/v1/memories/forget/batch', request); } + /** + * Store multiple memories in a single request (DAK-5508). + * + * Uses `POST /v1/memories/store/batch`. The server embeds all contents in a + * single ONNX inference pass, yielding ≥100× throughput vs. N sequential + * single-store calls. Accepts up to 1 000 memories per call. + * + * @example + * ```ts + * const resp = await client.storeMemoriesBatch({ + * agent_id: 'agent-1', + * memories: [ + * { content: 'The user prefers dark mode', importance: 0.8 }, + * { content: 'The user is based in Berlin', importance: 0.7 }, + * ], + * }); + * console.log(`Stored ${resp.stored_count} memories`); + * ``` + */ + async storeMemoriesBatch(request: BatchStoreMemoryRequest): Promise { + return this.request('POST', '/v1/memories/store/batch', request); + } + /** Search memories for an agent */ async searchMemories(agentId: string, query: string, options?: { top_k?: number; memory_type?: string; min_importance?: number; routing?: import('./types').RoutingMode; rerank?: boolean }): Promise { const body: Record = { query }; diff --git a/src/index.ts b/src/index.ts index 9908c89..ababaca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -93,6 +93,10 @@ export type { BatchRecallResponse, BatchForgetRequest, BatchForgetResponse, + BatchStoreMemoryItem, + BatchStoreMemoryRequest, + BatchStoreMemoryResponse, + BatchStoredMemory, // Rate-limit headers (OPS-1) RateLimitHeaders, // Session types diff --git a/src/types.ts b/src/types.ts index 2a9f0bb..8d7816e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1654,6 +1654,70 @@ export interface BatchForgetResponse { deleted_count: number; } +// ============================================================================ +// Batch Store Memory Types (DAK-5508) +// ============================================================================ + +/** + * A single memory entry within a {@link BatchStoreMemoryRequest}. + * + * Mirrors `StoreMemoryRequest` but omits `agent_id` — supplied at batch level. + */ +export interface BatchStoreMemoryItem { + /** Memory content text (required, max 100 000 chars). */ + content: string; + /** One of `"episodic"`, `"semantic"`, `"procedural"`, or `"working"`. */ + memory_type?: MemoryType; + /** Importance score 0.0–1.0 (default: 0.5). */ + importance?: number; + /** Optional tags to associate with the memory. */ + tags?: string[]; + /** Optional session ID to associate with. */ + session_id?: string; + /** Arbitrary metadata dictionary. */ + metadata?: Record; + /** Optional TTL in seconds. */ + ttl_seconds?: number; + /** Optional explicit expiry as a Unix timestamp (seconds). */ + expires_at?: number; + /** Optional custom ID. Auto-generated if not provided. */ + id?: string; +} + +/** + * Request body for `POST /v1/memories/store/batch` (DAK-5508). + * + * Accepts up to 1 000 memories per call. The server embeds all contents in a + * single ONNX inference pass, yielding ≥100× throughput vs. N sequential + * single-store calls. + */ +export interface BatchStoreMemoryRequest { + /** Agent namespace to store the memories in. */ + agent_id: string; + /** Memories to store (1–1000 items). */ + memories: BatchStoreMemoryItem[]; +} + +/** A single stored memory returned in a {@link BatchStoreMemoryResponse}. */ +export interface BatchStoredMemory { + id: string; + content: string; + agent_id: string; + tags: string[]; + importance: number; + created_at: number; +} + +/** Response from `POST /v1/memories/store/batch`. */ +export interface BatchStoreMemoryResponse { + /** Stored memories in the same order as the request items. */ + stored: BatchStoredMemory[]; + /** Number of memories successfully stored. */ + stored_count: number; + /** Time spent on ONNX embedding for the entire batch (milliseconds). */ + total_embedding_time_ms: number; +} + // ============================================================================ // Memory Knowledge Graph Types (CE-5 / SDK-9) // ============================================================================