@rynfar/meridian 1.57.0 → 1.57.1
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/{cli-ngtexmne.js → cli-h6hfkg3s.js} +30 -2
- package/dist/{cli-bsg2dd52.js → cli-kjd4cwcq.js} +1 -1
- package/dist/{cli-340h1chz.js → cli-vj9cv18n.js} +11 -6
- package/dist/{cli-sz964j04.js → cli-wszp24mg.js} +131 -74
- package/dist/cli.js +6 -6
- package/dist/{profileCli-00z04stw.js → profileCli-b1zmg2ad.js} +2 -2
- package/dist/{profiles-sq9t3fh9.js → profiles-3rg4x7cz.js} +2 -2
- package/dist/proxy/openaiResponses.d.ts +4 -2
- package/dist/proxy/openaiResponses.d.ts.map +1 -1
- package/dist/proxy/rateLimitStore.d.ts +26 -22
- package/dist/proxy/rateLimitStore.d.ts.map +1 -1
- package/dist/proxy/routing.d.ts +24 -1
- package/dist/proxy/routing.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/session/cache.d.ts.map +1 -1
- package/dist/proxy/session/fingerprint.d.ts +26 -0
- package/dist/proxy/session/fingerprint.d.ts.map +1 -1
- package/dist/proxy/session/lineage.d.ts +15 -9
- package/dist/proxy/session/lineage.d.ts.map +1 -1
- package/dist/proxy/settings.d.ts.map +1 -1
- package/dist/server.js +4 -4
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getSetting,
|
|
3
3
|
setSetting
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-vj9cv18n.js";
|
|
5
5
|
|
|
6
6
|
// src/proxy/profiles.ts
|
|
7
7
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -98,6 +98,34 @@ class ProfileExhaustion {
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
class AssignmentStore {
|
|
102
|
+
max;
|
|
103
|
+
entries = new Map;
|
|
104
|
+
constructor(max) {
|
|
105
|
+
this.max = max;
|
|
106
|
+
}
|
|
107
|
+
get(key) {
|
|
108
|
+
const value = this.entries.get(key);
|
|
109
|
+
if (value === undefined)
|
|
110
|
+
return;
|
|
111
|
+
this.entries.delete(key);
|
|
112
|
+
this.entries.set(key, value);
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
set(key, value) {
|
|
116
|
+
this.entries.delete(key);
|
|
117
|
+
this.entries.set(key, value);
|
|
118
|
+
if (this.entries.size > this.max) {
|
|
119
|
+
const oldest = this.entries.keys().next().value;
|
|
120
|
+
if (oldest !== undefined)
|
|
121
|
+
this.entries.delete(oldest);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
get size() {
|
|
125
|
+
return this.entries.size;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
101
129
|
// src/proxy/profiles.ts
|
|
102
130
|
var CONFIG_FILE = join(homedir(), ".config", "meridian", "profiles.json");
|
|
103
131
|
var DISK_CACHE_TTL_MS = 5000;
|
|
@@ -213,4 +241,4 @@ function listProfiles(profiles, defaultProfile) {
|
|
|
213
241
|
}));
|
|
214
242
|
}
|
|
215
243
|
|
|
216
|
-
export { getRoutingMode, resolvePriorityOrder, choosePriorityProfile, ProfileExhaustion, loadProfilesFromDisk, setActiveProfile, getActiveProfileId, resetActiveProfile, restoreActiveProfile, enableDiskProfileDiscovery, getEffectiveProfiles, hasProfiles, resolveProfile, listProfiles };
|
|
244
|
+
export { getRoutingMode, resolvePriorityOrder, choosePriorityProfile, ProfileExhaustion, AssignmentStore, loadProfilesFromDisk, setActiveProfile, getActiveProfileId, resetActiveProfile, restoreActiveProfile, enableDiskProfileDiscovery, getEffectiveProfiles, hasProfiles, resolveProfile, listProfiles };
|
|
@@ -2,25 +2,30 @@
|
|
|
2
2
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
3
3
|
import { join, dirname } from "node:path";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
|
-
|
|
5
|
+
function settingsFile() {
|
|
6
|
+
const override = process.env.MERIDIAN_CONFIG_DIR;
|
|
7
|
+
return override ? join(override, "settings.json") : join(homedir(), ".config", "meridian", "settings.json");
|
|
8
|
+
}
|
|
6
9
|
function loadSettings() {
|
|
10
|
+
const file = settingsFile();
|
|
7
11
|
try {
|
|
8
|
-
if (!existsSync(
|
|
12
|
+
if (!existsSync(file))
|
|
9
13
|
return {};
|
|
10
|
-
return JSON.parse(readFileSync(
|
|
14
|
+
return JSON.parse(readFileSync(file, "utf-8"));
|
|
11
15
|
} catch {
|
|
12
16
|
return {};
|
|
13
17
|
}
|
|
14
18
|
}
|
|
15
19
|
function saveSettings(updates) {
|
|
20
|
+
const file = settingsFile();
|
|
16
21
|
const current = loadSettings();
|
|
17
22
|
const merged = { ...current, ...updates };
|
|
18
23
|
try {
|
|
19
|
-
mkdirSync(dirname(
|
|
20
|
-
writeFileSync(
|
|
24
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
25
|
+
writeFileSync(file, JSON.stringify(merged, null, 2) + `
|
|
21
26
|
`, { mode: 384 });
|
|
22
27
|
} catch (err) {
|
|
23
|
-
console.warn(`[meridian] Failed to write ${
|
|
28
|
+
console.warn(`[meridian] Failed to write ${file}: ${err instanceof Error ? err.message : err}`);
|
|
24
29
|
}
|
|
25
30
|
}
|
|
26
31
|
function getSetting(key) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AssignmentStore,
|
|
2
3
|
ProfileExhaustion,
|
|
3
4
|
choosePriorityProfile,
|
|
4
5
|
getActiveProfileId,
|
|
@@ -9,7 +10,7 @@ import {
|
|
|
9
10
|
resolveProfile,
|
|
10
11
|
restoreActiveProfile,
|
|
11
12
|
setActiveProfile
|
|
12
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-h6hfkg3s.js";
|
|
13
14
|
import {
|
|
14
15
|
isTrackedPlugin,
|
|
15
16
|
recordError,
|
|
@@ -47,11 +48,11 @@ import {
|
|
|
47
48
|
resolvePassthrough,
|
|
48
49
|
resolveSdkModelDefaults,
|
|
49
50
|
stripExtendedContext
|
|
50
|
-
} from "./cli-
|
|
51
|
+
} from "./cli-kjd4cwcq.js";
|
|
51
52
|
import {
|
|
52
53
|
getSetting,
|
|
53
54
|
setSetting
|
|
54
|
-
} from "./cli-
|
|
55
|
+
} from "./cli-vj9cv18n.js";
|
|
55
56
|
import {
|
|
56
57
|
checkPluginConfigured
|
|
57
58
|
} from "./cli-je60fevk.js";
|
|
@@ -4364,24 +4365,40 @@ import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
|
4364
4365
|
|
|
4365
4366
|
// src/proxy/rateLimitStore.ts
|
|
4366
4367
|
class RateLimitStore {
|
|
4367
|
-
|
|
4368
|
-
record(info, observedAt = Date.now()) {
|
|
4368
|
+
byProfile = new Map;
|
|
4369
|
+
record(profileId, info, observedAt = Date.now()) {
|
|
4369
4370
|
if (!info || typeof info !== "object")
|
|
4370
4371
|
return;
|
|
4371
4372
|
const key = info.rateLimitType ?? "default";
|
|
4372
|
-
this.
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
return this.entries.get(key);
|
|
4379
|
-
}
|
|
4380
|
-
get size() {
|
|
4381
|
-
return this.entries.size;
|
|
4373
|
+
let buckets = this.byProfile.get(profileId);
|
|
4374
|
+
if (!buckets) {
|
|
4375
|
+
buckets = new Map;
|
|
4376
|
+
this.byProfile.set(profileId, buckets);
|
|
4377
|
+
}
|
|
4378
|
+
buckets.set(key, { ...info, observedAt });
|
|
4382
4379
|
}
|
|
4383
|
-
|
|
4384
|
-
this.
|
|
4380
|
+
getAll(profileId) {
|
|
4381
|
+
const buckets = this.byProfile.get(profileId);
|
|
4382
|
+
if (!buckets)
|
|
4383
|
+
return [];
|
|
4384
|
+
return Array.from(buckets.values()).sort((a, b) => b.observedAt - a.observedAt);
|
|
4385
|
+
}
|
|
4386
|
+
get(profileId, key) {
|
|
4387
|
+
return this.byProfile.get(profileId)?.get(key);
|
|
4388
|
+
}
|
|
4389
|
+
size(profileId) {
|
|
4390
|
+
if (profileId !== undefined)
|
|
4391
|
+
return this.byProfile.get(profileId)?.size ?? 0;
|
|
4392
|
+
let total = 0;
|
|
4393
|
+
for (const buckets of this.byProfile.values())
|
|
4394
|
+
total += buckets.size;
|
|
4395
|
+
return total;
|
|
4396
|
+
}
|
|
4397
|
+
clear(profileId) {
|
|
4398
|
+
if (profileId !== undefined)
|
|
4399
|
+
this.byProfile.delete(profileId);
|
|
4400
|
+
else
|
|
4401
|
+
this.byProfile.clear();
|
|
4385
4402
|
}
|
|
4386
4403
|
}
|
|
4387
4404
|
var rateLimitStore = new RateLimitStore;
|
|
@@ -11086,13 +11103,25 @@ function buildModelList(isMaxSubscription, now = Math.floor(Date.now() / 1000))
|
|
|
11086
11103
|
}
|
|
11087
11104
|
|
|
11088
11105
|
// src/proxy/openaiResponses.ts
|
|
11106
|
+
function itemDiscriminator(item) {
|
|
11107
|
+
if (typeof item !== "object" || item === null)
|
|
11108
|
+
return;
|
|
11109
|
+
const record = item;
|
|
11110
|
+
if (typeof record.type === "string")
|
|
11111
|
+
return record.type;
|
|
11112
|
+
if (record.type === undefined && "role" in record)
|
|
11113
|
+
return "message";
|
|
11114
|
+
return;
|
|
11115
|
+
}
|
|
11089
11116
|
function partsToText(content) {
|
|
11117
|
+
if (content === undefined)
|
|
11118
|
+
return "";
|
|
11090
11119
|
if (typeof content === "string")
|
|
11091
11120
|
return content;
|
|
11092
11121
|
return content.filter((p) => typeof p.text === "string").map((p) => p.text).join("");
|
|
11093
11122
|
}
|
|
11094
11123
|
function partsToBlocks(content) {
|
|
11095
|
-
if (typeof content === "string")
|
|
11124
|
+
if (content === undefined || typeof content === "string")
|
|
11096
11125
|
return null;
|
|
11097
11126
|
const hasImage = content.some((p) => p.type === "input_image");
|
|
11098
11127
|
if (!hasImage)
|
|
@@ -11141,7 +11170,7 @@ function translateResponsesToAnthropic(body) {
|
|
|
11141
11170
|
}
|
|
11142
11171
|
};
|
|
11143
11172
|
for (const item of items) {
|
|
11144
|
-
switch (item
|
|
11173
|
+
switch (itemDiscriminator(item)) {
|
|
11145
11174
|
case "message": {
|
|
11146
11175
|
const msg = item;
|
|
11147
11176
|
if (msg.role === "developer" || msg.role === "system") {
|
|
@@ -11833,6 +11862,12 @@ function getConversationFingerprint(messages, workingDirectory) {
|
|
|
11833
11862
|
${text.slice(0, 2000)}` : text.slice(0, 2000);
|
|
11834
11863
|
return createHash("sha256").update(seed).digest("hex").slice(0, 16);
|
|
11835
11864
|
}
|
|
11865
|
+
function getPriorityAssignmentKey(sessionId, messages, workingDirectory) {
|
|
11866
|
+
if (sessionId)
|
|
11867
|
+
return sessionId;
|
|
11868
|
+
const fingerprint = getConversationFingerprint(messages, workingDirectory);
|
|
11869
|
+
return fingerprint ? `fp:${fingerprint}` : null;
|
|
11870
|
+
}
|
|
11836
11871
|
|
|
11837
11872
|
// src/proxy/adapters/opencode.ts
|
|
11838
11873
|
init_env();
|
|
@@ -19189,22 +19224,20 @@ function findSuffixAnchorStart(storedHashes, incomingHashes, suffixOverlap) {
|
|
|
19189
19224
|
return -1;
|
|
19190
19225
|
return anchor - suffixOverlap + 1;
|
|
19191
19226
|
}
|
|
19192
|
-
function verifyLineage(cached, messages
|
|
19227
|
+
function verifyLineage(cached, messages) {
|
|
19193
19228
|
if (!cached.lineageHash || cached.messageCount === 0) {
|
|
19194
|
-
return { type: "
|
|
19229
|
+
return { type: "diverged", reason: "unverifiable" };
|
|
19195
19230
|
}
|
|
19196
19231
|
const prefix = messages.slice(0, cached.messageCount);
|
|
19197
19232
|
const prefixHash = computeLineageHash(prefix);
|
|
19198
19233
|
if (prefixHash === cached.lineageHash) {
|
|
19199
19234
|
if (messages.length <= cached.messageCount) {
|
|
19200
|
-
|
|
19201
|
-
return { type: "diverged" };
|
|
19235
|
+
return { type: "diverged", reason: "replayed-request" };
|
|
19202
19236
|
}
|
|
19203
|
-
return { type: "continuation", session: cached };
|
|
19237
|
+
return { type: "continuation", session: cached, resumeFrom: cached.messageCount };
|
|
19204
19238
|
}
|
|
19205
19239
|
if (!cached.messageHashes || cached.messageHashes.length === 0) {
|
|
19206
|
-
|
|
19207
|
-
return { type: "diverged" };
|
|
19240
|
+
return { type: "diverged", reason: "unverifiable" };
|
|
19208
19241
|
}
|
|
19209
19242
|
const incomingHashes = computeMessageHashes(messages);
|
|
19210
19243
|
const prefixOverlap = measurePrefixOverlap(cached.messageHashes, incomingHashes);
|
|
@@ -19212,13 +19245,12 @@ function verifyLineage(cached, messages, cacheKey2, cache) {
|
|
|
19212
19245
|
const MIN_STORED_FOR_COMPACTION = 6;
|
|
19213
19246
|
const suffixStartInIncoming = incomingHashes.length - suffixOverlap >= 0 ? findSuffixAnchorStart(cached.messageHashes, incomingHashes, suffixOverlap) : -1;
|
|
19214
19247
|
if (suffixOverlap >= MIN_SUFFIX_FOR_COMPACTION && cached.messageHashes.length >= MIN_STORED_FOR_COMPACTION && suffixStartInIncoming > 0) {
|
|
19215
|
-
|
|
19216
|
-
|
|
19217
|
-
|
|
19218
|
-
|
|
19219
|
-
|
|
19220
|
-
|
|
19221
|
-
return { type: "compaction", session: cached };
|
|
19248
|
+
return {
|
|
19249
|
+
type: "compaction",
|
|
19250
|
+
session: cached,
|
|
19251
|
+
resumeFrom: suffixStartInIncoming + suffixOverlap,
|
|
19252
|
+
suffixOverlap
|
|
19253
|
+
};
|
|
19222
19254
|
}
|
|
19223
19255
|
if (prefixOverlap > 0 && suffixOverlap === 0 && messages.length <= cached.messageCount) {
|
|
19224
19256
|
let rollbackUuid;
|
|
@@ -19230,22 +19262,12 @@ function verifyLineage(cached, messages, cacheKey2, cache) {
|
|
|
19230
19262
|
}
|
|
19231
19263
|
}
|
|
19232
19264
|
}
|
|
19233
|
-
const undoMsg = `Undo detected (key=${cacheKey2.slice(0, 8)}…): prefix overlap ${prefixOverlap}/${cached.messageHashes.length}, rollback UUID: ${rollbackUuid || "none (legacy session)"}.`;
|
|
19234
|
-
console.error(`[PROXY] ${undoMsg}`);
|
|
19235
|
-
diagnosticLog2.lineage(undoMsg);
|
|
19236
19265
|
return { type: "undo", session: cached, prefixOverlap, rollbackUuid };
|
|
19237
19266
|
}
|
|
19238
19267
|
if (prefixOverlap > 0 && messages.length > cached.messageCount) {
|
|
19239
|
-
|
|
19240
|
-
console.error(`[PROXY] ${modifiedMsg}`);
|
|
19241
|
-
diagnosticLog2.lineage(modifiedMsg);
|
|
19242
|
-
cached.lineageHash = computeLineageHash(messages.slice(0, messages.length));
|
|
19243
|
-
cached.messageHashes = incomingHashes;
|
|
19244
|
-
cached.messageCount = messages.length;
|
|
19245
|
-
return { type: "continuation", session: cached };
|
|
19268
|
+
return { type: "diverged", reason: "modified-history", prefixOverlap };
|
|
19246
19269
|
}
|
|
19247
|
-
|
|
19248
|
-
return { type: "diverged" };
|
|
19270
|
+
return { type: "diverged", reason: "unrelated-history", prefixOverlap };
|
|
19249
19271
|
}
|
|
19250
19272
|
|
|
19251
19273
|
// src/proxy/sessionStore.ts
|
|
@@ -19546,11 +19568,28 @@ function touchSession(state) {
|
|
|
19546
19568
|
state.lastAccess = Date.now();
|
|
19547
19569
|
return state;
|
|
19548
19570
|
}
|
|
19571
|
+
function classifyLineage(state, messages, cacheKey2) {
|
|
19572
|
+
const result = verifyLineage(state, messages);
|
|
19573
|
+
if (result.type === "compaction") {
|
|
19574
|
+
const msg = `Compaction detected (key=${cacheKey2.slice(0, 8)}…): suffix overlap ${result.suffixOverlap}/${state.messageCount}, resume from incoming message ${result.resumeFrom}.`;
|
|
19575
|
+
console.error(`[PROXY] ${msg}`);
|
|
19576
|
+
diagnosticLog2.lineage(msg);
|
|
19577
|
+
} else if (result.type === "undo") {
|
|
19578
|
+
const msg = `Undo detected (key=${cacheKey2.slice(0, 8)}…): prefix overlap ${result.prefixOverlap}/${state.messageCount}, rollback UUID: ${result.rollbackUuid || "none (legacy session)"}.`;
|
|
19579
|
+
console.error(`[PROXY] ${msg}`);
|
|
19580
|
+
diagnosticLog2.lineage(msg);
|
|
19581
|
+
} else if (result.type === "diverged" && result.reason === "modified-history") {
|
|
19582
|
+
const msg = `Stale session detected (key=${cacheKey2.slice(0, 8)}…): prefix overlap ${result.prefixOverlap || 0}/${state.messageCount}, incoming ${messages.length} msgs. Starting fresh replay.`;
|
|
19583
|
+
console.error(`[PROXY] ${msg}`);
|
|
19584
|
+
diagnosticLog2.lineage(msg);
|
|
19585
|
+
}
|
|
19586
|
+
return result;
|
|
19587
|
+
}
|
|
19549
19588
|
function lookupSession(sessionId, messages, workingDirectory) {
|
|
19550
19589
|
if (sessionId) {
|
|
19551
19590
|
const cached = sessionCache.get(sessionId);
|
|
19552
19591
|
if (cached) {
|
|
19553
|
-
const result =
|
|
19592
|
+
const result = classifyLineage(cached, messages, sessionId);
|
|
19554
19593
|
if (result.type === "continuation" || result.type === "compaction")
|
|
19555
19594
|
touchSession(result.session);
|
|
19556
19595
|
return result;
|
|
@@ -19566,19 +19605,19 @@ function lookupSession(sessionId, messages, workingDirectory) {
|
|
|
19566
19605
|
sdkMessageUuids: shared.sdkMessageUuids,
|
|
19567
19606
|
contextUsage: shared.contextUsage
|
|
19568
19607
|
};
|
|
19569
|
-
const result =
|
|
19608
|
+
const result = classifyLineage(state, messages, sessionId);
|
|
19570
19609
|
if (result.type === "continuation" || result.type === "compaction") {
|
|
19571
19610
|
sessionCache.set(sessionId, state);
|
|
19572
19611
|
}
|
|
19573
19612
|
return result;
|
|
19574
19613
|
}
|
|
19575
|
-
return { type: "diverged" };
|
|
19614
|
+
return { type: "diverged", reason: "not-found" };
|
|
19576
19615
|
}
|
|
19577
19616
|
const fp = getConversationFingerprint(messages, workingDirectory);
|
|
19578
19617
|
if (fp) {
|
|
19579
19618
|
const cached = fingerprintCache.get(fp);
|
|
19580
19619
|
if (cached) {
|
|
19581
|
-
const result =
|
|
19620
|
+
const result = classifyLineage(cached, messages, fp);
|
|
19582
19621
|
if (result.type === "continuation" || result.type === "compaction")
|
|
19583
19622
|
touchSession(result.session);
|
|
19584
19623
|
return result;
|
|
@@ -19594,14 +19633,14 @@ function lookupSession(sessionId, messages, workingDirectory) {
|
|
|
19594
19633
|
sdkMessageUuids: shared.sdkMessageUuids,
|
|
19595
19634
|
contextUsage: shared.contextUsage
|
|
19596
19635
|
};
|
|
19597
|
-
const result =
|
|
19636
|
+
const result = classifyLineage(state, messages, fp);
|
|
19598
19637
|
if (result.type === "continuation" || result.type === "compaction") {
|
|
19599
19638
|
fingerprintCache.set(fp, state);
|
|
19600
19639
|
}
|
|
19601
19640
|
return result;
|
|
19602
19641
|
}
|
|
19603
19642
|
}
|
|
19604
|
-
return { type: "diverged" };
|
|
19643
|
+
return { type: "diverged", reason: "not-found" };
|
|
19605
19644
|
}
|
|
19606
19645
|
function getSessionByClaudeId(claudeSessionId) {
|
|
19607
19646
|
let newest;
|
|
@@ -19905,8 +19944,8 @@ function createProxyServer(config = {}) {
|
|
|
19905
19944
|
app.use("/settings", requireAuth);
|
|
19906
19945
|
app.use("/design-login", requireAuth);
|
|
19907
19946
|
const priorityExhaustion = new ProfileExhaustion;
|
|
19908
|
-
const priorityAssignments = new Map;
|
|
19909
19947
|
const PRIORITY_ASSIGNMENTS_MAX = 5000;
|
|
19948
|
+
const priorityAssignments = new AssignmentStore(PRIORITY_ASSIGNMENTS_MAX);
|
|
19910
19949
|
const PRIORITY_DEFAULT_COOLDOWN_MS = 10 * 60000;
|
|
19911
19950
|
const PRIORITY_COOLDOWN_CAP_MS = 6 * 60 * 60000;
|
|
19912
19951
|
function priorityProfileOrderSetting() {
|
|
@@ -19916,11 +19955,33 @@ function createProxyServer(config = {}) {
|
|
|
19916
19955
|
const setting = getSetting("profileOrder");
|
|
19917
19956
|
return Array.isArray(setting) && setting.length > 0 ? setting : undefined;
|
|
19918
19957
|
}
|
|
19919
|
-
function priorityCooldownUntil(now) {
|
|
19920
|
-
const fiveHour = rateLimitStore.getAll().find((e) => e.rateLimitType === "five_hour" && (e.resetsAt ?? 0) > now);
|
|
19958
|
+
function priorityCooldownUntil(profileId, now) {
|
|
19959
|
+
const fiveHour = rateLimitStore.getAll(profileId).find((e) => e.rateLimitType === "five_hour" && (e.resetsAt ?? 0) > now && (e.status === "rejected" || (e.utilization ?? 0) >= 1));
|
|
19921
19960
|
const until = fiveHour?.resetsAt ?? now + PRIORITY_DEFAULT_COOLDOWN_MS;
|
|
19922
19961
|
return Math.min(until, now + PRIORITY_COOLDOWN_CAP_MS);
|
|
19923
19962
|
}
|
|
19963
|
+
function refinePriorityCooldown(profileId) {
|
|
19964
|
+
const target = getEffectiveProfiles(finalConfig.profiles).find((p) => p.id === profileId);
|
|
19965
|
+
fetchOAuthUsage({ profileId, claudeConfigDir: target?.claudeConfigDir, force: true }).then((usage) => {
|
|
19966
|
+
if (!usage || usage.stale)
|
|
19967
|
+
return;
|
|
19968
|
+
const fiveHour = usage.windows.find((w) => w.type === "five_hour");
|
|
19969
|
+
if (!fiveHour || (fiveHour.utilization ?? 0) < 1)
|
|
19970
|
+
return;
|
|
19971
|
+
const now = Date.now();
|
|
19972
|
+
const resetsAt = fiveHour.resetsAt;
|
|
19973
|
+
if (!resetsAt || resetsAt <= now)
|
|
19974
|
+
return;
|
|
19975
|
+
const until = Math.min(resetsAt, now + PRIORITY_COOLDOWN_CAP_MS);
|
|
19976
|
+
priorityExhaustion.mark(profileId, until, "rate_limit_error");
|
|
19977
|
+
claudeLog("priority.cooldown_refined", { profile: profileId, until, source: "oauth_usage" });
|
|
19978
|
+
}).catch((err) => {
|
|
19979
|
+
claudeLog("priority.cooldown_refine_failed", {
|
|
19980
|
+
profile: profileId,
|
|
19981
|
+
error: err instanceof Error ? err.message : String(err)
|
|
19982
|
+
});
|
|
19983
|
+
});
|
|
19984
|
+
}
|
|
19924
19985
|
async function sniffQuotaFailure(res) {
|
|
19925
19986
|
const contentType = res.headers.get("content-type") ?? "";
|
|
19926
19987
|
if (!contentType.includes("text/event-stream")) {
|
|
@@ -19995,22 +20056,18 @@ function createProxyServer(config = {}) {
|
|
|
19995
20056
|
const inner = await app.fetch(new Request(c.req.url, { method: "POST", headers, body: bodyBuf }));
|
|
19996
20057
|
const { failed, errorPayload, response } = await sniffQuotaFailure(inner);
|
|
19997
20058
|
if (!failed) {
|
|
19998
|
-
if (sessionKey)
|
|
20059
|
+
if (sessionKey)
|
|
19999
20060
|
priorityAssignments.set(sessionKey, candidate);
|
|
20000
|
-
if (priorityAssignments.size > PRIORITY_ASSIGNMENTS_MAX) {
|
|
20001
|
-
const oldest = priorityAssignments.keys().next().value;
|
|
20002
|
-
if (oldest !== undefined)
|
|
20003
|
-
priorityAssignments.delete(oldest);
|
|
20004
|
-
}
|
|
20005
|
-
}
|
|
20006
20061
|
if (previous) {
|
|
20007
20062
|
claudeLog("profile.failover", { from: previous, to: candidate, reason: "rate_limit_error", sessionKey });
|
|
20008
20063
|
plog(`[PROXY] PRIORITY failover ${previous} -> ${candidate}`);
|
|
20009
20064
|
}
|
|
20010
20065
|
return response;
|
|
20011
20066
|
}
|
|
20012
|
-
|
|
20013
|
-
|
|
20067
|
+
const cooldownUntil = priorityCooldownUntil(candidate, Date.now());
|
|
20068
|
+
priorityExhaustion.mark(candidate, cooldownUntil, "rate_limit_error");
|
|
20069
|
+
claudeLog("priority.exhausted", { profile: candidate, until: cooldownUntil });
|
|
20070
|
+
refinePriorityCooldown(candidate);
|
|
20014
20071
|
lastError = errorPayload;
|
|
20015
20072
|
previous = candidate;
|
|
20016
20073
|
}
|
|
@@ -20098,7 +20155,8 @@ data: ${JSON.stringify(lastError)}
|
|
|
20098
20155
|
const { order, unknown } = resolvePriorityOrder(effectivePool.map((p) => p.id), priorityProfileOrderSetting());
|
|
20099
20156
|
if (unknown.length > 0)
|
|
20100
20157
|
claudeLog("priority.unknown_order_ids", { unknown });
|
|
20101
|
-
const
|
|
20158
|
+
const assignmentCwd = adapter.extractClientWorkingDirectory?.(body) ?? adapter.extractWorkingDirectory(body);
|
|
20159
|
+
const sessionKey = getPriorityAssignmentKey(adapter.getSessionId(c, body), body.messages, assignmentCwd);
|
|
20102
20160
|
const assigned = sessionKey ? priorityAssignments.get(sessionKey) : undefined;
|
|
20103
20161
|
let first;
|
|
20104
20162
|
if (assigned && order.includes(assigned) && !priorityExhaustion.isExhausted(assigned)) {
|
|
@@ -20224,14 +20282,15 @@ data: ${JSON.stringify(lastError)}
|
|
|
20224
20282
|
claudeLog("session.pending_store_awaited", { waitedMs: Date.now() - waitStart });
|
|
20225
20283
|
}
|
|
20226
20284
|
}
|
|
20227
|
-
let lineageResult = isIndependentSession ? { type: "diverged" } : lookupSession(profileSessionId, body.messages || [], profileScopedCwd);
|
|
20285
|
+
let lineageResult = isIndependentSession ? { type: "diverged", reason: "independent-request" } : lookupSession(profileSessionId, body.messages || [], profileScopedCwd);
|
|
20228
20286
|
if (lineageResult.type === "undo" && adapterBase === "opencode" && !agentSessionId) {
|
|
20229
|
-
lineageResult = { type: "diverged" };
|
|
20287
|
+
lineageResult = { type: "diverged", reason: "missing-session-header" };
|
|
20230
20288
|
}
|
|
20231
20289
|
const isResume = lineageResult.type === "continuation" || lineageResult.type === "compaction";
|
|
20232
20290
|
const isUndo = lineageResult.type === "undo";
|
|
20233
20291
|
const cachedSession = lineageResult.type !== "diverged" ? lineageResult.session : undefined;
|
|
20234
20292
|
const resumeSessionId = cachedSession?.claudeSessionId;
|
|
20293
|
+
const resumeFrom = lineageResult.type === "continuation" || lineageResult.type === "compaction" ? lineageResult.resumeFrom : undefined;
|
|
20235
20294
|
const undoRollbackUuid = isUndo && lineageResult.type === "undo" ? lineageResult.rollbackUuid : undefined;
|
|
20236
20295
|
const msgSummary = body.messages?.map((m) => {
|
|
20237
20296
|
const contentTypes = Array.isArray(m.content) ? m.content.map((b) => b.type).join(",") : "string";
|
|
@@ -20274,9 +20333,8 @@ data: ${JSON.stringify(lastError)}
|
|
|
20274
20333
|
if (isUndo && undoRollbackUuid) {
|
|
20275
20334
|
messagesToConvert = getLastUserMessage(allMessages);
|
|
20276
20335
|
} else if (isResume) {
|
|
20277
|
-
|
|
20278
|
-
|
|
20279
|
-
messagesToConvert = allMessages.slice(knownCount);
|
|
20336
|
+
if (resumeFrom !== undefined && resumeFrom < allMessages.length) {
|
|
20337
|
+
messagesToConvert = allMessages.slice(resumeFrom);
|
|
20280
20338
|
} else {
|
|
20281
20339
|
messagesToConvert = getLastUserMessage(allMessages);
|
|
20282
20340
|
}
|
|
@@ -20569,7 +20627,7 @@ data: ${JSON.stringify(lastError)}
|
|
|
20569
20627
|
advisorModel
|
|
20570
20628
|
}, requestAbort.controller))) {
|
|
20571
20629
|
if (event.type === "rate_limit_event") {
|
|
20572
|
-
rateLimitStore.record(event.rate_limit_info);
|
|
20630
|
+
rateLimitStore.record(profile.id, event.rate_limit_info);
|
|
20573
20631
|
}
|
|
20574
20632
|
if (event.type === "assistant" && !event.error) {
|
|
20575
20633
|
didYieldContent = true;
|
|
@@ -21151,7 +21209,7 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
21151
21209
|
advisorModel
|
|
21152
21210
|
}, requestAbort.controller))) {
|
|
21153
21211
|
if (event.type === "rate_limit_event") {
|
|
21154
|
-
rateLimitStore.record(event.rate_limit_info);
|
|
21212
|
+
rateLimitStore.record(profile.id, event.rate_limit_info);
|
|
21155
21213
|
}
|
|
21156
21214
|
if (event.type === "stream_event") {
|
|
21157
21215
|
didYieldClientEvent = true;
|
|
@@ -22302,7 +22360,6 @@ data: ${JSON.stringify({
|
|
|
22302
22360
|
const previousProfile = getActiveProfileId() ?? null;
|
|
22303
22361
|
setActiveProfile(body.profile);
|
|
22304
22362
|
clearSessionCache();
|
|
22305
|
-
rateLimitStore.clear();
|
|
22306
22363
|
claudeLog("profile.switched", {
|
|
22307
22364
|
from: previousProfile,
|
|
22308
22365
|
to: body.profile,
|
|
@@ -22356,7 +22413,7 @@ data: ${JSON.stringify({
|
|
|
22356
22413
|
const store = credentialStoreForProfile(profile);
|
|
22357
22414
|
const success = store ? await refreshOAuthToken(store) : false;
|
|
22358
22415
|
if (success) {
|
|
22359
|
-
rateLimitStore.clear();
|
|
22416
|
+
rateLimitStore.clear(profile.id);
|
|
22360
22417
|
return c.json({ success: true, message: "OAuth token refreshed successfully", profile: profile.id });
|
|
22361
22418
|
}
|
|
22362
22419
|
return c.json({ success: false, message: "Token refresh failed. If the problem persists, run 'claude login'." }, 500);
|
|
@@ -22579,11 +22636,11 @@ data: ${JSON.stringify({ response: { id: responseId, status: "failed", error: {
|
|
|
22579
22636
|
return c.json({ object: "list", data: buildModelList(isMax) });
|
|
22580
22637
|
});
|
|
22581
22638
|
app.get("/v1/usage/quota", async (c) => {
|
|
22582
|
-
const sdkEntries = rateLimitStore.getAll().filter((entry) => entry.rateLimitType !== undefined);
|
|
22583
22639
|
const requestedProfile = c.req.query("profile");
|
|
22584
22640
|
const profilesList = getEffectiveProfiles(finalConfig.profiles);
|
|
22585
22641
|
const targetProfileId = requestedProfile || getActiveProfileId() || finalConfig.defaultProfile || profilesList[0]?.id || null;
|
|
22586
22642
|
const targetProfile = targetProfileId ? profilesList.find((p) => p.id === targetProfileId) : undefined;
|
|
22643
|
+
const sdkEntries = rateLimitStore.getAll(targetProfileId ?? "default").filter((entry) => entry.rateLimitType !== undefined);
|
|
22587
22644
|
const oauth = await fetchOAuthUsage({
|
|
22588
22645
|
profileId: targetProfileId ?? undefined,
|
|
22589
22646
|
claudeConfigDir: targetProfile?.claudeConfigDir
|
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
startProxyServer
|
|
4
|
-
} from "./cli-
|
|
5
|
-
import"./cli-
|
|
4
|
+
} from "./cli-wszp24mg.js";
|
|
5
|
+
import"./cli-h6hfkg3s.js";
|
|
6
6
|
import"./cli-sry5aqdj.js";
|
|
7
7
|
import"./cli-xmweegb1.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveClaudeExecutableAsync
|
|
10
|
-
} from "./cli-
|
|
11
|
-
import"./cli-
|
|
10
|
+
} from "./cli-kjd4cwcq.js";
|
|
11
|
+
import"./cli-vj9cv18n.js";
|
|
12
12
|
import"./cli-je60fevk.js";
|
|
13
13
|
import"./cli-aq5zz92m.js";
|
|
14
14
|
import {
|
|
@@ -55,7 +55,7 @@ See https://github.com/rynfar/meridian for full documentation.`);
|
|
|
55
55
|
process.exit(0);
|
|
56
56
|
}
|
|
57
57
|
if (args[0] === "profile") {
|
|
58
|
-
const { profileAdd, profileAddOauthToken, profileList, profileRemove, profileSwitch, profileLogin, profileHelp } = await import("./profileCli-
|
|
58
|
+
const { profileAdd, profileAddOauthToken, profileList, profileRemove, profileSwitch, profileLogin, profileHelp } = await import("./profileCli-b1zmg2ad.js");
|
|
59
59
|
const subcommand = args[1];
|
|
60
60
|
const profileId = args[2];
|
|
61
61
|
const headless = args.includes("--headless");
|
|
@@ -171,7 +171,7 @@ async function runCli(start = startProxyServer, runAuthCheck = async () => {
|
|
|
171
171
|
console.error("\x1B[33m⚠ Could not verify Claude auth status. If requests fail, run: claude login\x1B[0m");
|
|
172
172
|
}
|
|
173
173
|
if (!profiles) {
|
|
174
|
-
const { enableDiskProfileDiscovery } = await import("./profiles-
|
|
174
|
+
const { enableDiskProfileDiscovery } = await import("./profiles-3rg4x7cz.js");
|
|
175
175
|
enableDiskProfileDiscovery();
|
|
176
176
|
}
|
|
177
177
|
const proxy = await start({ port, host, idleTimeoutSeconds, pluginDir, pluginConfigPath, profiles, defaultProfile, version, installProcessErrorHandlers: true });
|
|
@@ -24,9 +24,11 @@ interface ResponsesContentPart {
|
|
|
24
24
|
image_url?: string;
|
|
25
25
|
}
|
|
26
26
|
interface ResponsesMessageItem {
|
|
27
|
-
|
|
27
|
+
/** Optional per the spec — `EasyInputMessage` requires only `role`. */
|
|
28
|
+
type?: "message";
|
|
28
29
|
role: "user" | "assistant" | "developer" | "system";
|
|
29
|
-
|
|
30
|
+
/** Also optional per the spec: `EasyInputMessage` requires only `role`. */
|
|
31
|
+
content?: ResponsesContentPart[] | string;
|
|
30
32
|
}
|
|
31
33
|
interface ResponsesFunctionCallItem {
|
|
32
34
|
type: "function_call";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openaiResponses.d.ts","sourceRoot":"","sources":["../../src/proxy/openaiResponses.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EACV,oBAAoB,EAIrB,MAAM,UAAU,CAAA;AAOjB,UAAU,oBAAoB;IAC5B,IAAI,EAAE,YAAY,GAAG,aAAa,GAAG,aAAa,GAAG,MAAM,CAAA;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,UAAU,oBAAoB;IAC5B,IAAI,EAAE,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"openaiResponses.d.ts","sourceRoot":"","sources":["../../src/proxy/openaiResponses.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,13 +27,16 @@
|
|
|
27
27
|
* in memory. State resets on proxy restart — that's fine because the SDK will
|
|
28
28
|
* push a fresh event on the next request.
|
|
29
29
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
30
|
+
* Entries are scoped per profile. Each profile is a separate Claude Max
|
|
31
|
+
* subscription with separate quotas, so a flat store would let one account's
|
|
32
|
+
* reset time be read as another's — which is exactly how priority routing
|
|
33
|
+
* (`routing: "priority"`) mis-derived exhaustion cooldowns before this was
|
|
34
|
+
* scoped. Every read names its profile explicitly; single-profile setups
|
|
35
|
+
* simply use the literal `"default"` key.
|
|
36
|
+
*
|
|
37
|
+
* `clear(profileId)` drops one account (wired into `POST /auth/refresh`,
|
|
38
|
+
* which re-authenticates one credential); `clear()` drops everything and is
|
|
39
|
+
* used by tests.
|
|
37
40
|
*/
|
|
38
41
|
import type { SDKRateLimitInfo } from "@anthropic-ai/claude-agent-sdk";
|
|
39
42
|
export interface RateLimitEntry extends SDKRateLimitInfo {
|
|
@@ -43,29 +46,30 @@ export interface RateLimitEntry extends SDKRateLimitInfo {
|
|
|
43
46
|
/** Type discriminator for the entry's bucket key. */
|
|
44
47
|
export type RateLimitBucketKey = NonNullable<SDKRateLimitInfo["rateLimitType"]> | "default";
|
|
45
48
|
declare class RateLimitStore {
|
|
46
|
-
|
|
49
|
+
/** profileId -> (bucket key -> entry). One inner map per configured profile. */
|
|
50
|
+
private byProfile;
|
|
47
51
|
/**
|
|
48
|
-
* Record a rate-limit info snapshot.
|
|
49
|
-
* Last-write-wins per
|
|
50
|
-
* same
|
|
52
|
+
* Record a rate-limit info snapshot for a specific profile.
|
|
53
|
+
* Last-write-wins per (profileId, rateLimitType). Older entries for the
|
|
54
|
+
* same pair are overwritten — clients should treat the latest as canonical.
|
|
51
55
|
*
|
|
52
56
|
* `observedAt` defaults to the current wall clock but may be supplied
|
|
53
57
|
* explicitly so callers (and tests) can control the capture timestamp used
|
|
54
58
|
* for newest-first ordering in {@link getAll}.
|
|
55
59
|
*/
|
|
56
|
-
record(info: SDKRateLimitInfo | undefined | null, observedAt?: number): void;
|
|
57
|
-
/** Snapshot
|
|
58
|
-
getAll(): RateLimitEntry[];
|
|
59
|
-
/** Snapshot a single bucket, or undefined if not yet seen. */
|
|
60
|
-
get(key: RateLimitBucketKey): RateLimitEntry | undefined;
|
|
61
|
-
/**
|
|
62
|
-
|
|
60
|
+
record(profileId: string, info: SDKRateLimitInfo | undefined | null, observedAt?: number): void;
|
|
61
|
+
/** Snapshot one profile's entries, newest-first by observedAt. */
|
|
62
|
+
getAll(profileId: string): RateLimitEntry[];
|
|
63
|
+
/** Snapshot a single bucket for one profile, or undefined if not yet seen. */
|
|
64
|
+
get(profileId: string, key: RateLimitBucketKey): RateLimitEntry | undefined;
|
|
65
|
+
/** Bucket count for one profile, or across all profiles when omitted. */
|
|
66
|
+
size(profileId?: string): number;
|
|
63
67
|
/**
|
|
64
|
-
* Drop
|
|
65
|
-
* `POST /auth/refresh`
|
|
66
|
-
* stale
|
|
68
|
+
* Drop stored entries for one profile, or every profile when `profileId`
|
|
69
|
+
* is omitted. Wired into the `POST /auth/refresh` handler so a refreshed
|
|
70
|
+
* credential's stale quotas can't linger. Also used by tests for isolation.
|
|
67
71
|
*/
|
|
68
|
-
clear(): void;
|
|
72
|
+
clear(profileId?: string): void;
|
|
69
73
|
}
|
|
70
74
|
/**
|
|
71
75
|
* Process-wide singleton. Importers should always use this instance — do
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rateLimitStore.d.ts","sourceRoot":"","sources":["../../src/proxy/rateLimitStore.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rateLimitStore.d.ts","sourceRoot":"","sources":["../../src/proxy/rateLimitStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAEtE,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACtD,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,qDAAqD;AACrD,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC,GAAG,SAAS,CAAA;AAE3F,cAAM,cAAc;IAClB,gFAAgF;IAChF,OAAO,CAAC,SAAS,CAA6D;IAE9E;;;;;;;;OAQG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,IAAI,EAAE,UAAU,GAAE,MAAmB,GAAG,IAAI;IAW3G,kEAAkE;IAClE,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,EAAE;IAM3C,8EAA8E;IAC9E,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,GAAG,cAAc,GAAG,SAAS;IAI3E,yEAAyE;IACzE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAOhC;;;;OAIG;IACH,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;CAIhC;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,gBAAuB,CAAA;AAElD,wCAAwC;AACxC,OAAO,EAAE,cAAc,IAAI,uBAAuB,EAAE,CAAA"}
|
package/dist/proxy/routing.d.ts
CHANGED
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
* Default mode is "active" (the pre-#383 chain) — existing setups are
|
|
18
18
|
* byte-identical unless routing is explicitly enabled.
|
|
19
19
|
*
|
|
20
|
-
* This is a leaf module —
|
|
20
|
+
* This is a leaf module — no I/O. Most functions here are pure; the
|
|
21
|
+
* exhaustion/assignment trackers below hold mutable in-memory state (by
|
|
22
|
+
* design — see their own doc comments) but still perform no I/O.
|
|
21
23
|
*/
|
|
22
24
|
export type RoutingMode = "active" | "sticky" | "priority";
|
|
23
25
|
/**
|
|
@@ -82,4 +84,25 @@ export declare class ProfileExhaustion {
|
|
|
82
84
|
/** Live entries only — expired marks are dropped on read. */
|
|
83
85
|
snapshot(): ExhaustionEntry[];
|
|
84
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Session-to-profile assignments with LRU eviction.
|
|
89
|
+
*
|
|
90
|
+
* A JS Map preserves insertion order and a bare `set()` on an EXISTING key
|
|
91
|
+
* does not reorder it — so a plain map evicts first-inserted, which drops a
|
|
92
|
+
* long-lived active conversation ahead of a newer idle one. Both read and
|
|
93
|
+
* write therefore delete-then-set to refresh recency.
|
|
94
|
+
*
|
|
95
|
+
* Deliberately not persisted: this is routing hygiene, not durable truth.
|
|
96
|
+
* After a restart the next request re-establishes the assignment.
|
|
97
|
+
*/
|
|
98
|
+
export declare class AssignmentStore {
|
|
99
|
+
private readonly max;
|
|
100
|
+
private readonly entries;
|
|
101
|
+
constructor(max: number);
|
|
102
|
+
/** Read an assignment, marking it most-recently-used. */
|
|
103
|
+
get(key: string): string | undefined;
|
|
104
|
+
/** Write an assignment, marking it most-recently-used and evicting if over capacity. */
|
|
105
|
+
set(key: string, value: string): void;
|
|
106
|
+
get size(): number;
|
|
107
|
+
}
|
|
85
108
|
//# sourceMappingURL=routing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/proxy/routing.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/proxy/routing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAA;AAE1D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAKnE;AAaD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAYvG;AAED;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,CAAC,CAM/F,CAAA;AAOD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAC1C;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAUxC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,GACnC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAMnD;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAEhB,OAAO,CAAC,QAAQ,CAAC,GAAG;IADhC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuD;gBAChD,GAAG,GAAE,MAAM,MAAiB;IAEzD,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAMrD,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAUhC,6DAA6D;IAC7D,QAAQ,IAAI,eAAe,EAAE;CAQ9B;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAGd,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;gBAEvB,GAAG,EAAE,MAAM;IAExC,yDAAyD;IACzD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAQpC,wFAAwF;IACxF,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IASrC,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AAGvD,YAAY,EACV,SAAS,EACT,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAA;AAKpB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAkDnG,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EAEpB,KAAK,aAAa,EAGnB,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AAGvD,YAAY,EACV,SAAS,EACT,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAA;AAKpB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAkDnG,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EAEpB,KAAK,aAAa,EAGnB,MAAM,mBAAmB,CAAA;AAI1B,OAAO,EAA+B,iBAAiB,EAAE,mBAAmB,EAAsC,MAAM,iBAAiB,CAAA;AAGzI,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,CAAA;AAgR7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CA0+HhF;AAWD,wBAAgB,gCAAgC,IAAI,IAAI,CAavD;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAmGhG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/proxy/session/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/proxy/session/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,aAAa,EACnB,MAAM,WAAW,CAAA;AAMlB,wBAAgB,mBAAmB,IAAI,MAAM,CAW5C;AAqCD;kGACkG;AAClG,wBAAgB,iBAAiB,SAYhC;AAED;iFACiF;AACjF,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,gBAAgB,CAAC,EAAE,MAAM,EACzB,QAAQ,CAAC,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAC/C,IAAI,CAoBN;AAkCD;;uDAEuD;AACvD,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,EAC/C,gBAAgB,CAAC,EAAE,MAAM,GACxB,aAAa,CAuDf;AAED;;uFAEuF;AACvF,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CA2BtF;AAED;;;yFAGyF;AACzF,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,EACnD,eAAe,EAAE,MAAM,EACvB,gBAAgB,CAAC,EAAE,MAAM,EACzB,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,EACtC,YAAY,CAAC,EAAE,UAAU,QAoC1B"}
|
|
@@ -28,4 +28,30 @@ export declare function getConversationFingerprint(messages: Array<{
|
|
|
28
28
|
role: string;
|
|
29
29
|
content: any;
|
|
30
30
|
}>, workingDirectory?: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Key a conversation for priority-pool assignment.
|
|
33
|
+
*
|
|
34
|
+
* An explicit session id always wins — keyed clients behave exactly as before.
|
|
35
|
+
* Without one, the conversation fingerprint stands in, which is what gives
|
|
36
|
+
* keyless clients pool affinity: Pylon's main process deliberately sends no
|
|
37
|
+
* session key (its provider headers are per-process, so one key would merge
|
|
38
|
+
* every open chat into a single meridian session), and without a fallback
|
|
39
|
+
* such a conversation re-picks its account every turn — bouncing back to the
|
|
40
|
+
* preferred profile the moment its cooldown expires and replaying its whole
|
|
41
|
+
* history against a cold cache.
|
|
42
|
+
*
|
|
43
|
+
* The `fp:` prefix namespaces fingerprint-derived keys so they can never
|
|
44
|
+
* collide with a real session id. An empty fingerprint returns null rather
|
|
45
|
+
* than inventing a key, preserving today's no-affinity behavior for requests
|
|
46
|
+
* we cannot identify.
|
|
47
|
+
*
|
|
48
|
+
* NOTE: this is only ever an ACCOUNT key, never a session key. Two unrelated
|
|
49
|
+
* conversations that share a first message and working directory will share
|
|
50
|
+
* an assignment — that costs nothing, because it selects a profile and never
|
|
51
|
+
* a resumable SDK session.
|
|
52
|
+
*/
|
|
53
|
+
export declare function getPriorityAssignmentKey(sessionId: string | undefined, messages: Array<{
|
|
54
|
+
role: string;
|
|
55
|
+
content: any;
|
|
56
|
+
}>, workingDirectory?: string): string | null;
|
|
31
57
|
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../../src/proxy/session/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,GAAG,SAAS,CAc9D;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAW7H"}
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../../src/proxy/session/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,GAAG,SAAS,CAc9D;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAW7H;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,EAC/C,gBAAgB,CAAC,EAAE,MAAM,GACxB,MAAM,GAAG,IAAI,CAIf"}
|
|
@@ -49,9 +49,12 @@ export interface SessionState {
|
|
|
49
49
|
export type LineageResult = {
|
|
50
50
|
type: "continuation";
|
|
51
51
|
session: SessionState;
|
|
52
|
+
resumeFrom: number;
|
|
52
53
|
} | {
|
|
53
54
|
type: "compaction";
|
|
54
55
|
session: SessionState;
|
|
56
|
+
resumeFrom: number;
|
|
57
|
+
suffixOverlap: number;
|
|
55
58
|
} | {
|
|
56
59
|
type: "undo";
|
|
57
60
|
session: SessionState;
|
|
@@ -59,7 +62,10 @@ export type LineageResult = {
|
|
|
59
62
|
rollbackUuid: string | undefined;
|
|
60
63
|
} | {
|
|
61
64
|
type: "diverged";
|
|
65
|
+
reason: LineageDivergenceReason;
|
|
66
|
+
prefixOverlap?: number;
|
|
62
67
|
};
|
|
68
|
+
export type LineageDivergenceReason = "unverifiable" | "replayed-request" | "modified-history" | "unrelated-history" | "not-found" | "independent-request" | "missing-session-header";
|
|
63
69
|
/**
|
|
64
70
|
* Compute a lineage hash of an ordered message array.
|
|
65
71
|
* Used as a fast-path check: if the aggregate hash matches, the messages
|
|
@@ -117,22 +123,22 @@ export declare function measurePrefixOverlap(storedHashes: string[], incomingHas
|
|
|
117
123
|
* contiguity.
|
|
118
124
|
*/
|
|
119
125
|
export declare function measureSuffixOverlap(storedHashes: string[], incomingHashes: string[]): number;
|
|
120
|
-
/** Cache-like interface for verifyLineage — only needs get/set/delete */
|
|
121
|
-
export interface SessionCacheLike {
|
|
122
|
-
delete(key: string): boolean;
|
|
123
|
-
}
|
|
124
126
|
/**
|
|
125
127
|
* Verify that incoming messages are a valid continuation of a cached session.
|
|
126
128
|
* Uses per-message hash comparison to deterministically classify mutations.
|
|
129
|
+
* This function is deliberately side-effect free: it never mutates the cached
|
|
130
|
+
* state. The caller commits new hashes/counts only after the upstream request
|
|
131
|
+
* succeeds.
|
|
127
132
|
*
|
|
128
133
|
* Decision matrix:
|
|
129
|
-
* Full prefix match (fast-path) → continuation (resume
|
|
130
|
-
* Suffix overlap >= MIN_SUFFIX → compaction (resume
|
|
131
|
-
* Prefix overlap > 0, no suffix
|
|
132
|
-
*
|
|
134
|
+
* Full prefix match (fast-path) → continuation (resume from stored count)
|
|
135
|
+
* Suffix overlap >= MIN_SUFFIX → compaction (resume after matched suffix)
|
|
136
|
+
* Prefix overlap > 0, no suffix, shrank → undo (fork at rollback point)
|
|
137
|
+
* Cached prefix changed while growing → diverged (fresh full-history replay)
|
|
138
|
+
* No overlap → diverged (fresh full-history replay)
|
|
133
139
|
*/
|
|
134
140
|
export declare function verifyLineage(cached: SessionState, messages: Array<{
|
|
135
141
|
role: string;
|
|
136
142
|
content: any;
|
|
137
|
-
}
|
|
143
|
+
}>): LineageResult;
|
|
138
144
|
//# sourceMappingURL=lineage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lineage.d.ts","sourceRoot":"","sources":["../../../src/proxy/session/lineage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"lineage.d.ts","sourceRoot":"","sources":["../../../src/proxy/session/lineage.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/proxy/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/proxy/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyBH,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;8EAC0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;gFAC4E;IAC5E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACxB;AAED,yFAAyF;AACzF,wBAAgB,YAAY,IAAI,gBAAgB,CAQ/C;AAED,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAUrE;AAED,iCAAiC;AACjC,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,GAAG,EAAE,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAExF;AAED,6CAA6C;AAC7C,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAErG"}
|
package/dist/server.js
CHANGED
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
runObserveHook,
|
|
12
12
|
runTransformHook,
|
|
13
13
|
startProxyServer
|
|
14
|
-
} from "./cli-
|
|
15
|
-
import"./cli-
|
|
14
|
+
} from "./cli-wszp24mg.js";
|
|
15
|
+
import"./cli-h6hfkg3s.js";
|
|
16
16
|
import"./cli-sry5aqdj.js";
|
|
17
17
|
import"./cli-xmweegb1.js";
|
|
18
|
-
import"./cli-
|
|
19
|
-
import"./cli-
|
|
18
|
+
import"./cli-kjd4cwcq.js";
|
|
19
|
+
import"./cli-vj9cv18n.js";
|
|
20
20
|
import"./cli-je60fevk.js";
|
|
21
21
|
import"./cli-aq5zz92m.js";
|
|
22
22
|
import"./cli-p9swy5t3.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynfar/meridian",
|
|
3
|
-
"version": "1.57.
|
|
3
|
+
"version": "1.57.1",
|
|
4
4
|
"description": "Local Anthropic API powered by your Claude Max subscription. One subscription, every agent.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/server.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"proxy": "./bin/claude-proxy-supervisor.sh",
|
|
24
24
|
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && bun build bin/cli.ts src/proxy/server.ts --outdir dist --target node --splitting --external @anthropic-ai/claude-agent-sdk --external jsonc-parser --entry-naming \"[name].js\" && tsc -p tsconfig.build.json",
|
|
25
25
|
"postbuild": "node scripts/fix-bun-exports.mjs && node --check dist/cli.js && node --check dist/server.js && node -e \"if(!require('fs').existsSync('dist/proxy/server.d.ts'))process.exit(1)\"",
|
|
26
|
-
"postinstall": "node
|
|
26
|
+
"postinstall": "node -e \"try{require('child_process').spawnSync(process.execPath,[require.resolve('@anthropic-ai/claude-code/install.cjs')],{stdio:'inherit'})}catch(e){console.error('[meridian] claude-code postinstall skipped:',e.message)}\"",
|
|
27
27
|
"prepublishOnly": "bun run build",
|
|
28
28
|
"test": "bun test --path-ignore-patterns '**/*session-store*' --path-ignore-patterns '**/*proxy-async-ops*' --path-ignore-patterns '**/*models-auth-status*' --path-ignore-patterns '**/*proxy-context-usage-store*' --path-ignore-patterns '**/*proxy-passthrough-thinking*' --path-ignore-patterns '**/*proxy-thinking-setting*' --path-ignore-patterns '**/*session-recovery*' --path-ignore-patterns '**/*models.test*' && bun test src/__tests__/proxy-async-ops.test.ts && bun test src/__tests__/proxy-session-store.test.ts && bun test src/__tests__/session-store-pruning.test.ts && bun test src/__tests__/proxy-session-store-locking.test.ts && bun test src/__tests__/proxy-context-usage-store.test.ts && bun test src/__tests__/models-auth-status.test.ts && bun test src/__tests__/proxy-passthrough-thinking.test.ts && bun test src/__tests__/proxy-session-recovery.test.ts && bun test src/__tests__/proxy-thinking-setting.test.ts && bun test src/__tests__/models.test.ts",
|
|
29
29
|
"nix:lock": "bun2nix -o bun.nix",
|