wontopos 2.2.37 → 2.2.39
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 +11 -108
- package/dist/cjs/wontopos.d.cts +1054 -0
- package/dist/cjs/wontopos.js +129 -43
- package/dist/wontopos.d.ts +39 -17
- package/dist/wontopos.js +129 -43
- package/package.json +17 -7
package/dist/wontopos.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const VERSION = "2.2.
|
|
1
|
+
const VERSION = "2.2.39";
|
|
2
2
|
const RUNTIME = (() => {
|
|
3
3
|
const p = globalThis?.process;
|
|
4
4
|
return p?.version ? ` (node/${p.version}; ${p.platform}-${p.arch})` : "";
|
|
@@ -13,7 +13,7 @@ function logDebug(msg) {
|
|
|
13
13
|
const DEFAULT_BASE_URL = "https://api.wontopos.com";
|
|
14
14
|
const DEFAULT_MODEL = "tablet-2";
|
|
15
15
|
const RETRY_ALWAYS = new Set([429]);
|
|
16
|
-
const RETRY_IF_IDEMPOTENT = new Set([502, 503]);
|
|
16
|
+
const RETRY_IF_IDEMPOTENT = new Set([408, 502, 503, 504]);
|
|
17
17
|
const IDEMPOTENT_METHODS = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
|
|
18
18
|
const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "0.0.0.0"]);
|
|
19
19
|
const MAX_RESPONSE_BYTES = 64 * 1024 * 1024;
|
|
@@ -24,6 +24,12 @@ function normalizeStoreId(id) {
|
|
|
24
24
|
return id.toLowerCase().replace(/[^a-z0-9_]/g, "_");
|
|
25
25
|
}
|
|
26
26
|
const WARNED_STORE_IDS_MAX = 1024;
|
|
27
|
+
function assertUsableStoreId(userId) {
|
|
28
|
+
if (userId !== undefined && (typeof userId !== "string" || !userId.trim())) {
|
|
29
|
+
throw new Error(`userId must be a non-blank string; got ${JSON.stringify(userId)}. Omit it to use the client's ` +
|
|
30
|
+
"default store, or pass a real store id — anything else would silently write into the default store.");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
27
33
|
const WARNED_FILTER_KEYS_MAX = 1024;
|
|
28
34
|
const warnedStoreIds = new Set();
|
|
29
35
|
function warnIfStoreIdCollapses(id) {
|
|
@@ -197,6 +203,47 @@ const KNOWN_FILTER_KEYS = new Set([
|
|
|
197
203
|
"min_importance",
|
|
198
204
|
]);
|
|
199
205
|
const warnedFilterKeys = new Set();
|
|
206
|
+
const KNOWN_SEARCH_KEYS = new Set([
|
|
207
|
+
"cache_control", "speaker", "filters", "verify", "max_images", "extra",
|
|
208
|
+
]);
|
|
209
|
+
const RESERVED_SEARCH_KEYS = new Set(["user_id", "query", "max_results"]);
|
|
210
|
+
const KNOWN_RECALL_KEYS = new Set(["form", "tz", "limit", "context_limit"]);
|
|
211
|
+
const KNOWN_ENGRAM_KEYS = new Set(["form", "tz"]);
|
|
212
|
+
function checkSearchOpts(opts) {
|
|
213
|
+
checkOpts(opts, KNOWN_SEARCH_KEYS, "search");
|
|
214
|
+
}
|
|
215
|
+
function checkOpts(opts, known, what) {
|
|
216
|
+
for (const k of Object.keys(opts)) {
|
|
217
|
+
if (RESERVED_SEARCH_KEYS.has(k))
|
|
218
|
+
throw new Error(`${JSON.stringify(k)} is set by the call, not by options — pass it as an argument. ` +
|
|
219
|
+
`An app forwarding untrusted input as options cannot steer the store, the query ` +
|
|
220
|
+
`or the count, and this says so rather than dropping it silently.`);
|
|
221
|
+
if (known.has(k))
|
|
222
|
+
continue;
|
|
223
|
+
const near = [...known].find((n) => n !== "extra" && editWithin(k, n, 2));
|
|
224
|
+
throw new Error(`unknown ${what} option ${JSON.stringify(k)}` +
|
|
225
|
+
(near ? ` — did you mean ${JSON.stringify(near)}?` : "") +
|
|
226
|
+
`. It would have had no effect, and the call would have looked like it worked.` +
|
|
227
|
+
(known.has("extra")
|
|
228
|
+
? ` Pass it under \`extra\` if the service accepts it and this client does not know it yet.`
|
|
229
|
+
: ""));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function editWithin(a, b, max) {
|
|
233
|
+
if (Math.abs(a.length - b.length) > max)
|
|
234
|
+
return false;
|
|
235
|
+
const prev = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
236
|
+
for (let i = 1; i <= a.length; i++) {
|
|
237
|
+
let diag = prev[0];
|
|
238
|
+
prev[0] = i;
|
|
239
|
+
for (let j = 1; j <= b.length; j++) {
|
|
240
|
+
const tmp = prev[j];
|
|
241
|
+
prev[j] = Math.min(prev[j] + 1, prev[j - 1] + 1, diag + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
242
|
+
diag = tmp;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return prev[b.length] <= max;
|
|
246
|
+
}
|
|
200
247
|
function warnOnUnknownFilters(filters) {
|
|
201
248
|
if (!filters || typeof filters !== "object" || Array.isArray(filters))
|
|
202
249
|
return;
|
|
@@ -242,6 +289,11 @@ export class Client {
|
|
|
242
289
|
throw new Error("apiKey contains whitespace - check for a stray newline or paste error");
|
|
243
290
|
if (/[\x00-\x1f\x7f]/.test(key))
|
|
244
291
|
throw new Error("apiKey contains a control character - check for a stray byte or paste error");
|
|
292
|
+
if (/[^\x00-\x7f]/.test(key)) {
|
|
293
|
+
const bad = key.match(/[^\x00-\x7f]/)?.[0];
|
|
294
|
+
throw new Error(`apiKey contains a non-ASCII character (${JSON.stringify(bad)}) - rich text turns '-' into an ` +
|
|
295
|
+
"en dash; copy the key from a plain-text field");
|
|
296
|
+
}
|
|
245
297
|
this.apiKey = key;
|
|
246
298
|
this.base = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
247
299
|
const tm = opts.timeoutMs;
|
|
@@ -250,7 +302,8 @@ export class Client {
|
|
|
250
302
|
if (this.model && !MODEL_RE.test(this.model)) {
|
|
251
303
|
throw new Error(`invalid model name: ${JSON.stringify(this.model)} (letters, digits, '.', '_', '-' only)`);
|
|
252
304
|
}
|
|
253
|
-
|
|
305
|
+
assertUsableStoreId(opts.userId);
|
|
306
|
+
this.defaultUser = opts.userId ?? DEFAULT_USER;
|
|
254
307
|
const mr = opts.maxRetries ?? opts.retries;
|
|
255
308
|
this.maxRetries = typeof mr === "number" && Number.isFinite(mr) ? Math.max(0, Math.floor(mr)) : 2;
|
|
256
309
|
const dl = opts.deadlineMs;
|
|
@@ -298,11 +351,8 @@ export class Client {
|
|
|
298
351
|
return `Client(${this.base}, model=${this.model}, userId=${this.defaultUser}, apiKey=${maskKey(this.apiKey)})`;
|
|
299
352
|
}
|
|
300
353
|
uid(userId) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
"default store, or pass a real store id — anything else would silently write into the default store.");
|
|
304
|
-
}
|
|
305
|
-
const id = userId || this.defaultUser;
|
|
354
|
+
assertUsableStoreId(userId);
|
|
355
|
+
const id = userId ?? this.defaultUser;
|
|
306
356
|
warnIfStoreIdCollapses(id);
|
|
307
357
|
return id;
|
|
308
358
|
}
|
|
@@ -324,6 +374,10 @@ export class Client {
|
|
|
324
374
|
return this.clone({ model });
|
|
325
375
|
}
|
|
326
376
|
withUser(userId) {
|
|
377
|
+
if (userId === undefined) {
|
|
378
|
+
throw new Error("withUser() needs a store id. It was called with undefined — usually a lookup that " +
|
|
379
|
+
"found nothing. Use the client's own default instead of calling withUser at all.");
|
|
380
|
+
}
|
|
327
381
|
return this.clone({ userId });
|
|
328
382
|
}
|
|
329
383
|
withSignal(signal) {
|
|
@@ -338,43 +392,49 @@ export class Client {
|
|
|
338
392
|
withRetries(maxRetries) {
|
|
339
393
|
return this.clone({ maxRetries });
|
|
340
394
|
}
|
|
341
|
-
add(content, userId, metadata = {}, opts = {}) {
|
|
395
|
+
async add(content, userId, metadata = {}, opts = {}) {
|
|
342
396
|
const body = { user_id: this.uid(userId), content, metadata };
|
|
343
397
|
if (opts.image !== undefined)
|
|
344
398
|
body.image = normalizeImage(opts.image);
|
|
345
399
|
return this.post("/api/v1/memory/store", body, opts.idempotencyKey);
|
|
346
400
|
}
|
|
347
|
-
store(content, userId, metadata = {}, opts = {}) {
|
|
401
|
+
async store(content, userId, metadata = {}, opts = {}) {
|
|
348
402
|
return this.add(content, userId, metadata, opts);
|
|
349
403
|
}
|
|
350
|
-
addTurn(userMsg, assistantMsg, userId, opts = {}) {
|
|
404
|
+
async addTurn(userMsg, assistantMsg, userId, opts = {}) {
|
|
351
405
|
return this.post("/api/v1/memory/store-turn", { user_id: this.uid(userId), user_msg: userMsg, assistant_msg: assistantMsg }, opts.idempotencyKey);
|
|
352
406
|
}
|
|
353
|
-
addBulk(content, userId, category = "general", timestamp, opts = {}) {
|
|
407
|
+
async addBulk(content, userId, category = "general", timestamp, opts = {}) {
|
|
354
408
|
const body = { user_id: this.uid(userId), content, category };
|
|
355
409
|
if (timestamp)
|
|
356
410
|
body.timestamp = timestamp;
|
|
357
411
|
return this.post("/api/v1/memory/bulk-store", body, opts.idempotencyKey);
|
|
358
412
|
}
|
|
359
|
-
update(oldMemoryId, newContent, userId, opts = {}) {
|
|
413
|
+
async update(oldMemoryId, newContent, userId, opts = {}) {
|
|
360
414
|
return this.post("/api/v1/memory/supersede", { user_id: this.uid(userId), old_memory_id: oldMemoryId, new_content: newContent }, opts.idempotencyKey);
|
|
361
415
|
}
|
|
362
416
|
async search(query, userId, limit = 10, opts = {}) {
|
|
417
|
+
checkSearchOpts(opts);
|
|
363
418
|
warnOnUnknownFilters(opts.filters);
|
|
364
419
|
checkCount(limit, "limit");
|
|
365
|
-
const
|
|
420
|
+
const { extra, ...known } = opts;
|
|
421
|
+
const r = await this.post("/api/v1/memory/search", { ...extra, ...known, user_id: this.uid(userId), query, max_results: limit });
|
|
366
422
|
return mergeResults(r);
|
|
367
423
|
}
|
|
368
424
|
async searchSelf(query, userId, limit = 10, opts = {}) {
|
|
425
|
+
checkSearchOpts(opts);
|
|
369
426
|
warnOnUnknownFilters(opts.filters);
|
|
370
427
|
checkCount(limit, "limit");
|
|
371
|
-
const
|
|
428
|
+
const { extra, ...known } = opts;
|
|
429
|
+
const r = await this.post("/api/v1/memory/search", { ...extra, ...known, user_id: this.uid(userId), query, max_results: limit });
|
|
372
430
|
return { memories: asRecords(r.memories), self_memories: asRecords(r.self_memories) };
|
|
373
431
|
}
|
|
374
432
|
async searchFull(query, userId, limit = 10, opts = {}) {
|
|
433
|
+
checkSearchOpts(opts);
|
|
375
434
|
warnOnUnknownFilters(opts.filters);
|
|
376
435
|
checkCount(limit, "limit");
|
|
377
|
-
const
|
|
436
|
+
const { extra, ...known } = opts;
|
|
437
|
+
const r = await this.post("/api/v1/memory/search", { ...extra, ...known, user_id: this.uid(userId), query, max_results: limit });
|
|
378
438
|
return {
|
|
379
439
|
...r,
|
|
380
440
|
memories: asRecords(r.memories),
|
|
@@ -383,6 +443,7 @@ export class Client {
|
|
|
383
443
|
};
|
|
384
444
|
}
|
|
385
445
|
async recall(query, userId, opts = {}) {
|
|
446
|
+
checkOpts(opts, KNOWN_RECALL_KEYS, "recall");
|
|
386
447
|
const body = { user_id: this.uid(userId), query };
|
|
387
448
|
if (opts.limit !== undefined) {
|
|
388
449
|
checkCount(opts.limit, "limit");
|
|
@@ -394,14 +455,15 @@ export class Client {
|
|
|
394
455
|
}
|
|
395
456
|
return this.post("/api/v1/memory/recall", withForm(body, opts.form, opts.tz));
|
|
396
457
|
}
|
|
397
|
-
engram(name, query, userId, opts = {}) {
|
|
458
|
+
async engram(name, query, userId, opts = {}) {
|
|
459
|
+
checkOpts(opts, KNOWN_ENGRAM_KEYS, "engram");
|
|
398
460
|
return this.post("/api/v1/engram/run", withForm({ name, user_id: this.uid(userId), query }, opts.form, opts.tz));
|
|
399
461
|
}
|
|
400
462
|
async history(userId) {
|
|
401
463
|
const r = await this.post("/api/v1/memory/history", { user_id: this.uid(userId) });
|
|
402
464
|
return asRecords(r.turns);
|
|
403
465
|
}
|
|
404
|
-
stats(userId) {
|
|
466
|
+
async stats(userId) {
|
|
405
467
|
return this.post("/api/v1/memory/stats", { user_id: this.uid(userId) });
|
|
406
468
|
}
|
|
407
469
|
async usage(days = 7) {
|
|
@@ -410,13 +472,13 @@ export class Client {
|
|
|
410
472
|
}
|
|
411
473
|
return this.request("GET", `/api/v1/won/usage?days=${days}`);
|
|
412
474
|
}
|
|
413
|
-
get(userId, memoryId) {
|
|
414
|
-
if (
|
|
475
|
+
async get(userId, memoryId) {
|
|
476
|
+
if (typeof memoryId !== "string" || !memoryId.trim()) {
|
|
415
477
|
throw new Error("memoryId is required — the id that add/store or listMemories returned.");
|
|
416
478
|
}
|
|
417
|
-
return this.post("/api/v1/memory/get", { user_id: this.uid(userId), memory_id: memoryId }).then((r) => asObj(r.memory));
|
|
479
|
+
return this.post("/api/v1/memory/get", { user_id: this.uid(userId), memory_id: memoryId.trim() }).then((r) => asObj(r.memory));
|
|
418
480
|
}
|
|
419
|
-
listMemories(userId, opts = {}) {
|
|
481
|
+
async listMemories(userId, opts = {}) {
|
|
420
482
|
const body = { user_id: this.uid(userId), limit: opts.limit ?? 100 };
|
|
421
483
|
if (opts.cursor)
|
|
422
484
|
body.cursor = opts.cursor;
|
|
@@ -444,22 +506,28 @@ export class Client {
|
|
|
444
506
|
out.push(m);
|
|
445
507
|
return out;
|
|
446
508
|
}
|
|
447
|
-
|
|
448
|
-
|
|
509
|
+
async exportImages(userId, opts = {}) {
|
|
510
|
+
const out = [];
|
|
511
|
+
for await (const m of this.iterImages(userId, opts))
|
|
512
|
+
out.push(m);
|
|
513
|
+
return out;
|
|
514
|
+
}
|
|
515
|
+
async getImage(userId, memoryId) {
|
|
516
|
+
if (typeof memoryId !== "string" || !memoryId.trim()) {
|
|
449
517
|
throw new Error("memoryId is required — the id that add/store or listImages returned.");
|
|
450
518
|
}
|
|
451
|
-
return this.requestBytes("/api/v1/memory/image", { user_id: this.uid(userId), memory_id: memoryId });
|
|
519
|
+
return this.requestBytes("/api/v1/memory/image", { user_id: this.uid(userId), memory_id: memoryId.trim() });
|
|
452
520
|
}
|
|
453
|
-
forgetImage(userId, memoryId, opts = {}) {
|
|
454
|
-
if (
|
|
521
|
+
async forgetImage(userId, memoryId, opts = {}) {
|
|
522
|
+
if (typeof memoryId !== "string" || !memoryId.trim()) {
|
|
455
523
|
throw new Error("memoryId is required — the id of the memory whose image you want removed.");
|
|
456
524
|
}
|
|
457
|
-
const body = { user_id: this.uid(userId), memory_id: memoryId };
|
|
525
|
+
const body = { user_id: this.uid(userId), memory_id: memoryId.trim() };
|
|
458
526
|
if (opts.preview)
|
|
459
527
|
body.preview = true;
|
|
460
528
|
return this.request("DELETE", "/api/v1/memory/image", body);
|
|
461
529
|
}
|
|
462
|
-
listImages(userId, opts = {}) {
|
|
530
|
+
async listImages(userId, opts = {}) {
|
|
463
531
|
const body = { user_id: this.uid(userId) };
|
|
464
532
|
if (opts.limit !== undefined)
|
|
465
533
|
body.limit = opts.limit;
|
|
@@ -489,7 +557,7 @@ export class Client {
|
|
|
489
557
|
throw new Error(`stopped after ${MAX_PAGES} pages — the store did not end. This is a truncated ` +
|
|
490
558
|
`answer, not the whole store.`);
|
|
491
559
|
}
|
|
492
|
-
revisions(userId, opts = {}) {
|
|
560
|
+
async revisions(userId, opts = {}) {
|
|
493
561
|
const body = {};
|
|
494
562
|
if (opts.include !== undefined)
|
|
495
563
|
body.include = opts.include;
|
|
@@ -502,13 +570,13 @@ export class Client {
|
|
|
502
570
|
body.user_id = this.uid(userId);
|
|
503
571
|
return this.post("/api/v1/won/revisions", body);
|
|
504
572
|
}
|
|
505
|
-
lineage(userId, memoryId) {
|
|
506
|
-
if (
|
|
573
|
+
async lineage(userId, memoryId) {
|
|
574
|
+
if (typeof memoryId !== "string" || !memoryId.trim()) {
|
|
507
575
|
throw new Error("memoryId is required — the memory whose history you want.");
|
|
508
576
|
}
|
|
509
|
-
return this.post("/api/v1/memory/lineage", { user_id: this.uid(userId), memory_id: memoryId });
|
|
577
|
+
return this.post("/api/v1/memory/lineage", { user_id: this.uid(userId), memory_id: memoryId.trim() });
|
|
510
578
|
}
|
|
511
|
-
bySpeaker(speaker, userId, opts = {}) {
|
|
579
|
+
async bySpeaker(speaker, userId, opts = {}) {
|
|
512
580
|
if (!speaker || typeof speaker !== "string" || speaker.trim() === "") {
|
|
513
581
|
throw new Error('speaker is required — "me" for the assistant, or a person\'s name.');
|
|
514
582
|
}
|
|
@@ -532,41 +600,42 @@ export class Client {
|
|
|
532
600
|
async listEngrams() {
|
|
533
601
|
const data = await this.request("GET", "/api/v1/engram");
|
|
534
602
|
return {
|
|
603
|
+
...data,
|
|
535
604
|
engrams: asRecords(data.engrams),
|
|
536
605
|
forms: asRecords(data.forms),
|
|
537
606
|
note: typeof data.note === "string" ? data.note : undefined,
|
|
538
607
|
};
|
|
539
608
|
}
|
|
540
|
-
createStore(userId) {
|
|
609
|
+
async createStore(userId) {
|
|
541
610
|
return this.post("/api/v1/memory/collection", { user_id: this.uid(userId) });
|
|
542
611
|
}
|
|
543
612
|
async listStores() {
|
|
544
613
|
const r = await this.request("GET", "/api/v1/memory/collections");
|
|
545
614
|
return asRecords(r.collections);
|
|
546
615
|
}
|
|
547
|
-
deleteStore(userId) {
|
|
616
|
+
async deleteStore(userId) {
|
|
548
617
|
if (typeof userId !== "string" || !userId.trim())
|
|
549
618
|
throw new Error("userId is required (a non-blank string) — deleteStore never falls back to the default store.");
|
|
550
619
|
warnIfStoreIdCollapses(userId);
|
|
551
620
|
return this.request("DELETE", "/api/v1/memory/collection", { user_id: userId });
|
|
552
621
|
}
|
|
553
|
-
addSpeaker(speaker, userId) {
|
|
622
|
+
async addSpeaker(speaker, userId) {
|
|
554
623
|
return this.post("/api/v1/memory/speakers", { user_id: this.uid(userId), speaker });
|
|
555
624
|
}
|
|
556
625
|
async listSpeakers(userId) {
|
|
557
626
|
const r = await this.request("GET", `/api/v1/memory/speakers?user_id=${encodeURIComponent(this.uid(userId))}`);
|
|
558
627
|
return { ...r, speakers: asRecords(r?.speakers) };
|
|
559
628
|
}
|
|
560
|
-
removeSpeaker(speaker, userId) {
|
|
629
|
+
async removeSpeaker(speaker, userId) {
|
|
561
630
|
return this.request("DELETE", "/api/v1/memory/speakers", { user_id: this.uid(userId), speaker });
|
|
562
631
|
}
|
|
563
|
-
delete(userId, memoryId) {
|
|
632
|
+
async delete(userId, memoryId) {
|
|
564
633
|
if (typeof memoryId !== "string" || !memoryId.trim()) {
|
|
565
634
|
throw new Error("memoryId is required (non-blank). To delete every memory in a store, call deleteAll(userId) explicitly.");
|
|
566
635
|
}
|
|
567
636
|
return this.post("/api/v1/memory/forget", { user_id: this.uid(userId), memory_id: memoryId.trim() });
|
|
568
637
|
}
|
|
569
|
-
deleteAll(userId) {
|
|
638
|
+
async deleteAll(userId) {
|
|
570
639
|
if (typeof userId !== "string" || !userId.trim())
|
|
571
640
|
throw new Error("userId is required (a non-blank string) for deleteAll — anything else would wipe the default store.");
|
|
572
641
|
warnIfStoreIdCollapses(userId);
|
|
@@ -701,7 +770,9 @@ export class Client {
|
|
|
701
770
|
if (e?.name === "AbortError" || att.signal.aborted) {
|
|
702
771
|
throw new APIConnectionError(0, this.abortMessage(att.why()));
|
|
703
772
|
}
|
|
704
|
-
|
|
773
|
+
if (e instanceof WosError)
|
|
774
|
+
throw e;
|
|
775
|
+
throw new APIConnectionError(0, `network error: ${e?.message ?? e}`);
|
|
705
776
|
}
|
|
706
777
|
if (buf.byteLength === 0) {
|
|
707
778
|
throw new WosError(res.status, "empty image body — the service returned no bytes");
|
|
@@ -774,6 +845,14 @@ export class Client {
|
|
|
774
845
|
const attempts = this.maxRetries + 1;
|
|
775
846
|
const logPath = path.split("?")[0];
|
|
776
847
|
const deadlineAt = this.deadlineAt();
|
|
848
|
+
let payload;
|
|
849
|
+
try {
|
|
850
|
+
payload = body === undefined ? undefined : JSON.stringify(body);
|
|
851
|
+
}
|
|
852
|
+
catch (e) {
|
|
853
|
+
throw new Error(`request body could not be serialized: ${e instanceof Error ? e.message : String(e)}. ` +
|
|
854
|
+
"Pass plain JSON values — an ORM entity, a BigInt or a circular reference cannot be sent.");
|
|
855
|
+
}
|
|
777
856
|
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
778
857
|
const start = Date.now();
|
|
779
858
|
const att = this.beginAttempt(deadlineAt);
|
|
@@ -782,7 +861,7 @@ export class Client {
|
|
|
782
861
|
res = await this.fetchImpl(`${this.base}${path}`, {
|
|
783
862
|
method,
|
|
784
863
|
headers: extraHeaders ? { ...this.headers, ...extraHeaders } : this.headers,
|
|
785
|
-
body:
|
|
864
|
+
body: payload,
|
|
786
865
|
signal: att.signal,
|
|
787
866
|
redirect: "manual",
|
|
788
867
|
});
|
|
@@ -826,7 +905,14 @@ export class Client {
|
|
|
826
905
|
}
|
|
827
906
|
if (e instanceof WosError)
|
|
828
907
|
throw e;
|
|
829
|
-
|
|
908
|
+
if (!(IDEMPOTENT_METHODS.has(method.toUpperCase()) && attempt + 1 < attempts)) {
|
|
909
|
+
throw new APIConnectionError(0, `network error: ${e?.message ?? e}`);
|
|
910
|
+
}
|
|
911
|
+
att.clear();
|
|
912
|
+
const delay = this.backoffMs(attempt);
|
|
913
|
+
logDebug(`${method} ${logPath} — body dropped mid-stream, retrying in ${delay}ms (attempt ${attempt + 1}/${attempts})`);
|
|
914
|
+
await this.backoffSleep(delay, deadlineAt);
|
|
915
|
+
continue;
|
|
830
916
|
}
|
|
831
917
|
finally {
|
|
832
918
|
att.clear();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wontopos",
|
|
3
|
-
"version": "2.2.
|
|
4
|
-
"description": "Wontopos
|
|
3
|
+
"version": "2.2.39",
|
|
4
|
+
"description": "Wontopos \u2014 long-term memory for AI agents. Identical recall in every language, ~100\u00d7 lower LLM bill.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"memory",
|
|
7
7
|
"ai",
|
|
@@ -20,11 +20,17 @@
|
|
|
20
20
|
"types": "./dist/wontopos.d.ts",
|
|
21
21
|
"exports": {
|
|
22
22
|
".": {
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
"import": {
|
|
24
|
+
"types": "./dist/wontopos.d.ts",
|
|
25
|
+
"default": "./dist/wontopos.js"
|
|
26
|
+
},
|
|
27
|
+
"require": {
|
|
28
|
+
"types": "./dist/cjs/wontopos.d.cts",
|
|
29
|
+
"default": "./dist/cjs/wontopos.js"
|
|
30
|
+
},
|
|
26
31
|
"default": "./dist/wontopos.js"
|
|
27
|
-
}
|
|
32
|
+
},
|
|
33
|
+
"./package.json": "./package.json"
|
|
28
34
|
},
|
|
29
35
|
"files": [
|
|
30
36
|
"dist",
|
|
@@ -35,7 +41,7 @@
|
|
|
35
41
|
"node": ">=18"
|
|
36
42
|
},
|
|
37
43
|
"scripts": {
|
|
38
|
-
"build": "tsc && tsc -p tsconfig.types.json && tsc -p tsconfig.cjs.json && node -e \"require('fs').writeFileSync('dist/cjs/package.json','{\\\"type\\\":\\\"commonjs\\\"}\\n')\"",
|
|
44
|
+
"build": "tsc && tsc -p tsconfig.types.json && tsc -p tsconfig.cjs.json && node -e \"const fs=require('fs');fs.writeFileSync('dist/cjs/package.json','{\\\"type\\\":\\\"commonjs\\\"}\\n');fs.copyFileSync('dist/wontopos.d.ts','dist/cjs/wontopos.d.cts')\"",
|
|
39
45
|
"test": "npm run build && node --test tests/client.test.mjs tests/cjs.test.cjs",
|
|
40
46
|
"prepublishOnly": "npm run build && node scripts/pre-publish.mjs"
|
|
41
47
|
},
|
|
@@ -44,5 +50,9 @@
|
|
|
44
50
|
},
|
|
45
51
|
"bugs": {
|
|
46
52
|
"url": "https://wontopos.com/contact?topic=bug"
|
|
53
|
+
},
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://github.com/wontopos/wontopos-node.git"
|
|
47
57
|
}
|
|
48
58
|
}
|