mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-04 08:20:24 +00:00
Sessions: fix sessions_list transcriptPath path resolution
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import path from "node:path";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
addSubagentRunForTests,
|
||||
@@ -171,6 +172,46 @@ describe("sessions tools", () => {
|
||||
expect(cronDetails.sessions?.[0]?.kind).toBe("cron");
|
||||
});
|
||||
|
||||
it("sessions_list resolves transcriptPath from agent state dir for multi-store listings", async () => {
|
||||
callGatewayMock.mockImplementation(async (opts: unknown) => {
|
||||
const request = opts as { method?: string };
|
||||
if (request.method === "sessions.list") {
|
||||
return {
|
||||
path: "(multiple)",
|
||||
sessions: [
|
||||
{
|
||||
key: "main",
|
||||
kind: "direct",
|
||||
sessionId: "sess-main",
|
||||
updatedAt: 12,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
return {};
|
||||
});
|
||||
|
||||
const tool = createOpenClawTools().find((candidate) => candidate.name === "sessions_list");
|
||||
expect(tool).toBeDefined();
|
||||
if (!tool) {
|
||||
throw new Error("missing sessions_list tool");
|
||||
}
|
||||
|
||||
const result = await tool.execute("call2b", {});
|
||||
const details = result.details as {
|
||||
sessions?: Array<{
|
||||
key?: string;
|
||||
transcriptPath?: string;
|
||||
}>;
|
||||
};
|
||||
const main = details.sessions?.find((session) => session.key === "main");
|
||||
expect(typeof main?.transcriptPath).toBe("string");
|
||||
expect(main?.transcriptPath).not.toContain("(multiple)");
|
||||
expect(main?.transcriptPath).toContain(
|
||||
path.join("agents", "main", "sessions", "sess-main.jsonl"),
|
||||
);
|
||||
});
|
||||
|
||||
it("sessions_history filters tool messages by default", async () => {
|
||||
callGatewayMock.mockImplementation(async (opts: unknown) => {
|
||||
const request = opts as { method?: string };
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import path from "node:path";
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { loadConfig } from "../../config/config.js";
|
||||
import { resolveSessionFilePath } from "../../config/sessions.js";
|
||||
import { resolveSessionFilePath, resolveSessionFilePathOptions } from "../../config/sessions.js";
|
||||
import { callGateway } from "../../gateway/call.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
||||
import type { AnyAgentTool } from "./common.js";
|
||||
@@ -156,13 +155,14 @@ export function createSessionsListTool(opts?: {
|
||||
let transcriptPath: string | undefined;
|
||||
if (sessionId && storePath) {
|
||||
try {
|
||||
const sessionPathOpts = resolveSessionFilePathOptions({
|
||||
agentId: resolveAgentIdFromSessionKey(key),
|
||||
storePath,
|
||||
});
|
||||
transcriptPath = resolveSessionFilePath(
|
||||
sessionId,
|
||||
sessionFile ? { sessionFile } : undefined,
|
||||
{
|
||||
agentId: resolveAgentIdFromSessionKey(key),
|
||||
sessionsDir: path.dirname(storePath),
|
||||
},
|
||||
sessionPathOpts,
|
||||
);
|
||||
} catch {
|
||||
transcriptPath = undefined;
|
||||
|
||||
@@ -39,13 +39,15 @@ export type SessionFilePathOptions = {
|
||||
sessionsDir?: string;
|
||||
};
|
||||
|
||||
const MULTI_STORE_PATH_SENTINEL = "(multiple)";
|
||||
|
||||
export function resolveSessionFilePathOptions(params: {
|
||||
agentId?: string;
|
||||
storePath?: string;
|
||||
}): SessionFilePathOptions | undefined {
|
||||
const agentId = params.agentId?.trim();
|
||||
const storePath = params.storePath?.trim();
|
||||
if (storePath) {
|
||||
if (storePath && storePath !== MULTI_STORE_PATH_SENTINEL) {
|
||||
const sessionsDir = path.dirname(path.resolve(storePath));
|
||||
return agentId ? { sessionsDir, agentId } : { sessionsDir };
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
import type { SessionConfig } from "../types.base.js";
|
||||
import {
|
||||
resolveSessionFilePath,
|
||||
resolveSessionFilePathOptions,
|
||||
resolveSessionTranscriptPathInDir,
|
||||
validateSessionId,
|
||||
} from "./paths.js";
|
||||
@@ -68,6 +69,13 @@ describe("session path safety", () => {
|
||||
expect(resolved).toBe(path.resolve(sessionsDir, "sess-1.jsonl"));
|
||||
});
|
||||
|
||||
it("ignores multi-store sentinel paths when deriving session file options", () => {
|
||||
expect(resolveSessionFilePathOptions({ agentId: "worker", storePath: "(multiple)" })).toEqual({
|
||||
agentId: "worker",
|
||||
});
|
||||
expect(resolveSessionFilePathOptions({ storePath: "(multiple)" })).toBeUndefined();
|
||||
});
|
||||
|
||||
it("accepts symlink-alias session paths that resolve under the sessions dir", () => {
|
||||
if (process.platform === "win32") {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user