@z3rno/sdk 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,7 +2,12 @@ import { z } from 'zod';
2
2
 
3
3
  // src/errors.ts
4
4
  var Z3rnoError = class extends Error {
5
+ /** HTTP status code returned by the server, if applicable. */
5
6
  statusCode;
7
+ /**
8
+ * @param message - Human-readable description of the error.
9
+ * @param statusCode - HTTP status code associated with the error, if any.
10
+ */
6
11
  constructor(message, statusCode) {
7
12
  super(message);
8
13
  this.name = "Z3rnoError";
@@ -10,13 +15,21 @@ var Z3rnoError = class extends Error {
10
15
  }
11
16
  };
12
17
  var AuthenticationError = class extends Z3rnoError {
18
+ /**
19
+ * @param message - Description of the authentication failure.
20
+ */
13
21
  constructor(message) {
14
22
  super(message, 401);
15
23
  this.name = "AuthenticationError";
16
24
  }
17
25
  };
18
26
  var RateLimitError = class extends Z3rnoError {
27
+ /** Number of seconds to wait before retrying, per the Retry-After header. */
19
28
  retryAfter;
29
+ /**
30
+ * @param message - Description of the rate-limit error.
31
+ * @param retryAfter - Seconds to wait before retrying (defaults to 60).
32
+ */
20
33
  constructor(message, retryAfter = 60) {
21
34
  super(message, 429);
22
35
  this.name = "RateLimitError";
@@ -24,23 +37,56 @@ var RateLimitError = class extends Z3rnoError {
24
37
  }
25
38
  };
26
39
  var ValidationError = class extends Z3rnoError {
40
+ /**
41
+ * @param message - Description of the validation failure.
42
+ * @param statusCode - HTTP status code (400 or 422, defaults to 400).
43
+ */
27
44
  constructor(message, statusCode = 400) {
28
45
  super(message, statusCode);
29
46
  this.name = "ValidationError";
30
47
  }
31
48
  };
32
49
  var NotFoundError = class extends Z3rnoError {
50
+ /**
51
+ * @param message - Description of what was not found.
52
+ */
33
53
  constructor(message) {
34
54
  super(message, 404);
35
55
  this.name = "NotFoundError";
36
56
  }
37
57
  };
38
58
  var ServerError = class extends Z3rnoError {
59
+ /**
60
+ * @param message - Description of the server error.
61
+ * @param statusCode - HTTP status code (defaults to 500).
62
+ */
39
63
  constructor(message, statusCode = 500) {
40
64
  super(message, statusCode);
41
65
  this.name = "ServerError";
42
66
  }
43
67
  };
68
+ var Z3rnoTimeoutError = class extends Z3rnoError {
69
+ /** The timeout duration in milliseconds that was exceeded. */
70
+ timeout;
71
+ /**
72
+ * @param message - Description of the timeout.
73
+ * @param timeout - The configured timeout value in milliseconds.
74
+ */
75
+ constructor(message, timeout) {
76
+ super(message, void 0);
77
+ this.name = "Z3rnoTimeoutError";
78
+ this.timeout = timeout;
79
+ }
80
+ };
81
+ var Z3rnoConnectionError = class extends Z3rnoError {
82
+ /**
83
+ * @param message - Description of the connection failure.
84
+ */
85
+ constructor(message) {
86
+ super(message, void 0);
87
+ this.name = "Z3rnoConnectionError";
88
+ }
89
+ };
44
90
  var MemoryType = z.enum([
45
91
  "working",
46
92
  "episodic",
@@ -56,104 +102,283 @@ var RelationshipType = z.enum([
56
102
  "caused_by"
57
103
  ]);
58
104
  z.object({
105
+ /** UUID of the agent that owns this memory. */
59
106
  agentId: z.string().uuid(),
107
+ /** The text content to store (1 to 100,000 characters). */
60
108
  content: z.string().min(1).max(1e5),
109
+ /** Category of memory. Defaults to `"episodic"`. */
61
110
  memoryType: MemoryType.default("episodic"),
111
+ /** Optional UUID of the user associated with this memory. */
62
112
  userId: z.string().uuid().optional(),
113
+ /** Arbitrary key-value metadata attached to the memory. */
63
114
  metadata: z.record(z.unknown()).default({}),
115
+ /** Relationships to other memories in the knowledge graph. */
64
116
  relationships: z.array(
65
117
  z.object({
118
+ /** UUID of the target memory. */
66
119
  targetMemoryId: z.string().uuid(),
120
+ /** Type of relationship to the target memory. */
67
121
  relationshipType: RelationshipType,
122
+ /** Relationship strength from 0 to 1. Defaults to 1.0. */
68
123
  weight: z.number().min(0).max(1).default(1),
124
+ /** Arbitrary metadata for the relationship edge. */
69
125
  metadata: z.record(z.unknown()).default({})
70
126
  })
71
127
  ).default([]),
128
+ /** Time-to-live in seconds. Memory auto-deletes after this duration. */
72
129
  ttlSeconds: z.number().int().positive().optional(),
130
+ /** Importance score from 0 to 1. Influences recall ranking. */
73
131
  importance: z.number().min(0).max(1).optional()
74
132
  });
75
133
  z.object({
134
+ /** UUID of the agent whose memories to search. */
76
135
  agentId: z.string().uuid(),
136
+ /** Natural-language query for semantic similarity search. */
77
137
  query: z.string().optional(),
138
+ /** Filter results to a specific memory type. */
78
139
  memoryType: z.string().optional(),
140
+ /** Additional metadata filters. */
79
141
  filters: z.record(z.unknown()).optional(),
142
+ /** Maximum number of results to return (1-100, default 10). */
80
143
  topK: z.number().int().min(1).max(100).default(10),
144
+ /** Minimum similarity score threshold (0-1, default 0). */
81
145
  similarityThreshold: z.number().min(0).max(1).default(0),
146
+ /** ISO 8601 timestamp for temporal queries (point-in-time recall). */
82
147
  asOf: z.string().datetime().optional(),
148
+ /** Whether to include soft-deleted memories. */
83
149
  includeDeleted: z.boolean().default(false)
84
150
  });
85
151
  z.object({
152
+ /** UUID of the agent that owns the memories. */
86
153
  agentId: z.string().uuid(),
154
+ /** UUID of a single memory to delete. */
87
155
  memoryId: z.string().uuid().optional(),
156
+ /** UUIDs of multiple memories to delete in one call. */
88
157
  memoryIds: z.array(z.string().uuid()).optional(),
158
+ /** If true, permanently deletes (vs. soft-delete). Defaults to false. */
89
159
  hardDelete: z.boolean().default(false),
160
+ /** If true, also deletes related memories. Defaults to false. */
90
161
  cascade: z.boolean().default(false),
162
+ /** Optional reason for the deletion (stored in audit log). */
91
163
  reason: z.string().optional()
92
164
  });
93
165
  var MemoryResponse = z.object({
166
+ /** Unique identifier for this memory. */
94
167
  id: z.string(),
168
+ /** UUID of the owning agent. */
95
169
  agent_id: z.string(),
170
+ /** Text content of the memory. */
96
171
  content: z.string(),
172
+ /** Category of the memory. */
97
173
  memory_type: z.string(),
174
+ /** Server-computed importance score (0-1). */
98
175
  importance_score: z.number(),
176
+ /** Number of times this memory has been recalled. */
99
177
  recall_count: z.number(),
178
+ /** Name of the embedding model used, if any. */
100
179
  embedding_model: z.string().nullable().optional(),
180
+ /** ISO 8601 creation timestamp. */
101
181
  created_at: z.string(),
182
+ /** Arbitrary metadata attached to the memory. */
102
183
  metadata: z.record(z.unknown()).default({})
103
184
  });
104
185
  var RecallResultItem = z.object({
186
+ /** Unique identifier of the recalled memory. */
105
187
  memory_id: z.string(),
188
+ /** Text content of the memory. */
106
189
  content: z.string(),
190
+ /** Optional server-generated summary. */
107
191
  summary: z.string().nullable().optional(),
192
+ /** Category of the memory. */
108
193
  memory_type: z.string(),
194
+ /** Cosine similarity to the query (0-1). */
109
195
  similarity_score: z.number(),
196
+ /** Server-computed importance score (0-1). */
110
197
  importance_score: z.number(),
198
+ /** Combined relevance score used for ranking (0-1). */
111
199
  relevance_score: z.number(),
200
+ /** Number of times this memory has been recalled. */
112
201
  recall_count: z.number(),
202
+ /** ISO 8601 creation timestamp. */
113
203
  created_at: z.string(),
204
+ /** Arbitrary metadata attached to the memory. */
114
205
  metadata: z.record(z.unknown()).default({})
115
206
  });
116
207
  var RecallResponse = z.object({
208
+ /** Ranked list of matching memories. */
117
209
  results: z.array(RecallResultItem),
210
+ /** Total number of matches (may exceed `topK`). */
118
211
  total: z.number(),
212
+ /** The query that was searched, if any. */
119
213
  query: z.string().nullable().optional()
120
214
  });
121
215
  var ForgetResponse = z.object({
216
+ /** Number of memories deleted. */
122
217
  deleted_count: z.number(),
218
+ /** Whether a hard delete was performed. */
123
219
  hard_deleted: z.boolean(),
220
+ /** Number of related memories deleted via cascade. */
124
221
  cascade_count: z.number(),
222
+ /** IDs of all deleted memories. */
125
223
  memory_ids: z.array(z.string())
126
224
  });
127
225
  var AuditEntry = z.object({
226
+ /** Auto-incrementing audit entry ID. */
128
227
  id: z.number(),
228
+ /** UUID of the agent, if applicable. */
129
229
  agent_id: z.string().nullable().optional(),
230
+ /** UUID of the user, if applicable. */
130
231
  user_id: z.string().nullable().optional(),
232
+ /** Operation type (e.g., `"store"`, `"recall"`, `"forget"`). */
131
233
  operation: z.string(),
234
+ /** UUID of the affected memory, if applicable. */
132
235
  memory_id: z.string().nullable().optional(),
236
+ /** Memory type of the affected memory, if applicable. */
133
237
  memory_type: z.string().nullable().optional(),
238
+ /** Additional details about the operation. */
134
239
  details: z.record(z.unknown()).default({}),
240
+ /** IP address of the caller, if available. */
135
241
  ip_address: z.string().nullable().optional(),
242
+ /** ISO 8601 timestamp of the operation. */
136
243
  created_at: z.string()
137
244
  });
138
245
  var AuditPageResponse = z.object({
246
+ /** Audit entries on this page. */
139
247
  entries: z.array(AuditEntry),
248
+ /** Total number of matching audit entries. */
140
249
  total: z.number(),
250
+ /** Current page number (1-indexed). */
141
251
  page: z.number(),
252
+ /** Number of entries per page. */
142
253
  page_size: z.number(),
254
+ /** Whether more pages are available. */
143
255
  has_next: z.boolean()
144
256
  });
257
+ var BatchStoreResponse = z.object({
258
+ /** Array of stored memory objects. */
259
+ results: z.array(MemoryResponse),
260
+ /** Number of memories successfully stored. */
261
+ stored_count: z.number()
262
+ });
263
+ var MemoryVersion = z.object({
264
+ /** Version identifier. */
265
+ id: z.string(),
266
+ /** Text content at this version. */
267
+ content: z.string(),
268
+ /** Memory type at this version. */
269
+ memory_type: z.string(),
270
+ /** Importance score at this version. */
271
+ importance_score: z.number(),
272
+ /** ISO 8601 timestamp when this version became active. */
273
+ valid_from: z.string(),
274
+ /** ISO 8601 timestamp when this version was superseded, or null if current. */
275
+ valid_to: z.string().nullable().optional(),
276
+ /** Metadata at this version. */
277
+ metadata: z.record(z.unknown()).default({})
278
+ });
279
+ var MemoryHistoryResponse = z.object({
280
+ /** UUID of the memory. */
281
+ memory_id: z.string(),
282
+ /** Chronologically ordered list of versions. */
283
+ versions: z.array(MemoryVersion),
284
+ /** Total number of versions. */
285
+ total: z.number()
286
+ });
287
+ var SessionResponse = z.object({
288
+ /** Unique session identifier. */
289
+ session_id: z.string(),
290
+ /** UUID of the agent this session belongs to. */
291
+ agent_id: z.string(),
292
+ /** Type of session (e.g., `"conversation"`). */
293
+ session_type: z.string(),
294
+ /** ISO 8601 timestamp when the session started. */
295
+ started_at: z.string(),
296
+ /** Arbitrary session metadata. */
297
+ metadata: z.record(z.unknown()).default({})
298
+ });
299
+ var EndSessionResponse = z.object({
300
+ /** The session that was ended. */
301
+ session_id: z.string(),
302
+ /** ISO 8601 timestamp when the session ended. */
303
+ ended_at: z.string(),
304
+ /** Total duration of the session in seconds. */
305
+ duration_seconds: z.number(),
306
+ /** Number of memories created during the session. */
307
+ memory_count: z.number()
308
+ });
145
309
 
146
310
  // src/client.ts
147
311
  var Z3rnoClient = class {
148
312
  baseUrl;
149
313
  apiKey;
150
314
  timeout;
151
- constructor(config) {
152
- this.baseUrl = config.baseUrl.replace(/\/$/, "");
153
- this.apiKey = config.apiKey;
315
+ maxRetries;
316
+ fetchImpl;
317
+ onRequest;
318
+ onResponse;
319
+ /**
320
+ * Creates a new Z3rno client instance.
321
+ *
322
+ * @param config - Client configuration options. All fields are optional.
323
+ *
324
+ * @example
325
+ * ```ts
326
+ * // Explicit configuration
327
+ * const client = new Z3rnoClient({
328
+ * baseUrl: "http://localhost:8000",
329
+ * apiKey: "z3rno_sk_test_...",
330
+ * timeout: 10000,
331
+ * maxRetries: 2,
332
+ * });
333
+ *
334
+ * // Or rely on environment variables (Z3RNO_BASE_URL, Z3RNO_API_KEY)
335
+ * const client = new Z3rnoClient();
336
+ * ```
337
+ */
338
+ constructor(config = {}) {
339
+ let resolvedUrl = config.baseUrl ?? "";
340
+ if (!resolvedUrl && typeof process !== "undefined" && process.env) {
341
+ resolvedUrl = process.env.Z3RNO_BASE_URL ?? "";
342
+ }
343
+ if (!resolvedUrl) {
344
+ resolvedUrl = "https://api.z3rno.dev";
345
+ }
346
+ this.baseUrl = resolvedUrl.replace(/\/$/, "");
347
+ let resolvedKey = config.apiKey ?? "";
348
+ if (!resolvedKey && typeof process !== "undefined" && process.env) {
349
+ resolvedKey = process.env.Z3RNO_API_KEY ?? "";
350
+ }
351
+ this.apiKey = resolvedKey;
154
352
  this.timeout = config.timeout ?? 3e4;
353
+ this.maxRetries = config.maxRetries ?? 3;
354
+ this.fetchImpl = config.fetch ?? globalThis.fetch;
355
+ this.onRequest = config.onRequest;
356
+ this.onResponse = config.onResponse;
155
357
  }
156
358
  // --- Store ---
359
+ /**
360
+ * Stores a new memory for an agent.
361
+ *
362
+ * The server generates an embedding for the content and stores it in
363
+ * the vector database. The memory is immediately available for recall.
364
+ *
365
+ * @param request - The memory to store.
366
+ * @returns The stored memory, including the server-generated ID and scores.
367
+ * @throws {@link AuthenticationError} If the API key is invalid.
368
+ * @throws {@link ValidationError} If the request body is invalid.
369
+ * @throws {@link Z3rnoTimeoutError} If the request times out.
370
+ *
371
+ * @example
372
+ * ```ts
373
+ * const memory = await client.store({
374
+ * agentId: "550e8400-e29b-41d4-a716-446655440000",
375
+ * content: "User prefers dark mode",
376
+ * memoryType: "semantic",
377
+ * metadata: { source: "settings-page" },
378
+ * });
379
+ * console.log(memory.id); // "mem-abc123"
380
+ * ```
381
+ */
157
382
  async store(request) {
158
383
  const body = {
159
384
  agent_id: request.agentId,
@@ -174,6 +399,36 @@ var Z3rnoClient = class {
174
399
  return MemoryResponse.parse(resp);
175
400
  }
176
401
  // --- Recall ---
402
+ /**
403
+ * Recalls memories by semantic similarity to a query.
404
+ *
405
+ * Returns a ranked list of memories sorted by a combined relevance score
406
+ * that factors in similarity, importance, and recency.
407
+ *
408
+ * @param params - Recall parameters including the query and filters.
409
+ * @param params.agentId - UUID of the agent whose memories to search.
410
+ * @param params.query - Natural-language query for semantic search.
411
+ * @param params.memoryType - Filter by memory type.
412
+ * @param params.filters - Additional metadata filters.
413
+ * @param params.topK - Maximum results to return (default 10).
414
+ * @param params.similarityThreshold - Minimum similarity score (default 0).
415
+ * @returns Ranked recall results with similarity scores.
416
+ * @throws {@link AuthenticationError} If the API key is invalid.
417
+ * @throws {@link Z3rnoTimeoutError} If the request times out.
418
+ *
419
+ * @example
420
+ * ```ts
421
+ * const results = await client.recall({
422
+ * agentId: "550e8400-e29b-41d4-a716-446655440000",
423
+ * query: "user preferences",
424
+ * topK: 5,
425
+ * similarityThreshold: 0.7,
426
+ * });
427
+ * for (const item of results.results) {
428
+ * console.log(`${item.content} (score: ${item.relevance_score})`);
429
+ * }
430
+ * ```
431
+ */
177
432
  async recall(params) {
178
433
  const body = {
179
434
  agent_id: params.agentId,
@@ -187,6 +442,35 @@ var Z3rnoClient = class {
187
442
  return RecallResponse.parse(resp);
188
443
  }
189
444
  // --- Forget ---
445
+ /**
446
+ * Forgets (deletes) one or more memories.
447
+ *
448
+ * By default, performs a soft delete (marks as deleted but retains data).
449
+ * Set `hardDelete: true` for permanent removal. Use `cascade: true` to
450
+ * also delete related memories in the knowledge graph.
451
+ *
452
+ * @param params - Forget parameters.
453
+ * @param params.agentId - UUID of the agent that owns the memories.
454
+ * @param params.memoryId - UUID of a single memory to delete.
455
+ * @param params.memoryIds - UUIDs of multiple memories to delete.
456
+ * @param params.hardDelete - Permanently delete (default false).
457
+ * @param params.cascade - Delete related memories too (default false).
458
+ * @param params.reason - Reason for deletion (stored in audit log).
459
+ * @returns Summary of the deletion operation.
460
+ * @throws {@link AuthenticationError} If the API key is invalid.
461
+ * @throws {@link NotFoundError} If the specified memory does not exist.
462
+ *
463
+ * @example
464
+ * ```ts
465
+ * const result = await client.forget({
466
+ * agentId: "550e8400-e29b-41d4-a716-446655440000",
467
+ * memoryId: "mem-abc123",
468
+ * hardDelete: true,
469
+ * reason: "User requested data deletion",
470
+ * });
471
+ * console.log(`Deleted ${result.deleted_count} memories`);
472
+ * ```
473
+ */
190
474
  async forget(params) {
191
475
  const body = {
192
476
  agent_id: params.agentId,
@@ -199,7 +483,193 @@ var Z3rnoClient = class {
199
483
  const resp = await this.request("POST", "/v1/memories/forget", body);
200
484
  return ForgetResponse.parse(resp);
201
485
  }
486
+ // --- Get Memory ---
487
+ /**
488
+ * Retrieves a single memory by its ID.
489
+ *
490
+ * @param memoryId - The unique identifier of the memory to retrieve.
491
+ * @returns The full memory object.
492
+ * @throws {@link NotFoundError} If no memory exists with the given ID.
493
+ * @throws {@link AuthenticationError} If the API key is invalid.
494
+ *
495
+ * @example
496
+ * ```ts
497
+ * const memory = await client.getMemory("mem-abc123");
498
+ * console.log(memory.content);
499
+ * console.log(memory.importance_score);
500
+ * ```
501
+ */
502
+ async getMemory(memoryId) {
503
+ const resp = await this.request("GET", `/v1/memories/${memoryId}`);
504
+ return MemoryResponse.parse(resp);
505
+ }
506
+ // --- Store Batch ---
507
+ /**
508
+ * Stores multiple memories in a single API call.
509
+ *
510
+ * More efficient than calling {@link store} in a loop. All memories are
511
+ * processed atomically on the server.
512
+ *
513
+ * @param memories - Array of memories to store.
514
+ * @returns The stored memories and a count of how many were created.
515
+ * @throws {@link ValidationError} If any memory in the batch is invalid.
516
+ * @throws {@link AuthenticationError} If the API key is invalid.
517
+ *
518
+ * @example
519
+ * ```ts
520
+ * const result = await client.storeBatch([
521
+ * { agentId: "agent-1", content: "Fact one" },
522
+ * { agentId: "agent-1", content: "Fact two", memoryType: "semantic" },
523
+ * ]);
524
+ * console.log(`Stored ${result.stored_count} memories`);
525
+ * ```
526
+ */
527
+ async storeBatch(memories) {
528
+ const body = {
529
+ memories: memories.map((m) => ({
530
+ agent_id: m.agentId,
531
+ content: m.content,
532
+ memory_type: m.memoryType,
533
+ metadata: m.metadata,
534
+ importance: m.importance
535
+ }))
536
+ };
537
+ const resp = await this.request("POST", "/v1/memories/batch", body);
538
+ return BatchStoreResponse.parse(resp);
539
+ }
540
+ // --- Memory History ---
541
+ /**
542
+ * Retrieves the full version history of a memory.
543
+ *
544
+ * Z3rno uses temporal versioning — every update creates a new version
545
+ * rather than overwriting. This method returns all versions ordered
546
+ * chronologically.
547
+ *
548
+ * @param memoryId - The unique identifier of the memory.
549
+ * @returns All versions of the memory with validity timestamps.
550
+ * @throws {@link NotFoundError} If no memory exists with the given ID.
551
+ * @throws {@link AuthenticationError} If the API key is invalid.
552
+ *
553
+ * @example
554
+ * ```ts
555
+ * const history = await client.getMemoryHistory("mem-abc123");
556
+ * for (const version of history.versions) {
557
+ * console.log(`${version.valid_from}: ${version.content}`);
558
+ * }
559
+ * ```
560
+ */
561
+ async getMemoryHistory(memoryId) {
562
+ const resp = await this.request("GET", `/v1/memories/${memoryId}/history`);
563
+ return MemoryHistoryResponse.parse(resp);
564
+ }
565
+ // --- Update Memory ---
566
+ /**
567
+ * Updates an existing memory's content, metadata, or importance.
568
+ *
569
+ * Creates a new temporal version of the memory. The previous version
570
+ * remains accessible via {@link getMemoryHistory}.
571
+ *
572
+ * @param memoryId - The unique identifier of the memory to update.
573
+ * @param updates - Fields to update (only provided fields are changed).
574
+ * @param updates.content - New text content.
575
+ * @param updates.metadata - New metadata (replaces existing metadata).
576
+ * @param updates.importance - New importance score (0-1).
577
+ * @returns The updated memory object.
578
+ * @throws {@link NotFoundError} If no memory exists with the given ID.
579
+ * @throws {@link ValidationError} If the update values are invalid.
580
+ * @throws {@link AuthenticationError} If the API key is invalid.
581
+ *
582
+ * @example
583
+ * ```ts
584
+ * const updated = await client.updateMemory("mem-abc123", {
585
+ * content: "User now prefers light mode",
586
+ * importance: 0.9,
587
+ * });
588
+ * ```
589
+ */
590
+ async updateMemory(memoryId, updates) {
591
+ const body = {};
592
+ if (updates.content !== void 0) body.content = updates.content;
593
+ if (updates.metadata !== void 0) body.metadata = updates.metadata;
594
+ if (updates.importance !== void 0) body.importance = updates.importance;
595
+ const resp = await this.request("PATCH", `/v1/memories/${memoryId}`, body);
596
+ return MemoryResponse.parse(resp);
597
+ }
598
+ // --- Sessions ---
599
+ /**
600
+ * Starts a new session for grouping related memory operations.
601
+ *
602
+ * Sessions are useful for tracking conversation turns or task boundaries.
603
+ * Memories created during a session are automatically associated with it.
604
+ *
605
+ * @param params - Session parameters.
606
+ * @param params.agentId - UUID of the agent to start the session for.
607
+ * @param params.sessionType - Type of session (default `"conversation"`).
608
+ * @returns The created session with its ID and start time.
609
+ * @throws {@link AuthenticationError} If the API key is invalid.
610
+ *
611
+ * @example
612
+ * ```ts
613
+ * const session = await client.startSession({ agentId: "agent-1" });
614
+ * console.log(`Session started: ${session.session_id}`);
615
+ * // ... perform operations ...
616
+ * await client.endSession(session.session_id);
617
+ * ```
618
+ */
619
+ async startSession(params) {
620
+ const body = {
621
+ agent_id: params.agentId,
622
+ session_type: params.sessionType ?? "conversation"
623
+ };
624
+ const resp = await this.request("POST", "/v1/sessions", body);
625
+ return SessionResponse.parse(resp);
626
+ }
627
+ /**
628
+ * Ends an active session.
629
+ *
630
+ * Returns summary statistics including the session duration and the
631
+ * number of memories created during the session.
632
+ *
633
+ * @param sessionId - The unique identifier of the session to end.
634
+ * @returns Session summary with duration and memory count.
635
+ * @throws {@link NotFoundError} If no active session exists with the given ID.
636
+ * @throws {@link AuthenticationError} If the API key is invalid.
637
+ *
638
+ * @example
639
+ * ```ts
640
+ * const summary = await client.endSession("sess-abc123");
641
+ * console.log(`Session lasted ${summary.duration_seconds}s, ${summary.memory_count} memories`);
642
+ * ```
643
+ */
644
+ async endSession(sessionId) {
645
+ const resp = await this.request("POST", `/v1/sessions/${sessionId}/end`);
646
+ return EndSessionResponse.parse(resp);
647
+ }
202
648
  // --- Audit ---
649
+ /**
650
+ * Retrieves a paginated audit log of memory operations.
651
+ *
652
+ * The audit log records every store, recall, forget, and update operation
653
+ * performed by any agent. Useful for compliance, debugging, and analytics.
654
+ *
655
+ * @param params - Optional pagination and filter parameters.
656
+ * @param params.agentId - Filter by agent UUID.
657
+ * @param params.page - Page number (1-indexed).
658
+ * @param params.pageSize - Number of entries per page.
659
+ * @returns A page of audit log entries with pagination metadata.
660
+ * @throws {@link AuthenticationError} If the API key is invalid.
661
+ *
662
+ * @example
663
+ * ```ts
664
+ * const page = await client.audit({ agentId: "agent-1", page: 1, pageSize: 20 });
665
+ * for (const entry of page.entries) {
666
+ * console.log(`${entry.created_at}: ${entry.operation} on ${entry.memory_id}`);
667
+ * }
668
+ * if (page.has_next) {
669
+ * const nextPage = await client.audit({ agentId: "agent-1", page: 2 });
670
+ * }
671
+ * ```
672
+ */
203
673
  async audit(params) {
204
674
  const searchParams = new URLSearchParams();
205
675
  if (params?.agentId) searchParams.set("agent_id", params.agentId);
@@ -213,26 +683,75 @@ var Z3rnoClient = class {
213
683
  }
214
684
  // --- HTTP layer ---
215
685
  async request(method, path, body) {
216
- const controller = new AbortController();
217
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
218
- try {
219
- const response = await fetch(`${this.baseUrl}${path}`, {
220
- method,
221
- headers: {
222
- Authorization: `Bearer ${this.apiKey}`,
223
- "Content-Type": "application/json",
224
- "User-Agent": "@z3rno/sdk/0.0.1"
225
- },
226
- body: body ? JSON.stringify(body) : void 0,
227
- signal: controller.signal
228
- });
229
- clearTimeout(timeoutId);
230
- return this.handleResponse(response);
231
- } catch (error) {
232
- clearTimeout(timeoutId);
233
- if (error instanceof Z3rnoError) throw error;
234
- throw new Z3rnoError(`Request failed: ${String(error)}`);
686
+ let lastError;
687
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
688
+ const controller = new AbortController();
689
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
690
+ try {
691
+ const url = `${this.baseUrl}${path}`;
692
+ let init = {
693
+ method,
694
+ headers: {
695
+ Authorization: `Bearer ${this.apiKey}`,
696
+ "Content-Type": "application/json",
697
+ "User-Agent": "@z3rno/sdk/0.0.1"
698
+ },
699
+ body: body ? JSON.stringify(body) : void 0,
700
+ signal: controller.signal
701
+ };
702
+ if (this.onRequest) {
703
+ init = this.onRequest(url, init);
704
+ }
705
+ let response = await this.fetchImpl(url, init);
706
+ if (this.onResponse) {
707
+ response = this.onResponse(response);
708
+ }
709
+ clearTimeout(timeoutId);
710
+ if (response.status === 429 && attempt < this.maxRetries) {
711
+ const retryAfter = parseInt(
712
+ response.headers.get("Retry-After") ?? "1",
713
+ 10
714
+ );
715
+ await this.sleep(retryAfter * 1e3);
716
+ continue;
717
+ }
718
+ if (response.status >= 500 && attempt < this.maxRetries) {
719
+ const delay = Math.pow(2, attempt) * 1e3;
720
+ await this.sleep(delay);
721
+ continue;
722
+ }
723
+ return this.handleResponse(response);
724
+ } catch (error) {
725
+ clearTimeout(timeoutId);
726
+ if (error instanceof Z3rnoError) throw error;
727
+ if (error instanceof DOMException && error.name === "AbortError") {
728
+ lastError = new Z3rnoTimeoutError(
729
+ `Request timed out after ${this.timeout}ms`,
730
+ this.timeout
731
+ );
732
+ } else if (error instanceof TypeError) {
733
+ lastError = new Z3rnoConnectionError(
734
+ `Connection failed: ${error.message}`
735
+ );
736
+ } else {
737
+ lastError = error instanceof Error ? error : new Error(String(error));
738
+ }
739
+ if (attempt < this.maxRetries) {
740
+ const delay = Math.pow(2, attempt) * 1e3;
741
+ await this.sleep(delay);
742
+ continue;
743
+ }
744
+ }
745
+ }
746
+ if (lastError instanceof Z3rnoError) {
747
+ throw lastError;
235
748
  }
749
+ throw new Z3rnoError(
750
+ `Request failed after ${this.maxRetries + 1} attempts: ${String(lastError)}`
751
+ );
752
+ }
753
+ sleep(ms) {
754
+ return new Promise((resolve) => setTimeout(resolve, ms));
236
755
  }
237
756
  async handleResponse(resp) {
238
757
  if (resp.ok) {
@@ -240,8 +759,16 @@ var Z3rnoClient = class {
240
759
  }
241
760
  let detail = resp.statusText;
242
761
  try {
243
- const body = await resp.json();
244
- detail = String(body.detail ?? body.error ?? resp.statusText);
762
+ const text = await resp.text();
763
+ try {
764
+ const body = JSON.parse(text);
765
+ detail = String(body.detail ?? body.error ?? resp.statusText);
766
+ } catch {
767
+ if (text.length > 0) {
768
+ const preview = text.length > 200 ? text.slice(0, 200) + "..." : text;
769
+ detail = `${resp.statusText} \u2014 ${preview}`;
770
+ }
771
+ }
245
772
  } catch {
246
773
  }
247
774
  switch (resp.status) {
@@ -271,6 +798,6 @@ var Z3rnoClient = class {
271
798
  }
272
799
  };
273
800
 
274
- export { AuditEntry, AuditPageResponse, AuthenticationError, ForgetResponse, MemoryResponse, MemoryType, NotFoundError, RateLimitError, RecallResponse, RecallResultItem, RelationshipType, ServerError, ValidationError, Z3rnoClient, Z3rnoError };
801
+ export { AuditEntry, AuditPageResponse, AuthenticationError, BatchStoreResponse, EndSessionResponse, ForgetResponse, MemoryHistoryResponse, MemoryResponse, MemoryType, MemoryVersion, NotFoundError, RateLimitError, RecallResponse, RecallResultItem, RelationshipType, ServerError, SessionResponse, ValidationError, Z3rnoClient, Z3rnoConnectionError, Z3rnoError, Z3rnoTimeoutError };
275
802
  //# sourceMappingURL=index.js.map
276
803
  //# sourceMappingURL=index.js.map