@rynfar/meridian 1.28.1 → 1.29.0
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-zcxn6xmn.js → cli-msyx6dnk.js} +120 -12
- package/dist/cli.js +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/session/lineage.d.ts +22 -5
- package/dist/proxy/session/lineage.d.ts.map +1 -1
- package/dist/proxy/sessionStore.d.ts +24 -0
- package/dist/proxy/sessionStore.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
|
@@ -13851,26 +13851,59 @@ function computeMessageHashes(messages) {
|
|
|
13851
13851
|
return [];
|
|
13852
13852
|
return messages.map(hashMessage);
|
|
13853
13853
|
}
|
|
13854
|
-
function measurePrefixOverlap(storedHashes,
|
|
13854
|
+
function measurePrefixOverlap(storedHashes, incomingHashes) {
|
|
13855
13855
|
let overlap = 0;
|
|
13856
|
-
|
|
13857
|
-
|
|
13856
|
+
const minLen = Math.min(storedHashes.length, incomingHashes.length);
|
|
13857
|
+
for (let i = 0;i < minLen; i++) {
|
|
13858
|
+
if (storedHashes[i] === incomingHashes[i])
|
|
13858
13859
|
overlap++;
|
|
13859
13860
|
else
|
|
13860
13861
|
break;
|
|
13861
13862
|
}
|
|
13862
13863
|
return overlap;
|
|
13863
13864
|
}
|
|
13864
|
-
function measureSuffixOverlap(storedHashes,
|
|
13865
|
+
function measureSuffixOverlap(storedHashes, incomingHashes) {
|
|
13866
|
+
if (storedHashes.length === 0 || incomingHashes.length === 0)
|
|
13867
|
+
return 0;
|
|
13868
|
+
const lastStoredHash = storedHashes[storedHashes.length - 1];
|
|
13869
|
+
let anchorInIncoming = -1;
|
|
13870
|
+
for (let i = incomingHashes.length - 1;i >= 0; i--) {
|
|
13871
|
+
if (incomingHashes[i] === lastStoredHash) {
|
|
13872
|
+
anchorInIncoming = i;
|
|
13873
|
+
break;
|
|
13874
|
+
}
|
|
13875
|
+
}
|
|
13876
|
+
if (anchorInIncoming < 0)
|
|
13877
|
+
return 0;
|
|
13865
13878
|
let overlap = 0;
|
|
13866
|
-
|
|
13867
|
-
|
|
13879
|
+
let si = storedHashes.length - 1;
|
|
13880
|
+
let ii = anchorInIncoming;
|
|
13881
|
+
while (si >= 0 && ii >= 0) {
|
|
13882
|
+
if (storedHashes[si] === incomingHashes[ii]) {
|
|
13868
13883
|
overlap++;
|
|
13869
|
-
|
|
13884
|
+
si--;
|
|
13885
|
+
ii--;
|
|
13886
|
+
} else {
|
|
13870
13887
|
break;
|
|
13888
|
+
}
|
|
13871
13889
|
}
|
|
13872
13890
|
return overlap;
|
|
13873
13891
|
}
|
|
13892
|
+
function findSuffixAnchorStart(storedHashes, incomingHashes, suffixOverlap) {
|
|
13893
|
+
if (suffixOverlap <= 0)
|
|
13894
|
+
return -1;
|
|
13895
|
+
const lastStoredHash = storedHashes[storedHashes.length - 1];
|
|
13896
|
+
let anchor = -1;
|
|
13897
|
+
for (let i = incomingHashes.length - 1;i >= 0; i--) {
|
|
13898
|
+
if (incomingHashes[i] === lastStoredHash) {
|
|
13899
|
+
anchor = i;
|
|
13900
|
+
break;
|
|
13901
|
+
}
|
|
13902
|
+
}
|
|
13903
|
+
if (anchor < 0)
|
|
13904
|
+
return -1;
|
|
13905
|
+
return anchor - suffixOverlap + 1;
|
|
13906
|
+
}
|
|
13874
13907
|
function verifyLineage(cached, messages, cacheKey2, cache) {
|
|
13875
13908
|
if (!cached.lineageHash || cached.messageCount === 0) {
|
|
13876
13909
|
return { type: "continuation", session: cached };
|
|
@@ -13889,11 +13922,11 @@ function verifyLineage(cached, messages, cacheKey2, cache) {
|
|
|
13889
13922
|
return { type: "diverged" };
|
|
13890
13923
|
}
|
|
13891
13924
|
const incomingHashes = computeMessageHashes(messages);
|
|
13892
|
-
const
|
|
13893
|
-
const
|
|
13894
|
-
const suffixOverlap = measureSuffixOverlap(cached.messageHashes, incomingSet);
|
|
13925
|
+
const prefixOverlap = measurePrefixOverlap(cached.messageHashes, incomingHashes);
|
|
13926
|
+
const suffixOverlap = measureSuffixOverlap(cached.messageHashes, incomingHashes);
|
|
13895
13927
|
const MIN_STORED_FOR_COMPACTION = 6;
|
|
13896
|
-
|
|
13928
|
+
const suffixStartInIncoming = incomingHashes.length - suffixOverlap >= 0 ? findSuffixAnchorStart(cached.messageHashes, incomingHashes, suffixOverlap) : -1;
|
|
13929
|
+
if (suffixOverlap >= MIN_SUFFIX_FOR_COMPACTION && cached.messageHashes.length >= MIN_STORED_FOR_COMPACTION && suffixStartInIncoming > 0) {
|
|
13897
13930
|
const compactionMsg = `Compaction detected (key=${cacheKey2.slice(0, 8)}…): suffix overlap ${suffixOverlap}/${cached.messageHashes.length}. Allowing resume.`;
|
|
13898
13931
|
console.error(`[PROXY] ${compactionMsg}`);
|
|
13899
13932
|
diagnosticLog.lineage(compactionMsg);
|
|
@@ -14130,6 +14163,7 @@ function storeSharedSession(key, claudeSessionId, messageCount, lineageHash, mes
|
|
|
14130
14163
|
try {
|
|
14131
14164
|
const store = readStore();
|
|
14132
14165
|
const existing = store[key];
|
|
14166
|
+
const previousClaudeSessionId = existing && existing.claudeSessionId !== claudeSessionId ? existing.claudeSessionId : existing?.previousClaudeSessionId;
|
|
14133
14167
|
store[key] = {
|
|
14134
14168
|
claudeSessionId,
|
|
14135
14169
|
createdAt: existing?.createdAt || Date.now(),
|
|
@@ -14138,7 +14172,8 @@ function storeSharedSession(key, claudeSessionId, messageCount, lineageHash, mes
|
|
|
14138
14172
|
lineageHash: lineageHash ?? existing?.lineageHash,
|
|
14139
14173
|
messageHashes: messageHashes ?? existing?.messageHashes,
|
|
14140
14174
|
sdkMessageUuids: sdkMessageUuids ?? existing?.sdkMessageUuids,
|
|
14141
|
-
contextUsage: contextUsage ?? existing?.contextUsage
|
|
14175
|
+
contextUsage: contextUsage ?? existing?.contextUsage,
|
|
14176
|
+
...previousClaudeSessionId ? { previousClaudeSessionId } : {}
|
|
14142
14177
|
};
|
|
14143
14178
|
const maxEntries = getMaxStoredSessions();
|
|
14144
14179
|
const keys = Object.keys(store);
|
|
@@ -14175,6 +14210,30 @@ function evictSharedSession(key) {
|
|
|
14175
14210
|
}
|
|
14176
14211
|
}
|
|
14177
14212
|
}
|
|
14213
|
+
function lookupSessionRecovery(key) {
|
|
14214
|
+
const store = readStore();
|
|
14215
|
+
const session = store[key];
|
|
14216
|
+
if (!session)
|
|
14217
|
+
return;
|
|
14218
|
+
return {
|
|
14219
|
+
claudeSessionId: session.claudeSessionId,
|
|
14220
|
+
previousClaudeSessionId: session.previousClaudeSessionId,
|
|
14221
|
+
createdAt: session.createdAt,
|
|
14222
|
+
lastUsedAt: session.lastUsedAt,
|
|
14223
|
+
messageCount: session.messageCount
|
|
14224
|
+
};
|
|
14225
|
+
}
|
|
14226
|
+
function listStoredSessions() {
|
|
14227
|
+
const store = readStore();
|
|
14228
|
+
return Object.entries(store).map(([key, session]) => ({
|
|
14229
|
+
key,
|
|
14230
|
+
claudeSessionId: session.claudeSessionId,
|
|
14231
|
+
previousClaudeSessionId: session.previousClaudeSessionId,
|
|
14232
|
+
createdAt: session.createdAt,
|
|
14233
|
+
lastUsedAt: session.lastUsedAt,
|
|
14234
|
+
messageCount: session.messageCount
|
|
14235
|
+
}));
|
|
14236
|
+
}
|
|
14178
14237
|
function clearSharedSessions() {
|
|
14179
14238
|
const path3 = getStorePath();
|
|
14180
14239
|
try {
|
|
@@ -14588,6 +14647,15 @@ function createProxyServer(config = {}) {
|
|
|
14588
14647
|
const requestLogLine = `${requestMeta.requestId} adapter=${adapter.name} model=${model} stream=${stream2} tools=${body.tools?.length ?? 0} lineage=${lineageType} session=${resumeSessionId?.slice(0, 8) || "new"}${isUndo && undoRollbackUuid ? ` rollback=${undoRollbackUuid.slice(0, 8)}` : ""}${agentMode ? ` agent=${agentMode}` : ""} active=${activeSessions}/${MAX_CONCURRENT_SESSIONS} msgCount=${msgCount}`;
|
|
14589
14648
|
console.error(`[PROXY] ${requestLogLine} msgs=${msgSummary}`);
|
|
14590
14649
|
diagnosticLog.session(`${requestLogLine}`, requestMeta.requestId);
|
|
14650
|
+
if (lineageResult.type === "diverged" && profileSessionId) {
|
|
14651
|
+
const recovery = lookupSessionRecovery(profileSessionId);
|
|
14652
|
+
if (recovery) {
|
|
14653
|
+
const prevId = recovery.previousClaudeSessionId || recovery.claudeSessionId;
|
|
14654
|
+
const recoveryMsg = `${requestMeta.requestId} SESSION RECOVERY: previous conversation available. Run: claude --resume ${prevId}`;
|
|
14655
|
+
console.error(`[PROXY] ${recoveryMsg}`);
|
|
14656
|
+
diagnosticLog.session(recoveryMsg, requestMeta.requestId);
|
|
14657
|
+
}
|
|
14658
|
+
}
|
|
14591
14659
|
claudeLog("request.received", {
|
|
14592
14660
|
model,
|
|
14593
14661
|
stream: stream2,
|
|
@@ -15797,6 +15865,46 @@ data: ${JSON.stringify({
|
|
|
15797
15865
|
}
|
|
15798
15866
|
return c.json({ session_id: claudeSessionId, context_usage: session.contextUsage });
|
|
15799
15867
|
});
|
|
15868
|
+
app.get("/v1/sessions/recover", (c) => {
|
|
15869
|
+
const sessions = listStoredSessions();
|
|
15870
|
+
if (sessions.length === 0) {
|
|
15871
|
+
return c.json({ error: "No sessions found in store" }, 404);
|
|
15872
|
+
}
|
|
15873
|
+
return c.json({
|
|
15874
|
+
sessions: sessions.map((s) => ({
|
|
15875
|
+
key: s.key,
|
|
15876
|
+
claudeSessionId: s.claudeSessionId,
|
|
15877
|
+
previousClaudeSessionId: s.previousClaudeSessionId,
|
|
15878
|
+
createdAt: new Date(s.createdAt).toISOString(),
|
|
15879
|
+
lastUsedAt: new Date(s.lastUsedAt).toISOString(),
|
|
15880
|
+
messageCount: s.messageCount,
|
|
15881
|
+
recoverCommand: `claude --resume ${s.claudeSessionId}`,
|
|
15882
|
+
...s.previousClaudeSessionId ? {
|
|
15883
|
+
recoverPreviousCommand: `claude --resume ${s.previousClaudeSessionId}`
|
|
15884
|
+
} : {}
|
|
15885
|
+
}))
|
|
15886
|
+
});
|
|
15887
|
+
});
|
|
15888
|
+
app.get("/v1/sessions/:key/recover", (c) => {
|
|
15889
|
+
const key = c.req.param("key");
|
|
15890
|
+
const recovery = lookupSessionRecovery(key);
|
|
15891
|
+
if (!recovery) {
|
|
15892
|
+
return c.json({ error: "Session not found", key }, 404);
|
|
15893
|
+
}
|
|
15894
|
+
return c.json({
|
|
15895
|
+
key,
|
|
15896
|
+
claudeSessionId: recovery.claudeSessionId,
|
|
15897
|
+
previousClaudeSessionId: recovery.previousClaudeSessionId,
|
|
15898
|
+
createdAt: new Date(recovery.createdAt).toISOString(),
|
|
15899
|
+
lastUsedAt: new Date(recovery.lastUsedAt).toISOString(),
|
|
15900
|
+
messageCount: recovery.messageCount,
|
|
15901
|
+
recoverCommand: `claude --resume ${recovery.claudeSessionId}`,
|
|
15902
|
+
...recovery.previousClaudeSessionId ? {
|
|
15903
|
+
recoverPreviousCommand: `claude --resume ${recovery.previousClaudeSessionId}`,
|
|
15904
|
+
note: "Previous session was replaced — if your current session has lost context, try the previous session ID."
|
|
15905
|
+
} : {}
|
|
15906
|
+
});
|
|
15907
|
+
});
|
|
15800
15908
|
app.all("*", (c) => {
|
|
15801
15909
|
console.error(`[PROXY] UNHANDLED ${c.req.method} ${c.req.url}`);
|
|
15802
15910
|
return c.json({ error: { type: "not_found", message: `Endpoint not supported: ${c.req.method} ${new URL(c.req.url).pathname}` } }, 404);
|
package/dist/cli.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AAqBvD,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EACpB,KAAK,aAAa,EAEnB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAA+B,iBAAiB,EAAE,mBAAmB,EAAsC,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AAqBvD,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EACpB,KAAK,aAAa,EAEnB,MAAM,mBAAmB,CAAA;AAG1B,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;AAoG7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CA0pDhF;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAiEhG"}
|
|
@@ -77,20 +77,37 @@ export declare function computeMessageHashes(messages: Array<{
|
|
|
77
77
|
}>): string[];
|
|
78
78
|
/**
|
|
79
79
|
* Measure how many stored hashes match from the START of the stored array
|
|
80
|
-
* against the incoming hashes (
|
|
80
|
+
* against the incoming hashes (positional comparison).
|
|
81
81
|
*
|
|
82
82
|
* Prefix overlap means the beginning of the conversation is intact (undo
|
|
83
83
|
* changes the end but preserves the beginning).
|
|
84
|
+
*
|
|
85
|
+
* NOTE: Compares stored[i] === incoming[i] positionally. An earlier
|
|
86
|
+
* implementation used a Set for O(1) lookups, but that allowed a stored
|
|
87
|
+
* hash at position i to match an incoming hash at a completely different
|
|
88
|
+
* position, inflating the overlap count when duplicate messages exist
|
|
89
|
+
* in the conversation history.
|
|
84
90
|
*/
|
|
85
|
-
export declare function measurePrefixOverlap(storedHashes: string[],
|
|
91
|
+
export declare function measurePrefixOverlap(storedHashes: string[], incomingHashes: string[]): number;
|
|
86
92
|
/**
|
|
87
|
-
* Measure how many
|
|
88
|
-
*
|
|
93
|
+
* Measure how many consecutive messages at the END of the stored array
|
|
94
|
+
* appear as a contiguous run in the incoming array.
|
|
89
95
|
*
|
|
90
96
|
* Suffix overlap means the recent conversation is intact (compaction
|
|
91
97
|
* changes the beginning but preserves the end).
|
|
98
|
+
*
|
|
99
|
+
* Algorithm: find the last stored hash in the incoming array, then walk
|
|
100
|
+
* backward through both arrays verifying contiguous matches. This handles
|
|
101
|
+
* the real-world compaction pattern where new messages are appended AFTER
|
|
102
|
+
* the preserved suffix.
|
|
103
|
+
*
|
|
104
|
+
* NOTE: An earlier implementation used a Set for O(1) lookups, but that
|
|
105
|
+
* allowed a stored suffix hash to match an incoming hash at a completely
|
|
106
|
+
* different position — producing false compaction when duplicate messages
|
|
107
|
+
* exist in the conversation. The current approach verifies positional
|
|
108
|
+
* contiguity.
|
|
92
109
|
*/
|
|
93
|
-
export declare function measureSuffixOverlap(storedHashes: string[],
|
|
110
|
+
export declare function measureSuffixOverlap(storedHashes: string[], incomingHashes: string[]): number;
|
|
94
111
|
/** Cache-like interface for verifyLineage — only needs get/set/delete */
|
|
95
112
|
export interface SessionCacheLike {
|
|
96
113
|
delete(key: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lineage.d.ts","sourceRoot":"","sources":["../../../src/proxy/session/lineage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,4EAA4E;AAC5E,MAAM,WAAW,UAAU;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,2BAA2B,CAAC,EAAE,MAAM,CAAA;CACrC;AAED;0EAC0E;AAC1E,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAE1C,MAAM,WAAW,YAAY;IAC3B,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB;;qDAEiD;IACjD,WAAW,EAAE,MAAM,CAAA;IACnB;;kCAE8B;IAC9B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;oDAEgD;IAChD,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACtC,iGAAiG;IACjG,YAAY,CAAC,EAAE,UAAU,CAAA;CAC1B;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,YAAY,CAAC;IAAG,OAAO,EAAE,YAAY,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAS,OAAO,EAAE,YAAY,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACxG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAA;AAIxB;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAAG,MAAM,CAI1F;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,GAAG,MAAM,CAK3E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAAG,MAAM,EAAE,CAG9F;AAID
|
|
1
|
+
{"version":3,"file":"lineage.d.ts","sourceRoot":"","sources":["../../../src/proxy/session/lineage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,4EAA4E;AAC5E,MAAM,WAAW,UAAU;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,2BAA2B,CAAC,EAAE,MAAM,CAAA;CACrC;AAED;0EAC0E;AAC1E,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAE1C,MAAM,WAAW,YAAY;IAC3B,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB;;qDAEiD;IACjD,WAAW,EAAE,MAAM,CAAA;IACnB;;kCAE8B;IAC9B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;oDAEgD;IAChD,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACtC,iGAAiG;IACjG,YAAY,CAAC,EAAE,UAAU,CAAA;CAC1B;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,YAAY,CAAC;IAAG,OAAO,EAAE,YAAY,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAS,OAAO,EAAE,YAAY,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACxG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAA;AAIxB;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAAG,MAAM,CAI1F;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,GAAG,MAAM,CAK3E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAAG,MAAM,EAAE,CAG9F;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ7F;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,CA6B7F;AAyBD,yEAAyE;AACzE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAC7B;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,EAC/C,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,gBAAgB,GACtB,aAAa,CA6Ff"}
|
|
@@ -23,6 +23,10 @@ export interface StoredSession {
|
|
|
23
23
|
sdkMessageUuids?: Array<string | null>;
|
|
24
24
|
/** Last observed token usage for this Claude session */
|
|
25
25
|
contextUsage?: TokenUsage;
|
|
26
|
+
/** Previous Claude session ID preserved when the session mapping is replaced.
|
|
27
|
+
* Enables recovery when a lineage bug (e.g. false compaction) causes the
|
|
28
|
+
* original session to be abandoned and a new one started. */
|
|
29
|
+
previousClaudeSessionId?: string;
|
|
26
30
|
}
|
|
27
31
|
/** Set an explicit session store directory. Takes priority over env var.
|
|
28
32
|
* Pass null to clear. For testing only.
|
|
@@ -36,5 +40,25 @@ export declare function storeSharedSession(key: string, claudeSessionId: string,
|
|
|
36
40
|
/** Remove a single session from the shared file store.
|
|
37
41
|
* Used when a session is detected as stale (e.g. expired upstream). */
|
|
38
42
|
export declare function evictSharedSession(key: string): void;
|
|
43
|
+
/** Look up recovery information for a session key.
|
|
44
|
+
* Returns the current and previous Claude session IDs, plus derived
|
|
45
|
+
* file paths and CLI commands for conversation recovery. */
|
|
46
|
+
export declare function lookupSessionRecovery(key: string): {
|
|
47
|
+
claudeSessionId: string;
|
|
48
|
+
previousClaudeSessionId?: string;
|
|
49
|
+
createdAt: number;
|
|
50
|
+
lastUsedAt: number;
|
|
51
|
+
messageCount: number;
|
|
52
|
+
} | undefined;
|
|
53
|
+
/** List all stored session keys and their Claude session IDs.
|
|
54
|
+
* Used by the recovery endpoint to find sessions by partial match. */
|
|
55
|
+
export declare function listStoredSessions(): Array<{
|
|
56
|
+
key: string;
|
|
57
|
+
claudeSessionId: string;
|
|
58
|
+
previousClaudeSessionId?: string;
|
|
59
|
+
createdAt: number;
|
|
60
|
+
lastUsedAt: number;
|
|
61
|
+
messageCount: number;
|
|
62
|
+
}>;
|
|
39
63
|
export declare function clearSharedSessions(): void;
|
|
40
64
|
//# sourceMappingURL=sessionStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../../src/proxy/sessionStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAeH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEnD,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,iFAAiF;IACjF,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACtC,wDAAwD;IACxD,YAAY,CAAC,EAAE,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../../src/proxy/sessionStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAeH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEnD,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,iFAAiF;IACjF,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACtC,wDAAwD;IACxD,YAAY,CAAC,EAAE,UAAU,CAAA;IACzB;;kEAE8D;IAC9D,uBAAuB,CAAC,EAAE,MAAM,CAAA;CACjC;AA0DD;;oFAEoF;AACpF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAG7F;AAsED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAG1E;AAED,wBAAgB,6BAA6B,CAAC,eAAe,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAYhG;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,MAAM,EACvB,YAAY,CAAC,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,MAAM,EACpB,aAAa,CAAC,EAAE,MAAM,EAAE,EACxB,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,EACtC,YAAY,CAAC,EAAE,UAAU,GACxB,IAAI,CA8CN;AAED;wEACwE;AACxE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAkBpD;AAED;;6DAE6D;AAC7D,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG;IAClD,eAAe,EAAE,MAAM,CAAA;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,SAAS,CAWZ;AAED;uEACuE;AACvE,wBAAgB,kBAAkB,IAAI,KAAK,CAAC;IAC1C,GAAG,EAAE,MAAM,CAAA;IACX,eAAe,EAAE,MAAM,CAAA;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAC,CAUD;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAO1C"}
|
package/dist/server.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynfar/meridian",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.29.0",
|
|
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",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"build": "rm -rf dist && bun build bin/cli.ts src/proxy/server.ts --outdir dist --target node --splitting --external @anthropic-ai/claude-agent-sdk --entry-naming '[name].js' && tsc -p tsconfig.build.json",
|
|
25
25
|
"postbuild": "node --check dist/cli.js && node --check dist/server.js && test -f dist/proxy/server.d.ts",
|
|
26
26
|
"prepublishOnly": "bun run build",
|
|
27
|
-
"test": "bun test --path-ignore-patterns '**/*session-store*' --path-ignore-patterns '**/*proxy-async-ops*' --path-ignore-patterns '**/*proxy-extra-usage-fallback*' --path-ignore-patterns '**/*models-auth-status*' --path-ignore-patterns '**/*proxy-context-usage-store*' --path-ignore-patterns '**/*proxy-passthrough-thinking*' --path-ignore-patterns '**/*profile-switch-integration*' && bun test src/__tests__/profile-switch-integration.test.ts && bun test src/__tests__/proxy-extra-usage-fallback.test.ts && 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",
|
|
27
|
+
"test": "bun test --path-ignore-patterns '**/*session-store*' --path-ignore-patterns '**/*proxy-async-ops*' --path-ignore-patterns '**/*proxy-extra-usage-fallback*' --path-ignore-patterns '**/*models-auth-status*' --path-ignore-patterns '**/*proxy-context-usage-store*' --path-ignore-patterns '**/*proxy-passthrough-thinking*' --path-ignore-patterns '**/*profile-switch-integration*' --path-ignore-patterns '**/*session-recovery*' && bun test src/__tests__/profile-switch-integration.test.ts && bun test src/__tests__/proxy-extra-usage-fallback.test.ts && 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",
|
|
28
28
|
"typecheck": "tsc --noEmit",
|
|
29
29
|
"proxy:direct": "bun run ./bin/cli.ts"
|
|
30
30
|
},
|