wontopos 2.2.19 → 2.2.21
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/README.md +4 -0
- package/dist/wontopos.js +14 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,10 @@ npm install wontopos
|
|
|
8
8
|
import { Client } from "wontopos";
|
|
9
9
|
|
|
10
10
|
const mem = new Client({ apiKey: "wos-..." });
|
|
11
|
+
|
|
12
|
+
// Each end-user / agent / topic gets its own store — create it once.
|
|
13
|
+
// (A `default` store already exists, so you can skip this and omit the id.)
|
|
14
|
+
await mem.createStore("alice");
|
|
11
15
|
await mem.add("she prefers tea over coffee", "alice");
|
|
12
16
|
|
|
13
17
|
// one call → short-term + long-term + context, ready for your LLM prompt
|
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.
|
|
40
|
+
const VERSION = "2.2.21";
|
|
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). */
|
|
@@ -129,6 +129,13 @@ function parseRateLimit(h) {
|
|
|
129
129
|
// that isn't actually an array/object to the empty value.
|
|
130
130
|
const asList = (x) => (Array.isArray(x) ? x : []);
|
|
131
131
|
const asObj = (x) => (x != null && typeof x === "object" && !Array.isArray(x) ? x : {});
|
|
132
|
+
// A list of API records (memories, turns, models...) — every element is an object
|
|
133
|
+
// by contract. `asList` only fixes the CONTAINER: a hostile/broken server sending
|
|
134
|
+
// `{"memories": [null, 1, "x", {...}]}` still handed the caller those non-objects,
|
|
135
|
+
// typed as Memory[], and the first `m.content` threw a raw TypeError from inside
|
|
136
|
+
// user code. Drop elements that aren't objects and keep the valid records, so one
|
|
137
|
+
// bad element never poisons the batch (and never destroys it).
|
|
138
|
+
const asRecords = (x) => asList(x).filter((m) => m != null && typeof m === "object" && !Array.isArray(m));
|
|
132
139
|
// Attach a delivery-form override (memoir/archive) + tz to a body, the way search
|
|
133
140
|
// passes them; on Scroll 1.2+ this renders each returned memory's time in that form.
|
|
134
141
|
function withForm(body, form, tz) {
|
|
@@ -343,7 +350,7 @@ export class Client {
|
|
|
343
350
|
// Reserved fields win over ...opts: an app that forwards untrusted input as
|
|
344
351
|
// opts must not be able to override the store (user_id), query, or limit.
|
|
345
352
|
const r = await this.post("/api/v1/memory/search", { ...opts, user_id: this.uid(userId), query, max_results: limit });
|
|
346
|
-
return
|
|
353
|
+
return asRecords(r.memories);
|
|
347
354
|
}
|
|
348
355
|
/** Search a self-memory model (Scroll 1.2+): both lanes from ONE call. Returns
|
|
349
356
|
* `{ memories, self_memories }` — `memories` is the main lane (what others said /
|
|
@@ -352,7 +359,7 @@ export class Client {
|
|
|
352
359
|
* without a self lane, `self_memories` is `[]`. `userId` optional (default store). */
|
|
353
360
|
async searchSelf(query, userId, limit = 10, opts = {}) {
|
|
354
361
|
const r = await this.post("/api/v1/memory/search", { ...opts, user_id: this.uid(userId), query, max_results: limit });
|
|
355
|
-
return { memories:
|
|
362
|
+
return { memories: asRecords(r.memories), self_memories: asRecords(r.self_memories) };
|
|
356
363
|
}
|
|
357
364
|
/** One-call LLM context: short-term turns + long-term matches + surrounding context.
|
|
358
365
|
* `form` ("memoir"/"archive", Scroll 1.2+) renders each long-term memory's time in
|
|
@@ -368,7 +375,7 @@ export class Client {
|
|
|
368
375
|
/** Recent conversation turns (short-term memory). */
|
|
369
376
|
async history(userId) {
|
|
370
377
|
const r = await this.post("/api/v1/memory/history", { user_id: this.uid(userId) });
|
|
371
|
-
return
|
|
378
|
+
return asRecords(r.turns);
|
|
372
379
|
}
|
|
373
380
|
/** Memory counts for a store: { total_memories, short_term_turns }. */
|
|
374
381
|
stats(userId) {
|
|
@@ -416,7 +423,7 @@ export class Client {
|
|
|
416
423
|
// server that mints a FRESH cursor every page forever — bound the walk.
|
|
417
424
|
for (let page = 0; page < MAX_PAGES; page++) {
|
|
418
425
|
const p = await this.listMemories(userId, { limit: opts.pageSize ?? 100, cursor });
|
|
419
|
-
for (const m of
|
|
426
|
+
for (const m of asRecords(p.memories))
|
|
420
427
|
yield m;
|
|
421
428
|
const next = p.next_cursor ?? undefined;
|
|
422
429
|
if (!next || seen.has(next))
|
|
@@ -443,7 +450,7 @@ export class Client {
|
|
|
443
450
|
/** Available models: `[{ id, name, available, memory }, ...]`. Needs no API key. */
|
|
444
451
|
async listModels() {
|
|
445
452
|
const data = await this.request("GET", "/api/v1/models");
|
|
446
|
-
return
|
|
453
|
+
return asRecords(data.models);
|
|
447
454
|
}
|
|
448
455
|
// ----- stores -----
|
|
449
456
|
/** Create a store — the `userId` you read and write under. Stores are explicit:
|
|
@@ -456,7 +463,7 @@ export class Client {
|
|
|
456
463
|
/** List your stores: `[{ user_id, created_at }, ...]` (`default` first). */
|
|
457
464
|
async listStores() {
|
|
458
465
|
const r = await this.request("GET", "/api/v1/memory/collections");
|
|
459
|
-
return
|
|
466
|
+
return asRecords(r.collections);
|
|
460
467
|
}
|
|
461
468
|
/** Delete a store and ALL its memories. Returns `{ user_id, status }`. */
|
|
462
469
|
deleteStore(userId) {
|
package/package.json
CHANGED