wontopos 2.2.15 → 2.2.16
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/wontopos.js +16 -6
- package/package.json +1 -1
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.16";
|
|
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). */
|
|
@@ -69,6 +69,10 @@ const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "0.0.0.0"]);
|
|
|
69
69
|
const MAX_RESPONSE_BYTES = 64 * 1024 * 1024;
|
|
70
70
|
/** Model names travel in a header — only header-safe characters. */
|
|
71
71
|
const MODEL_RE = /^[A-Za-z0-9._-]+$/;
|
|
72
|
+
/** Cap a server-controlled error message so a hostile body can't blow up a log. */
|
|
73
|
+
const MAX_ERR_MSG = 4096;
|
|
74
|
+
/** Paging backstop: bound the walk so a fresh-cursor-forever server can't loop us. */
|
|
75
|
+
const MAX_PAGES = 1_000_000;
|
|
72
76
|
/** Error codes that only occur while ESTABLISHING a connection — the request
|
|
73
77
|
* never reached the server, so a retry can't double-process a write. Mid-stream
|
|
74
78
|
* codes (ECONNRESET, EPIPE, UND_ERR_SOCKET, ETIMEDOUT) are ambiguous: the server
|
|
@@ -381,12 +385,13 @@ export class Client {
|
|
|
381
385
|
async *iterMemories(userId, opts = {}) {
|
|
382
386
|
let cursor;
|
|
383
387
|
const seen = new Set();
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
388
|
+
// Backstop: the cursor-repeat guard catches a repeated cursor, but not a
|
|
389
|
+
// server that mints a FRESH cursor every page forever — bound the walk.
|
|
390
|
+
for (let page = 0; page < MAX_PAGES; page++) {
|
|
391
|
+
const p = await this.listMemories(userId, { limit: opts.pageSize ?? 100, cursor });
|
|
392
|
+
for (const m of p.memories ?? [])
|
|
387
393
|
yield m;
|
|
388
|
-
const next =
|
|
389
|
-
// Stop on last page OR a server that repeats a cursor (would loop forever).
|
|
394
|
+
const next = p.next_cursor ?? undefined;
|
|
390
395
|
if (!next || seen.has(next))
|
|
391
396
|
break;
|
|
392
397
|
seen.add(next);
|
|
@@ -564,6 +569,7 @@ export class Client {
|
|
|
564
569
|
}
|
|
565
570
|
if ((res.status >= 300 && res.status < 400) || res.type === "opaqueredirect") {
|
|
566
571
|
clearTimeout(timer);
|
|
572
|
+
void res.body?.cancel(); // release the stream — otherwise the connection leaks
|
|
567
573
|
throw new WosError(res.status, "unexpected redirect — refused (the API key never follows a redirect). Check baseUrl: exact host, https://.");
|
|
568
574
|
}
|
|
569
575
|
this._rateLimit = parseRateLimit(res.headers) ?? this._rateLimit;
|
|
@@ -612,6 +618,10 @@ export class Client {
|
|
|
612
618
|
catch {
|
|
613
619
|
/* keep raw text */
|
|
614
620
|
}
|
|
621
|
+
// Cap the FINAL message (a string `error` field can be as huge as the body),
|
|
622
|
+
// so a hostile server can't turn our exception/log into a giant string.
|
|
623
|
+
if (typeof msg === "string" && msg.length > MAX_ERR_MSG)
|
|
624
|
+
msg = msg.slice(0, MAX_ERR_MSG) + "…(truncated)";
|
|
615
625
|
throw errorFor(res.status, msg, requestId);
|
|
616
626
|
}
|
|
617
627
|
if (!text)
|
package/package.json
CHANGED