Skip to content

Commit 55d3a4e

Browse files
committed
refactor: use canonical transcript reader identity
1 parent 925d98d commit 55d3a4e

34 files changed

Lines changed: 521 additions & 257 deletions

scripts/check-session-accessor-boundary.mjs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,20 @@ export const migratedSessionAccessorFiles = new Set([
9595
"src/cron/isolated-agent/delivery-target.ts",
9696
"src/cron/service/timer.ts",
9797
"src/gateway/session-compaction-checkpoints.ts",
98+
"src/gateway/session-history-state.ts",
9899
"src/gateway/session-utils.ts",
100+
"src/gateway/managed-image-attachments.ts",
101+
"src/gateway/server-methods/artifacts.ts",
102+
"src/gateway/server-methods/chat.ts",
99103
"src/gateway/sessions-resolve.ts",
104+
"src/gateway/server-methods/sessions-files.ts",
100105
"src/gateway/server-methods/sessions.ts",
106+
"src/gateway/server-session-events.ts",
107+
"src/gateway/session-reset-service.ts",
101108
"src/infra/outbound/message-action-tts.ts",
109+
"src/agents/tools/embedded-gateway-stub.ts",
110+
"src/agents/tools/sessions-list-tool.ts",
111+
"src/status/status-message.ts",
102112
"src/tui/embedded-backend.ts",
103113
]);
104114

src/agents/main-session-restart-recovery.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,8 +805,9 @@ async function recoverStore(params: {
805805
messages = await readSessionMessagesAsync(
806806
{
807807
agentId: resolveAgentIdFromSessionKey(sessionKey),
808-
sessionFile: entry.sessionFile,
808+
sessionEntry: entry,
809809
sessionId: entry.sessionId,
810+
sessionKey,
810811
storePath: params.storePath,
811812
},
812813
{

src/agents/subagent-announce-output.test.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import {
1212
type CallGateway = typeof import("../gateway/call.js").callGateway;
1313
type GetRuntimeConfig = typeof import("./subagent-announce.runtime.js").getRuntimeConfig;
1414
type ReadSessionEntry = typeof import("./subagent-announce.runtime.js").readSessionEntry;
15-
type ReadSessionMessagesAsync =
16-
typeof import("./subagent-announce.runtime.js").readSessionMessagesAsync;
15+
type ReadSessionMessagesFromFileAsync =
16+
typeof import("./subagent-announce.runtime.js").readSessionMessagesFromFileAsync;
1717
type ResolveAgentIdFromSessionKey =
1818
typeof import("./subagent-announce.runtime.js").resolveAgentIdFromSessionKey;
1919
type ResolveStorePath = typeof import("./subagent-announce.runtime.js").resolveStorePath;
@@ -23,12 +23,13 @@ function installOutputDeps(params: {
2323
transcriptMessages?: Array<unknown>;
2424
}) {
2525
const callGateway = vi.fn(async () => ({ messages: params.messages }));
26-
const readSessionMessagesAsync = vi.fn(async () => params.transcriptMessages ?? []);
26+
const readSessionMessagesFromFileAsync = vi.fn(async () => params.transcriptMessages ?? []);
2727
testing.setDepsForTest({
2828
callGateway: callGateway as unknown as CallGateway,
29-
readSessionMessagesAsync: readSessionMessagesAsync as unknown as ReadSessionMessagesAsync,
29+
readSessionMessagesFromFileAsync:
30+
readSessionMessagesFromFileAsync as unknown as ReadSessionMessagesFromFileAsync,
3031
});
31-
return { callGateway, readSessionMessagesAsync };
32+
return { callGateway, readSessionMessagesFromFileAsync };
3233
}
3334

3435
function sessionsYieldTurn(message = "Waiting for subagent completion.") {
@@ -215,7 +216,7 @@ describe("readSubagentOutput", () => {
215216
sessionFile: "/tmp/openclaw-internal-run.jsonl",
216217
}),
217218
).resolves.toBe("fresh recovered output");
218-
expect(deps.readSessionMessagesAsync).toHaveBeenCalledWith(
219+
expect(deps.readSessionMessagesFromFileAsync).toHaveBeenCalledWith(
219220
{
220221
sessionFile: "/tmp/openclaw-internal-run.jsonl",
221222
sessionId: "agent:main:subagent:child",

src/agents/subagent-announce-output.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
callGateway,
1616
getRuntimeConfig,
1717
readSessionEntry,
18-
readSessionMessagesAsync,
18+
readSessionMessagesFromFileAsync,
1919
resolveAgentIdFromSessionKey,
2020
resolveStorePath,
2121
} from "./subagent-announce.runtime.js";
@@ -29,7 +29,7 @@ type SubagentAnnounceOutputDeps = {
2929
callGateway: typeof callGateway;
3030
getRuntimeConfig: typeof getRuntimeConfig;
3131
readSessionEntry: typeof readSessionEntry;
32-
readSessionMessagesAsync: typeof readSessionMessagesAsync;
32+
readSessionMessagesFromFileAsync: typeof readSessionMessagesFromFileAsync;
3333
resolveAgentIdFromSessionKey: typeof resolveAgentIdFromSessionKey;
3434
resolveStorePath: typeof resolveStorePath;
3535
};
@@ -38,7 +38,7 @@ const defaultSubagentAnnounceOutputDeps: SubagentAnnounceOutputDeps = {
3838
callGateway,
3939
getRuntimeConfig,
4040
readSessionEntry,
41-
readSessionMessagesAsync,
41+
readSessionMessagesFromFileAsync,
4242
resolveAgentIdFromSessionKey,
4343
resolveStorePath,
4444
};
@@ -206,7 +206,7 @@ export async function readSubagentOutput(
206206
): Promise<string | undefined> {
207207
let messages: unknown[] | undefined;
208208
if (options?.sessionFile) {
209-
const transcriptMessages = await subagentAnnounceOutputDeps.readSessionMessagesAsync(
209+
const transcriptMessages = await subagentAnnounceOutputDeps.readSessionMessagesFromFileAsync(
210210
{
211211
sessionFile: options.sessionFile,
212212
sessionId: sessionKey,

src/agents/subagent-announce.runtime.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ export {
1212
resolveStorePath,
1313
} from "../config/sessions.js";
1414
export { callGateway } from "../gateway/call.js";
15-
export { readSessionMessagesAsync } from "../gateway/session-transcript-readers.js";
15+
export {
16+
readSessionMessagesAsync,
17+
readSessionMessagesAsync as readSessionMessagesFromFileAsync,
18+
} from "../gateway/session-transcript-readers.js";
1619
export { dispatchGatewayMethodInProcess } from "../gateway/server-plugins.js";
1720
export {
1821
isEmbeddedAgentRunActive,

src/agents/subagent-announce.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ vi.mock("./subagent-announce.runtime.js", () => ({
6565
getRuntimeConfig: () => mockConfig,
6666
loadSessionStore: (storePath: string) => loadSessionStoreMock(storePath),
6767
readSessionMessagesAsync: vi.fn(async () => []),
68+
readSessionMessagesFromFileAsync: vi.fn(async () => []),
6869
readSessionEntry: (storePath: string, sessionKey: string) =>
6970
(loadSessionStoreMock(storePath) as Record<string, unknown>)[sessionKey],
7071
resolveAgentIdFromSessionKey: (sessionKey: string) =>

src/agents/subagent-announce.timeout.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ vi.mock("./subagent-announce.runtime.js", () => ({
188188
getRuntimeConfig: () => configOverride,
189189
loadSessionStore: vi.fn(() => sessionStore),
190190
readSessionMessagesAsync: vi.fn(async () => []),
191+
readSessionMessagesFromFileAsync: vi.fn(async () => []),
191192
readSessionEntry: (_storePath: string, sessionKey: string) => sessionStore[sessionKey],
192193
resolveAgentIdFromSessionKey: () => "main",
193194
resolveStorePath: () => "/tmp/sessions-main.json",

src/agents/subagent-orphan-recovery.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,9 @@ export async function recoverOrphanedSubagentSessions(params: {
296296
const messages = await readSessionMessagesAsync(
297297
{
298298
agentId: resolveAgentIdFromSessionKey(childSessionKey),
299-
sessionFile: entry.sessionFile,
299+
sessionEntry: entry,
300300
sessionId: entry.sessionId,
301+
sessionKey: childSessionKey,
301302
storePath,
302303
},
303304
{

src/agents/test-helpers/fast-openclaw-tools-sessions.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,16 @@ vi.mock("../../channels/plugins/session-conversation.js", () => ({
6969
threadId: match.groups.threadId,
7070
};
7171
},
72+
resolveSessionThreadInfo: (sessionKey: string | undefined | null) => {
73+
const trimmed = sessionKey?.trim();
74+
const topicMarker = ":topic:";
75+
const topicIndex = trimmed?.lastIndexOf(topicMarker) ?? -1;
76+
if (!trimmed || topicIndex < 0) {
77+
return { baseSessionKey: trimmed, threadId: undefined };
78+
}
79+
return {
80+
baseSessionKey: trimmed.slice(0, topicIndex),
81+
threadId: trimmed.slice(topicIndex + topicMarker.length) || undefined,
82+
};
83+
},
7284
}));

src/agents/tools/embedded-gateway-stub.test.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,9 @@ describe("embedded gateway stub", () => {
126126
expect(runtime.readSessionMessagesAsync).toHaveBeenCalledWith(
127127
{
128128
agentId: "main",
129-
sessionFile: undefined,
129+
sessionEntry: { sessionId: "sess-main" },
130130
sessionId: "sess-main",
131+
sessionKey: "agent:main:main",
131132
storePath: "/tmp/openclaw-sessions.json",
132133
},
133134
{
@@ -192,8 +193,9 @@ describe("embedded gateway stub", () => {
192193
expect(runtime.readSessionMessagesAsync).toHaveBeenCalledWith(
193194
{
194195
agentId: "main",
195-
sessionFile: undefined,
196+
sessionEntry: { sessionId: "sess-main" },
196197
sessionId: "sess-main",
198+
sessionKey: "agent:main:main",
197199
storePath: "/tmp/openclaw-sessions.json",
198200
},
199201
{
@@ -225,8 +227,9 @@ describe("embedded gateway stub", () => {
225227
expect(runtime.readSessionMessagesAsync).toHaveBeenCalledWith(
226228
{
227229
agentId: "main",
228-
sessionFile: undefined,
230+
sessionEntry: { sessionId: "sess-main" },
229231
sessionId: "sess-main",
232+
sessionKey: "agent:main:main",
230233
storePath: "/tmp/openclaw-sessions.json",
231234
},
232235
{

0 commit comments

Comments
 (0)