mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-26 17:32:16 +00:00
fix: prefer deterministic session usage targets
This commit is contained in:
@@ -189,6 +189,46 @@ describe("sessions.usage", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("prefers the deterministic store key when duplicate sessionIds exist", async () => {
|
||||
const preferredKey = "agent:opus:acp:run-dup";
|
||||
const stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-usage-test-"));
|
||||
|
||||
try {
|
||||
await withEnvAsync({ OPENCLAW_STATE_DIR: stateDir }, async () => {
|
||||
const agentSessionsDir = path.join(stateDir, "agents", "opus", "sessions");
|
||||
fs.mkdirSync(agentSessionsDir, { recursive: true });
|
||||
const sessionFile = path.join(agentSessionsDir, "run-dup.jsonl");
|
||||
fs.writeFileSync(sessionFile, "", "utf-8");
|
||||
|
||||
vi.mocked(loadCombinedSessionStoreForGateway).mockReturnValue({
|
||||
storePath: "(multiple)",
|
||||
store: {
|
||||
[preferredKey]: {
|
||||
sessionId: "run-dup",
|
||||
sessionFile: "run-dup.jsonl",
|
||||
updatedAt: 1_000,
|
||||
},
|
||||
"agent:other:main": {
|
||||
sessionId: "run-dup",
|
||||
sessionFile: "run-dup.jsonl",
|
||||
updatedAt: 2_000,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const respond = await runSessionsUsage({
|
||||
...BASE_USAGE_RANGE,
|
||||
key: "agent:opus:run-dup",
|
||||
});
|
||||
const sessions = expectSuccessfulSessionsUsage(respond);
|
||||
expect(sessions).toHaveLength(1);
|
||||
expect(sessions[0]?.key).toBe(preferredKey);
|
||||
});
|
||||
} finally {
|
||||
fs.rmSync(stateDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects traversal-style keys in specific session usage lookups", async () => {
|
||||
const respond = await runSessionsUsage({
|
||||
...BASE_USAGE_RANGE,
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
type DiscoveredSession,
|
||||
} from "../../infra/session-cost-usage.js";
|
||||
import { parseAgentSessionKey } from "../../routing/session-key.js";
|
||||
import { resolvePreferredSessionKeyForSessionIdMatches } from "../../sessions/session-id-resolution.js";
|
||||
import {
|
||||
buildUsageAggregateTail,
|
||||
mergeUsageDailyLatency,
|
||||
@@ -252,10 +253,25 @@ type DiscoveredSessionWithAgent = DiscoveredSession & { agentId: string };
|
||||
function buildStoreBySessionId(
|
||||
store: Record<string, SessionEntry>,
|
||||
): Map<string, { key: string; entry: SessionEntry }> {
|
||||
const storeBySessionId = new Map<string, { key: string; entry: SessionEntry }>();
|
||||
const matchesBySessionId = new Map<string, Array<[string, SessionEntry]>>();
|
||||
for (const [key, entry] of Object.entries(store)) {
|
||||
if (entry?.sessionId) {
|
||||
storeBySessionId.set(entry.sessionId, { key, entry });
|
||||
if (!entry?.sessionId) {
|
||||
continue;
|
||||
}
|
||||
const matches = matchesBySessionId.get(entry.sessionId) ?? [];
|
||||
matches.push([key, entry]);
|
||||
matchesBySessionId.set(entry.sessionId, matches);
|
||||
}
|
||||
|
||||
const storeBySessionId = new Map<string, { key: string; entry: SessionEntry }>();
|
||||
for (const [sessionId, matches] of matchesBySessionId) {
|
||||
const preferredKey = resolvePreferredSessionKeyForSessionIdMatches(matches, sessionId);
|
||||
if (!preferredKey) {
|
||||
continue;
|
||||
}
|
||||
const preferredEntry = store[preferredKey];
|
||||
if (preferredEntry) {
|
||||
storeBySessionId.set(sessionId, { key: preferredKey, entry: preferredEntry });
|
||||
}
|
||||
}
|
||||
return storeBySessionId;
|
||||
|
||||
Reference in New Issue
Block a user