@remnic/core 10.0.31 → 10.0.33
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/access-admin-ops-surface.js +4 -4
- package/dist/access-authorization-probe.js +5 -5
- package/dist/access-boundary.js +4 -4
- package/dist/access-cli.js +22 -22
- package/dist/access-extraction-force-flush.js +4 -4
- package/dist/access-http-briefing.js +5 -5
- package/dist/access-http-query.js +4 -4
- package/dist/access-http.js +16 -16
- package/dist/access-identity-continuity-surface.js +4 -4
- package/dist/access-lcm-surface.js +4 -4
- package/dist/access-mcp.js +11 -11
- package/dist/access-namespace-preflight.js +4 -4
- package/dist/access-observe-write-surface.js +4 -4
- package/dist/access-operations-batch.js +5 -5
- package/dist/access-operations.js +10 -10
- package/dist/access-recall-concurrency.js +4 -4
- package/dist/access-recall-response.js +4 -4
- package/dist/access-recall-surface.js +4 -4
- package/dist/access-service.js +4 -4
- package/dist/access-surface-catalog.js +6 -6
- package/dist/calibration.js +2 -2
- package/dist/{chunk-5HJCZ7SB.js → chunk-2XYXESKN.js} +2 -2
- package/dist/{chunk-42MM5DKK.js → chunk-32WCMGIF.js} +2 -2
- package/dist/{chunk-WK7GFAQ2.js → chunk-3JYHSXYS.js} +2 -2
- package/dist/{chunk-J6SZXAQ2.js → chunk-5ARKPBLS.js} +2 -2
- package/dist/{chunk-EXYDKAR6.js → chunk-5B4UQF6K.js} +3 -3
- package/dist/{chunk-TB2J4PBY.js → chunk-5CIKBKU6.js} +1 -1
- package/dist/{chunk-3EJQXF3B.js → chunk-6FOKJ423.js} +2 -2
- package/dist/{chunk-GJBSEMC5.js → chunk-ASBDON6P.js} +3 -3
- package/dist/{chunk-WPCK6EJ2.js → chunk-BXCKME3Q.js} +2 -2
- package/dist/{chunk-3IDNKOCE.js → chunk-IEGJFQPG.js} +2 -2
- package/dist/{chunk-2IXEKMBJ.js → chunk-IRBXNULW.js} +3 -3
- package/dist/{chunk-464QR7WO.js → chunk-KW5B533Q.js} +9 -9
- package/dist/{chunk-UZDOPJ2P.js → chunk-M3VACAD2.js} +2 -2
- package/dist/{chunk-HJ444KNS.js → chunk-QEDLJDHP.js} +9 -5
- package/dist/chunk-QEDLJDHP.js.map +1 -0
- package/dist/{chunk-NRLWHZVS.js → chunk-QLDZJEJC.js} +2 -2
- package/dist/{chunk-OTWZXOJI.js → chunk-QNQNFRIZ.js} +2 -2
- package/dist/{chunk-W7X7XT7Z.js → chunk-TI6EN3PF.js} +8 -8
- package/dist/{chunk-RILIWZA6.js → chunk-UXWO5L7B.js} +2 -2
- package/dist/{chunk-A5ZY537U.js → chunk-XD5YSVP5.js} +2 -2
- package/dist/{chunk-YGBWSKBD.js → chunk-YIN6Y2I4.js} +2 -2
- package/dist/{chunk-HSPEVXT5.js → chunk-Z3XTS4TD.js} +4 -4
- package/dist/{chunk-ID62FNER.js → chunk-ZJGTJAB3.js} +2 -2
- package/dist/cli.js +17 -17
- package/dist/compounding/engine.js +1 -1
- package/dist/external-wiki-access.js +5 -5
- package/dist/extraction.js +3 -3
- package/dist/index.js +22 -22
- package/dist/local-llm-rate-limit.d.ts +1 -1
- package/dist/local-llm-rate-limit.d.ts.map +1 -1
- package/dist/local-llm-rate-limit.js +1 -1
- package/dist/local-llm.js +2 -2
- package/dist/memory-browse-operations.js +5 -5
- package/dist/orchestration/maintenance.js +4 -4
- package/dist/orchestrator.js +22 -22
- package/dist/recall-navigation-operations.js +5 -5
- package/dist/recall-navigation.js +4 -4
- package/dist/summarizer.js +3 -3
- package/dist/support-passport/index.js +7 -7
- package/package.json +2 -2
- package/src/local-llm-rate-limit.test.ts +28 -0
- package/src/local-llm-rate-limit.ts +12 -5
- package/dist/chunk-HJ444KNS.js.map +0 -1
- /package/dist/{chunk-5HJCZ7SB.js.map → chunk-2XYXESKN.js.map} +0 -0
- /package/dist/{chunk-42MM5DKK.js.map → chunk-32WCMGIF.js.map} +0 -0
- /package/dist/{chunk-WK7GFAQ2.js.map → chunk-3JYHSXYS.js.map} +0 -0
- /package/dist/{chunk-J6SZXAQ2.js.map → chunk-5ARKPBLS.js.map} +0 -0
- /package/dist/{chunk-EXYDKAR6.js.map → chunk-5B4UQF6K.js.map} +0 -0
- /package/dist/{chunk-TB2J4PBY.js.map → chunk-5CIKBKU6.js.map} +0 -0
- /package/dist/{chunk-3EJQXF3B.js.map → chunk-6FOKJ423.js.map} +0 -0
- /package/dist/{chunk-GJBSEMC5.js.map → chunk-ASBDON6P.js.map} +0 -0
- /package/dist/{chunk-WPCK6EJ2.js.map → chunk-BXCKME3Q.js.map} +0 -0
- /package/dist/{chunk-3IDNKOCE.js.map → chunk-IEGJFQPG.js.map} +0 -0
- /package/dist/{chunk-2IXEKMBJ.js.map → chunk-IRBXNULW.js.map} +0 -0
- /package/dist/{chunk-464QR7WO.js.map → chunk-KW5B533Q.js.map} +0 -0
- /package/dist/{chunk-UZDOPJ2P.js.map → chunk-M3VACAD2.js.map} +0 -0
- /package/dist/{chunk-NRLWHZVS.js.map → chunk-QLDZJEJC.js.map} +0 -0
- /package/dist/{chunk-OTWZXOJI.js.map → chunk-QNQNFRIZ.js.map} +0 -0
- /package/dist/{chunk-W7X7XT7Z.js.map → chunk-TI6EN3PF.js.map} +0 -0
- /package/dist/{chunk-RILIWZA6.js.map → chunk-UXWO5L7B.js.map} +0 -0
- /package/dist/{chunk-A5ZY537U.js.map → chunk-XD5YSVP5.js.map} +0 -0
- /package/dist/{chunk-YGBWSKBD.js.map → chunk-YIN6Y2I4.js.map} +0 -0
- /package/dist/{chunk-HSPEVXT5.js.map → chunk-Z3XTS4TD.js.map} +0 -0
- /package/dist/{chunk-ID62FNER.js.map → chunk-ZJGTJAB3.js.map} +0 -0
package/dist/summarizer.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HourlySummarizer,
|
|
3
3
|
summarizeHourlyStatus
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QLDZJEJC.js";
|
|
5
5
|
import "./chunk-FLI6DEIU.js";
|
|
6
6
|
import "./chunk-5Y43VGYB.js";
|
|
7
7
|
import "./chunk-5MA7ZLPD.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-6FOKJ423.js";
|
|
9
9
|
import "./chunk-MLED254J.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-QEDLJDHP.js";
|
|
11
11
|
import "./chunk-U4LUIE6Y.js";
|
|
12
12
|
import "./chunk-JUXOTY6J.js";
|
|
13
13
|
import "./chunk-KF7PQ7G2.js";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
SUPPORT_PASSPORT_MODEL_RESULT_PATH,
|
|
5
5
|
SupportPassportModelBridge,
|
|
6
6
|
parseSupportPassportModelJob
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-BXCKME3Q.js";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_SUPPORT_PASSPORT_CONFIG,
|
|
10
10
|
parseSupportPassportConfig
|
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
buildSupportPassportPublicRequestHandler,
|
|
15
15
|
composeSupportPassportExternalRequestHandlers,
|
|
16
16
|
normalizeSupportPassportNetworkAddress
|
|
17
|
-
} from "../chunk-
|
|
18
|
-
import "../chunk-
|
|
17
|
+
} from "../chunk-3JYHSXYS.js";
|
|
18
|
+
import "../chunk-IEGJFQPG.js";
|
|
19
19
|
import {
|
|
20
20
|
SUPPORT_PASSPORT_DRAFT_MAX_CONTENT_CHARACTERS,
|
|
21
21
|
SUPPORT_PASSPORT_DRAFT_MAX_MEMORIES,
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
notifySupportPassportCommitted,
|
|
57
57
|
resolveSupportPassportModelRoutePlan,
|
|
58
58
|
syncDirectoryForDurability
|
|
59
|
-
} from "../chunk-
|
|
59
|
+
} from "../chunk-IRBXNULW.js";
|
|
60
60
|
import "../chunk-W4F3C7N7.js";
|
|
61
61
|
import "../chunk-MPC7TYTZ.js";
|
|
62
62
|
import "../chunk-ISMZ5UNE.js";
|
|
@@ -69,7 +69,7 @@ import "../chunk-OIKLZCJD.js";
|
|
|
69
69
|
import "../chunk-GNVZQ5JN.js";
|
|
70
70
|
import "../chunk-YN2UN7N3.js";
|
|
71
71
|
import "../chunk-JWX2Q6HS.js";
|
|
72
|
-
import "../chunk-
|
|
72
|
+
import "../chunk-QLDZJEJC.js";
|
|
73
73
|
import "../chunk-FLI6DEIU.js";
|
|
74
74
|
import "../chunk-WWDO7ZWM.js";
|
|
75
75
|
import "../chunk-UAAAXSKQ.js";
|
|
@@ -131,9 +131,9 @@ import "../chunk-2LSZVONP.js";
|
|
|
131
131
|
import "../chunk-DEUNUKTD.js";
|
|
132
132
|
import "../chunk-LXY5VVGM.js";
|
|
133
133
|
import "../chunk-GKCXTSFF.js";
|
|
134
|
-
import "../chunk-
|
|
134
|
+
import "../chunk-6FOKJ423.js";
|
|
135
135
|
import "../chunk-MLED254J.js";
|
|
136
|
-
import "../chunk-
|
|
136
|
+
import "../chunk-QEDLJDHP.js";
|
|
137
137
|
import "../chunk-U4LUIE6Y.js";
|
|
138
138
|
import "../chunk-JUXOTY6J.js";
|
|
139
139
|
import "../chunk-ZY2MNJR6.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/core",
|
|
3
|
-
"version": "10.0.
|
|
3
|
+
"version": "10.0.33",
|
|
4
4
|
"description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -3347,7 +3347,7 @@
|
|
|
3347
3347
|
"core"
|
|
3348
3348
|
],
|
|
3349
3349
|
"peerDependencies": {
|
|
3350
|
-
"@remnic/coding-graph": "^10.0.
|
|
3350
|
+
"@remnic/coding-graph": "^10.0.33"
|
|
3351
3351
|
},
|
|
3352
3352
|
"peerDependenciesMeta": {
|
|
3353
3353
|
"@remnic/coding-graph": {
|
|
@@ -450,6 +450,34 @@ test("reserved background queue survives aborts and responds to resizing", async
|
|
|
450
450
|
assert.equal(limiter.inFlight, 0);
|
|
451
451
|
});
|
|
452
452
|
|
|
453
|
+
for (const max of [2, 4]) {
|
|
454
|
+
test(`queued background work progresses under critical backlog at cap ${max}`, async () => {
|
|
455
|
+
const limiter = new LocalLlmConcurrencyLimiter(max);
|
|
456
|
+
const held = await Promise.all(Array.from({ length: max }, () => limiter.acquire({ highPriority: true })));
|
|
457
|
+
assert.ok(held.every(Boolean));
|
|
458
|
+
const controller = new AbortController();
|
|
459
|
+
const backgroundRelease = limiter.acquire({ signal: controller.signal });
|
|
460
|
+
const criticalBacklog = limiter.acquire({ highPriority: true, signal: controller.signal });
|
|
461
|
+
try {
|
|
462
|
+
assert.equal(limiter.queued, 2);
|
|
463
|
+
held[0]?.();
|
|
464
|
+
const background = await Promise.race([backgroundRelease, Promise.resolve(null)]);
|
|
465
|
+
assert.ok(background, "background must get the released permit while critical work stays live");
|
|
466
|
+
assert.equal(limiter.inFlight, max);
|
|
467
|
+
assert.equal(limiter.queued, 1);
|
|
468
|
+
background();
|
|
469
|
+
const critical = await criticalBacklog;
|
|
470
|
+
assert.ok(critical, "critical backlog resumes when background no longer needs its permit");
|
|
471
|
+
critical();
|
|
472
|
+
} finally {
|
|
473
|
+
controller.abort();
|
|
474
|
+
for (const release of [...held, ...await Promise.all([backgroundRelease, criticalBacklog])]) release?.();
|
|
475
|
+
}
|
|
476
|
+
assert.equal(limiter.inFlight, 0);
|
|
477
|
+
assert.equal(limiter.queued, 0);
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
|
|
453
481
|
test("one-permit and unlimited limits still admit background work", async () => {
|
|
454
482
|
for (const max of [1, 0]) {
|
|
455
483
|
const limiter = new LocalLlmConcurrencyLimiter(max);
|
|
@@ -151,7 +151,7 @@ export function computeRateLimitDelayMs(
|
|
|
151
151
|
|
|
152
152
|
type Waiter = { highPriority: boolean; grant: () => void };
|
|
153
153
|
|
|
154
|
-
/**
|
|
154
|
+
/** Priority semaphore; finite caps above one protect recall capacity and queued background progress. */
|
|
155
155
|
export class LocalLlmConcurrencyLimiter {
|
|
156
156
|
private active = 0;
|
|
157
157
|
private activeBackground = 0;
|
|
@@ -224,9 +224,12 @@ export class LocalLlmConcurrencyLimiter {
|
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
private canAcquire(highPriority: boolean): boolean {
|
|
227
|
+
const backgroundWaiting = highPriority && this.max > 1 && this.activeBackground === 0 &&
|
|
228
|
+
this.waiters.some((waiter) => !waiter.highPriority);
|
|
227
229
|
return this.max <= 0 || (
|
|
228
230
|
this.active < this.max &&
|
|
229
|
-
(highPriority || this.max === 1 || this.activeBackground < this.max - 1)
|
|
231
|
+
(highPriority || this.max === 1 || this.activeBackground < this.max - 1) &&
|
|
232
|
+
(!highPriority || !backgroundWaiting || this.active < this.max - 1)
|
|
230
233
|
);
|
|
231
234
|
}
|
|
232
235
|
|
|
@@ -242,9 +245,13 @@ export class LocalLlmConcurrencyLimiter {
|
|
|
242
245
|
}
|
|
243
246
|
|
|
244
247
|
private pump(): void {
|
|
245
|
-
while (this.waiters.length > 0
|
|
246
|
-
|
|
247
|
-
|
|
248
|
+
while (this.waiters.length > 0) {
|
|
249
|
+
// An ineligible critical head must not strand the background permit.
|
|
250
|
+
const criticalAllowed = this.canAcquire(true);
|
|
251
|
+
const backgroundAllowed = this.canAcquire(false);
|
|
252
|
+
const index = this.waiters.findIndex((waiter) => waiter.highPriority ? criticalAllowed : backgroundAllowed);
|
|
253
|
+
if (index < 0) break;
|
|
254
|
+
const next = this.waiters.splice(index, 1)[0];
|
|
248
255
|
this.active += 1;
|
|
249
256
|
if (!next.highPriority) this.activeBackground += 1;
|
|
250
257
|
next.grant();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/local-llm-rate-limit.ts"],"sourcesContent":["/**\n * Process-wide rate-limit handling for the local LLM client (COS-447).\n *\n * A LiteLLM proxy in front of the local models answers `429 No deployments\n * available` (and `503`/`408`) when every deployment is busy or in cooldown.\n * Before this module the client returned on the first 429 and the caller\n * loop immediately issued the next request, so one daemon could hammer the\n * proxy with thousands of calls per hour while it was saturated.\n *\n * This module provides three pieces that the client composes:\n *\n * - classification of rate-limit responses and of the retry hint\n * (`Retry-After` header as delta-seconds or HTTP-date, falling back to\n * LiteLLM's `Try again in N seconds` body text);\n * - exponential backoff with full jitter;\n * - process-wide state shared by every `LocalLlmClient` instance: a\n * concurrency semaphore for in-flight HTTP attempts and a per-endpoint\n * \"do not call before\" deadline, so one client's 429 slows every client\n * pointed at the same endpoint.\n *\n * State lives on `globalThis` so duplicated module copies in bundled output\n * still share one limiter.\n */\n\nexport const RATE_LIMIT_STATUSES: ReadonlySet<number> = new Set([408, 429, 503]);\n\nconst RATE_LIMIT_BODY_PATTERN = /no deployments available|cooldown_list|all deployments.*cooldown/i;\nconst TRY_AGAIN_PATTERN = /try again in (\\d+(?:\\.\\d+)?) ?(seconds?|secs?|s|milliseconds?|ms|minutes?|mins?)\\b/i;\n\n/** Upper bound on any server-provided wait we will record (sanity clamp). */\nexport const MAX_RECORDED_BACKOFF_MS = 10 * 60_000;\n\nexport const DEFAULT_RATE_LIMIT_RETRY_COUNT = 3;\nexport const DEFAULT_RATE_LIMIT_BACKOFF_BASE_MS = 1_000;\nexport const DEFAULT_RATE_LIMIT_BACKOFF_MAX_MS = 60_000;\nexport const DEFAULT_MAX_CONCURRENCY = 4;\n\nexport interface LocalLlmRateLimitSettings {\n retryCount: number;\n backoffBaseMs: number;\n backoffMaxMs: number;\n /** 0 disables the process-wide concurrency cap. */\n maxConcurrency: number;\n}\n\nfunction nonNegativeInt(value: number | undefined, fallback: number): number {\n if (value === undefined || !Number.isFinite(value) || value < 0) return fallback;\n return Math.floor(value);\n}\n\nexport function resolveRateLimitSettings(config: {\n localLlmRateLimitRetryCount?: number;\n localLlmRateLimitBackoffBaseMs?: number;\n localLlmRateLimitBackoffMaxMs?: number;\n localLlmMaxConcurrency?: number;\n}): LocalLlmRateLimitSettings {\n const backoffBaseMs = Math.max(\n 1,\n nonNegativeInt(config.localLlmRateLimitBackoffBaseMs, DEFAULT_RATE_LIMIT_BACKOFF_BASE_MS)\n );\n const backoffMaxMs = Math.max(\n backoffBaseMs,\n nonNegativeInt(config.localLlmRateLimitBackoffMaxMs, DEFAULT_RATE_LIMIT_BACKOFF_MAX_MS)\n );\n return {\n retryCount: nonNegativeInt(config.localLlmRateLimitRetryCount, DEFAULT_RATE_LIMIT_RETRY_COUNT),\n backoffBaseMs,\n backoffMaxMs,\n maxConcurrency: nonNegativeInt(config.localLlmMaxConcurrency, DEFAULT_MAX_CONCURRENCY),\n };\n}\n\n/**\n * True for responses that mean \"the endpoint is saturated, slow down\":\n * 408/429/503, or a 5xx whose body carries LiteLLM's cooldown wording.\n * 400s are never rate limits (context-window errors mention fallbacks).\n */\nexport function isRateLimitedResponse(status: number, bodyText: string): boolean {\n if (RATE_LIMIT_STATUSES.has(status)) return true;\n return status >= 500 && RATE_LIMIT_BODY_PATTERN.test(bodyText);\n}\n\n/**\n * Parse an HTTP `Retry-After` value (RFC 9110: delta-seconds or HTTP-date).\n * Returns milliseconds to wait, or null when absent/invalid.\n */\nexport function parseRetryAfterMs(value: string | null | undefined, nowMs: number = Date.now()): number | null {\n if (value === null || value === undefined) return null;\n const trimmed = value.trim();\n if (!trimmed) return null;\n if (/^\\d+(\\.\\d+)?$/.test(trimmed)) {\n return Math.min(MAX_RECORDED_BACKOFF_MS, Math.round(Number(trimmed) * 1000));\n }\n const dateMs = Date.parse(trimmed);\n if (Number.isNaN(dateMs)) return null;\n return Math.min(MAX_RECORDED_BACKOFF_MS, Math.max(0, dateMs - nowMs));\n}\n\n/** Parse LiteLLM's `Try again in N seconds` hint from an error body. */\nexport function parseTryAgainHintMs(bodyText: string): number | null {\n const match = bodyText.match(TRY_AGAIN_PATTERN);\n if (!match) return null;\n const amount = Number(match[1]);\n if (!Number.isFinite(amount)) return null;\n const unit = match[2].toLowerCase();\n let ms: number;\n if (unit.startsWith(\"ms\") || unit.startsWith(\"milli\")) ms = amount;\n else if (unit.startsWith(\"min\")) ms = amount * 60_000;\n else ms = amount * 1000;\n return Math.min(MAX_RECORDED_BACKOFF_MS, Math.round(ms));\n}\n\n/** Server-provided wait: `Retry-After` header first, then the body hint. */\nexport function serverRetryHintMs(\n retryAfterHeader: string | null | undefined,\n bodyText: string,\n nowMs: number = Date.now()\n): number | null {\n return parseRetryAfterMs(retryAfterHeader, nowMs) ?? parseTryAgainHintMs(bodyText);\n}\n\n/**\n * Exponential backoff with full jitter: uniform in [0, min(max, base * 2^(n-1))].\n * `attempt` is 1-based (the number of consecutive rate-limit responses).\n */\nexport function computeFullJitterBackoffMs(\n attempt: number,\n baseMs: number,\n maxMs: number,\n random: () => number = Math.random\n): number {\n const exponent = Math.max(0, Math.min(30, attempt - 1));\n const ceiling = Math.min(maxMs, baseMs * 2 ** exponent);\n return Math.floor(random() * ceiling);\n}\n\n/**\n * Delay before the next attempt after a rate-limit response. A server hint\n * is a floor (never call earlier than asked); jitter is added on top of the\n * exponential term so synchronized callers spread out.\n */\nexport function computeRateLimitDelayMs(\n attempt: number,\n settings: Pick<LocalLlmRateLimitSettings, \"backoffBaseMs\" | \"backoffMaxMs\">,\n serverHintMs: number | null,\n random: () => number = Math.random\n): number {\n const jittered = computeFullJitterBackoffMs(attempt, settings.backoffBaseMs, settings.backoffMaxMs, random);\n return serverHintMs === null ? jittered : Math.max(serverHintMs, jittered);\n}\n\ntype Waiter = { highPriority: boolean; grant: () => void };\n\n/** FIFO semaphore; finite caps above one reserve a permit for recall-critical work. */\nexport class LocalLlmConcurrencyLimiter {\n private active = 0;\n private activeBackground = 0;\n private max: number;\n private readonly waiters: Waiter[] = [];\n\n constructor(max: number) {\n this.max = max;\n }\n\n setMax(max: number): void {\n this.max = max;\n this.pump();\n }\n\n get inFlight(): number {\n return this.active;\n }\n\n get queued(): number {\n return this.waiters.length;\n }\n\n /**\n * Wait for a slot. Resolves to a release function, or null when the\n * signal aborts first. `max <= 0` means unlimited.\n */\n acquire(\n options: { highPriority?: boolean; signal?: AbortSignal; timeoutMs?: number } = {}\n ): Promise<(() => void) | null> {\n const { signal, timeoutMs } = options;\n const highPriority = options.highPriority === true;\n if (signal?.aborted) return Promise.resolve(null);\n if (\n this.canAcquire(highPriority) &&\n (this.waiters.length === 0 || (highPriority && !this.waiters[0].highPriority))\n ) {\n this.active += 1;\n if (!highPriority) this.activeBackground += 1;\n return Promise.resolve(this.releaser(highPriority));\n }\n if (timeoutMs !== undefined && timeoutMs <= 0) return Promise.resolve(null);\n return new Promise((resolve) => {\n let timer: NodeJS.Timeout | undefined;\n const waiter: Waiter = {\n highPriority,\n grant: () => {\n signal?.removeEventListener(\"abort\", onAbort);\n if (timer) clearTimeout(timer);\n resolve(this.releaser(highPriority));\n },\n };\n const onAbort = (): void => {\n const index = this.waiters.indexOf(waiter);\n if (index >= 0) this.waiters.splice(index, 1);\n signal?.removeEventListener(\"abort\", onAbort);\n if (timer) clearTimeout(timer);\n resolve(null);\n };\n if (waiter.highPriority) {\n const firstLow = this.waiters.findIndex((w) => !w.highPriority);\n if (firstLow < 0) this.waiters.push(waiter);\n else this.waiters.splice(firstLow, 0, waiter);\n } else {\n this.waiters.push(waiter);\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (timeoutMs !== undefined) timer = setTimeout(onAbort, timeoutMs);\n });\n }\n\n private canAcquire(highPriority: boolean): boolean {\n return this.max <= 0 || (\n this.active < this.max &&\n (highPriority || this.max === 1 || this.activeBackground < this.max - 1)\n );\n }\n\n private releaser(highPriority: boolean): () => void {\n let released = false;\n return () => {\n if (released) return;\n released = true;\n this.active -= 1;\n if (!highPriority) this.activeBackground -= 1;\n this.pump();\n };\n }\n\n private pump(): void {\n while (this.waiters.length > 0 && this.canAcquire(this.waiters[0].highPriority)) {\n const next = this.waiters.shift();\n if (!next) break;\n this.active += 1;\n if (!next.highPriority) this.activeBackground += 1;\n next.grant();\n }\n }\n}\n\ninterface EndpointBackoffState {\n untilMs: number;\n consecutiveRateLimits: number;\n}\n\ninterface RateLimitGlobalState {\n limiter: LocalLlmConcurrencyLimiter;\n endpoints: Map<string, EndpointBackoffState>;\n}\n\ndeclare global {\n // Shared across duplicated module copies in bundled output.\n var __remnicLocalLlmRateLimitState: RateLimitGlobalState | undefined;\n}\n\nfunction globalState(): RateLimitGlobalState {\n globalThis.__remnicLocalLlmRateLimitState ??= {\n limiter: new LocalLlmConcurrencyLimiter(DEFAULT_MAX_CONCURRENCY),\n endpoints: new Map(),\n };\n return globalThis.__remnicLocalLlmRateLimitState;\n}\n\n/** Process-wide limiter, resized to the caller's configured cap. */\nexport function getLocalLlmConcurrencyLimiter(maxConcurrency: number): LocalLlmConcurrencyLimiter {\n const { limiter } = globalState();\n limiter.setMax(maxConcurrency);\n return limiter;\n}\n\n/** Milliseconds until `endpoint` may be called again (0 when clear). */\nexport function endpointBackoffRemainingMs(endpoint: string, nowMs: number = Date.now()): number {\n const entry = globalState().endpoints.get(endpoint);\n return entry ? Math.max(0, entry.untilMs - nowMs) : 0;\n}\n\n/**\n * Record a rate-limit response for `endpoint`. Returns the consecutive\n * rate-limit count (1-based) to feed the backoff exponent.\n */\nexport function noteEndpointRateLimited(endpoint: string): number {\n const { endpoints } = globalState();\n const entry = endpoints.get(endpoint) ?? { untilMs: 0, consecutiveRateLimits: 0 };\n entry.consecutiveRateLimits += 1;\n endpoints.set(endpoint, entry);\n return entry.consecutiveRateLimits;\n}\n\n/** Push the endpoint's \"do not call before\" deadline out to at least `nowMs + delayMs`. */\nexport function extendEndpointBackoff(endpoint: string, delayMs: number, nowMs: number = Date.now()): void {\n const { endpoints } = globalState();\n const entry = endpoints.get(endpoint) ?? { untilMs: 0, consecutiveRateLimits: 0 };\n const bounded = Math.min(MAX_RECORDED_BACKOFF_MS, Math.max(0, delayMs));\n entry.untilMs = Math.max(entry.untilMs, nowMs + bounded);\n endpoints.set(endpoint, entry);\n}\n\n/**\n * Reset the backoff exponent after a non-rate-limited response. An already\n * recorded deadline is left to expire so concurrent callers that saw the\n * 429 still wait it out.\n */\nexport function noteEndpointRecovered(endpoint: string): void {\n const entry = globalState().endpoints.get(endpoint);\n if (entry) entry.consecutiveRateLimits = 0;\n}\n\n/** Test seam: drop all process-wide state. */\nexport function resetLocalLlmRateLimitStateForTests(): void {\n const state = globalState();\n state.endpoints.clear();\n state.limiter = new LocalLlmConcurrencyLimiter(DEFAULT_MAX_CONCURRENCY);\n}\n\nexport type RateLimitAttemptGate =\n | { kind: \"go\"; release: () => void }\n | { kind: \"aborted\" }\n | { kind: \"skip\"; reason: \"backoff\" | \"queue\"; remainingMs: number };\n\nexport type RateLimitDecision =\n | { kind: \"not-rate-limited\" }\n | { kind: \"retry\"; delayMs: number; hintMs: number | null; consecutive: number; retry: number }\n | { kind: \"give-up\"; delayMs: number; retries: number };\n\n/**\n * Per-request driver for the rate-limit policy. The client calls\n * `beforeAttempt` ahead of every HTTP attempt (waits out the shared endpoint\n * deadline, then takes a concurrency slot) and `onResponse` after every\n * non-ok response.\n */\nexport class LocalLlmRateLimitSession {\n private retries = 0;\n private readonly limiter: LocalLlmConcurrencyLimiter;\n readonly settings: LocalLlmRateLimitSettings;\n\n /**\n * @param waitBudgetMs the caller's per-attempt time budget. Waiting for the\n * endpoint backoff or a concurrency slot never exceeds it, and a backoff\n * longer than it skips the request instead (fail open to the caller).\n */\n constructor(\n private readonly endpoint: string,\n settings: LocalLlmRateLimitSettings,\n private readonly highPriority: boolean,\n private readonly waitBudgetMs: number = settings.backoffMaxMs\n ) {\n this.settings = settings;\n this.limiter = getLocalLlmConcurrencyLimiter(settings.maxConcurrency);\n }\n\n get retryCount(): number {\n return this.retries;\n }\n\n async beforeAttempt(signal?: AbortSignal): Promise<RateLimitAttemptGate> {\n const deadlineMs = Date.now() + Math.max(0, this.waitBudgetMs);\n // Recheck the shared deadline after every async wait: another attempt may\n // have recorded or extended a cooldown while this one slept or queued.\n for (;;) {\n const remainingMs = endpointBackoffRemainingMs(this.endpoint);\n if (remainingMs > 0) {\n if (remainingMs > Math.min(this.settings.backoffMaxMs, deadlineMs - Date.now())) {\n return { kind: \"skip\", reason: \"backoff\", remainingMs };\n }\n if (!(await waitWithSignal(remainingMs, signal))) return { kind: \"aborted\" };\n continue;\n }\n const release = await this.limiter.acquire({\n highPriority: this.highPriority,\n signal,\n timeoutMs: deadlineMs - Date.now(),\n });\n if (!release) return signal?.aborted ? { kind: \"aborted\" } : { kind: \"skip\", reason: \"queue\", remainingMs: 0 };\n if (endpointBackoffRemainingMs(this.endpoint) > 0) {\n release();\n continue;\n }\n return { kind: \"go\", release };\n }\n }\n\n onSuccess(): void {\n noteEndpointRecovered(this.endpoint);\n }\n\n onResponse(status: number, retryAfterHeader: string | null | undefined, bodyText: string): RateLimitDecision {\n if (!isRateLimitedResponse(status, bodyText)) {\n noteEndpointRecovered(this.endpoint);\n return { kind: \"not-rate-limited\" };\n }\n const consecutive = noteEndpointRateLimited(this.endpoint);\n const hintMs = serverRetryHintMs(retryAfterHeader, bodyText);\n const delayMs = computeRateLimitDelayMs(consecutive, this.settings, hintMs);\n extendEndpointBackoff(this.endpoint, delayMs);\n if (this.retries >= this.settings.retryCount || delayMs > Math.min(this.settings.backoffMaxMs, this.waitBudgetMs)) {\n return { kind: \"give-up\", delayMs, retries: this.retries };\n }\n this.retries += 1;\n return { kind: \"retry\", delayMs, hintMs, consecutive, retry: this.retries };\n }\n}\n\nfunction waitWithSignal(ms: number, signal?: AbortSignal): Promise<boolean> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve(false);\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n resolve(false);\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(true);\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|