wontopos 2.2.16 → 2.2.17

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.
@@ -273,7 +273,7 @@ export declare class Client {
273
273
  withTimeout(timeoutMs: number): Client;
274
274
  /** A client with a different retry budget (everything else kept). 0 disables retries. */
275
275
  withRetries(maxRetries: number): Client;
276
- /** Store one memory. `metadata` optional (e.g. { event_date: "2026-03-01" }).
276
+ /** Store one memory. `metadata` optional (e.g. { event_date: "2026-03-01T00:00:00Z" } — RFC3339).
277
277
  * `metadata.speaker`: "me" = the assistant's own words, or a person's name (up to 50 per store). */
278
278
  add(content: string, userId?: string, metadata?: Record<string, unknown>): Promise<StoreResult>;
279
279
  /** Alias of `add` — store one memory. Same surface as the Python SDK's `store`. */
package/dist/wontopos.js CHANGED
@@ -37,7 +37,7 @@
37
37
  * runtime's (never disabled by this SDK; Node 18+ floors TLS at 1.2). Prefer
38
38
  * `Client.fromEnv()` over keys in source code.
39
39
  */
40
- const VERSION = "2.2.16";
40
+ const VERSION = "2.2.17";
41
41
  /** Runtime info helps support debug a report ("node 18 on Windows...") —
42
42
  * platform only, never anything identifying. Browsers have no `process` (and
43
43
  * silently drop the UA header anyway). */
@@ -298,7 +298,7 @@ export class Client {
298
298
  // ----- write -----
299
299
  // `userId` is optional in every call below - omit it to use the client's default
300
300
  // store (set via `new Client({ apiKey, userId })` or `withUser`).
301
- /** Store one memory. `metadata` optional (e.g. { event_date: "2026-03-01" }).
301
+ /** Store one memory. `metadata` optional (e.g. { event_date: "2026-03-01T00:00:00Z" } — RFC3339).
302
302
  * `metadata.speaker`: "me" = the assistant's own words, or a person's name (up to 50 per store). */
303
303
  add(content, userId, metadata = {}) {
304
304
  return this.post("/api/v1/memory/store", { user_id: this.uid(userId), content, metadata });
@@ -625,15 +625,24 @@ export class Client {
625
625
  throw errorFor(res.status, msg, requestId);
626
626
  }
627
627
  if (!text)
628
- return null;
628
+ return {};
629
+ let data;
629
630
  try {
630
- return JSON.parse(text);
631
+ data = JSON.parse(text);
631
632
  }
632
633
  catch (e) {
633
634
  // A 2xx with a corrupt body is a real failure — surface it, don't leak
634
635
  // a raw SyntaxError (parity with the Rust SDK).
635
636
  throw new WosError(res.status, `invalid JSON in response: ${e?.message ?? e}`);
636
637
  }
638
+ // Enforce a JSON OBJECT: every method reads the result with `.field`, so a
639
+ // body that parses to null / a number / a string / an array (a broken or
640
+ // hostile server) must be a clean WosError, not a `null.memories` TypeError.
641
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
642
+ const got = data === null ? "null" : Array.isArray(data) ? "array" : typeof data;
643
+ throw new WosError(res.status, `expected a JSON object in the response, got ${got}`);
644
+ }
645
+ return data;
637
646
  }
638
647
  throw new WosError(0, "retries exhausted"); // unreachable; keeps the compiler happy
639
648
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wontopos",
3
- "version": "2.2.16",
3
+ "version": "2.2.17",
4
4
  "description": "Wontopos — long-term memory for AI agents. Pure semantic retrieval, identical recall in every language, ~100× lower LLM bill.",
5
5
  "keywords": [
6
6
  "memory",