fix: land multi-agent session path fix + regressions (#15103) (#15448)

Co-authored-by: Josh Lehman <josh@martian.engineering>
This commit is contained in:
Peter Steinberger
2026-02-13 14:17:24 +01:00
committed by GitHub
parent 5d37b204c0
commit 990413534a
11 changed files with 274 additions and 37 deletions

View File

@@ -64,10 +64,20 @@ vi.mock("../../infra/session-cost-usage.js", async () => {
cacheWriteCost: 0,
missingCostEntries: 0,
})),
loadSessionUsageTimeSeries: vi.fn(async () => ({
sessionId: "s-opus",
points: [],
})),
loadSessionLogs: vi.fn(async () => []),
};
});
import { discoverAllSessions } from "../../infra/session-cost-usage.js";
import {
discoverAllSessions,
loadSessionCostSummary,
loadSessionLogs,
loadSessionUsageTimeSeries,
} from "../../infra/session-cost-usage.js";
import { loadCombinedSessionStoreForGateway } from "../session-utils.js";
import { usageHandlers } from "./usage.js";
@@ -148,6 +158,10 @@ describe("sessions.usage", () => {
const result = respond.mock.calls[0]?.[1] as unknown as { sessions: Array<{ key: string }> };
expect(result.sessions).toHaveLength(1);
expect(result.sessions[0]?.key).toBe(storeKey);
expect(vi.mocked(loadSessionCostSummary)).toHaveBeenCalled();
expect(
vi.mocked(loadSessionCostSummary).mock.calls.some((call) => call[0]?.agentId === "opus"),
).toBe(true);
} finally {
if (previousStateDir === undefined) {
delete process.env.OPENCLAW_STATE_DIR;
@@ -176,4 +190,32 @@ describe("sessions.usage", () => {
const error = respond.mock.calls[0]?.[2] as { message?: string } | undefined;
expect(error?.message).toContain("Invalid session reference");
});
it("passes parsed agentId into sessions.usage.timeseries", async () => {
const respond = vi.fn();
await usageHandlers["sessions.usage.timeseries"]({
respond,
params: {
key: "agent:opus:s-opus",
},
} as unknown as Parameters<(typeof usageHandlers)["sessions.usage.timeseries"]>[0]);
expect(vi.mocked(loadSessionUsageTimeSeries)).toHaveBeenCalled();
expect(vi.mocked(loadSessionUsageTimeSeries).mock.calls[0]?.[0]?.agentId).toBe("opus");
});
it("passes parsed agentId into sessions.usage.logs", async () => {
const respond = vi.fn();
await usageHandlers["sessions.usage.logs"]({
respond,
params: {
key: "agent:opus:s-opus",
},
} as unknown as Parameters<(typeof usageHandlers)["sessions.usage.logs"]>[0]);
expect(vi.mocked(loadSessionLogs)).toHaveBeenCalled();
expect(vi.mocked(loadSessionLogs).mock.calls[0]?.[0]?.agentId).toBe("opus");
});
});

View File

@@ -496,11 +496,13 @@ export const usageHandlers: GatewayRequestHandlers = {
};
for (const merged of limitedEntries) {
const agentId = parseAgentSessionKey(merged.key)?.agentId;
const usage = await loadSessionCostSummary({
sessionId: merged.sessionId,
sessionEntry: merged.storeEntry,
sessionFile: merged.sessionFile,
config,
agentId,
startMs,
endMs,
});
@@ -519,7 +521,6 @@ export const usageHandlers: GatewayRequestHandlers = {
aggregateTotals.missingCostEntries += usage.missingCostEntries;
}
const agentId = parseAgentSessionKey(merged.key)?.agentId;
const channel = merged.storeEntry?.channel ?? merged.storeEntry?.origin?.provider;
const chatType = merged.storeEntry?.chatType ?? merged.storeEntry?.origin?.chatType;
@@ -796,6 +797,7 @@ export const usageHandlers: GatewayRequestHandlers = {
sessionEntry: entry,
sessionFile,
config,
agentId,
maxPoints: 200,
});
@@ -849,6 +851,7 @@ export const usageHandlers: GatewayRequestHandlers = {
sessionEntry: entry,
sessionFile,
config,
agentId,
limit,
});