perf(test): keep session init thread parsing hot path lazy

This commit is contained in:
Peter Steinberger
2026-04-20 17:14:32 +01:00
parent 9e125184ed
commit 6a4d633e42
4 changed files with 62 additions and 5 deletions

View File

@@ -1,2 +1,2 @@
cf682f7ed83294f79b72758a9bfa0a720da38f967e249bae5bfa916b2a5f0238 plugin-sdk-api-baseline.json
67c723fb639384f457b2900bc1f2bf2639462ae0d2091e6984b77fd9c5c30251 plugin-sdk-api-baseline.jsonl
15505f02306eb9920e350babf1b290d8fcc1b2338b4fccf65d3525de83d9bbcb plugin-sdk-api-baseline.json
06fc58082be4c2e1df1030fa9e8d965c6d5947984c4aed360c0474c1639a0a84 plugin-sdk-api-baseline.jsonl

View File

@@ -26,6 +26,31 @@ import { drainFormattedSystemEvents } from "./session-updates.js";
import { persistSessionUsageUpdate } from "./session-usage.js";
import { initSessionState } from "./session.js";
const sessionForkMocks = vi.hoisted(() => ({
forkSessionFromParent: vi.fn(),
nextSessionId: 0,
}));
type ForkSessionParamsForTest = {
parentEntry: SessionEntry;
sessionsDir: string;
};
vi.mock("./session-fork.js", () => ({
forkSessionFromParent: (...args: [ForkSessionParamsForTest]) =>
sessionForkMocks.forkSessionFromParent(...args),
resolveParentForkMaxTokens: (cfg: { session?: { parentForkMaxTokens?: unknown } }) => {
const configured = cfg.session?.parentForkMaxTokens;
return typeof configured === "number" && Number.isFinite(configured) && configured >= 0
? Math.floor(configured)
: 100_000;
},
}));
vi.mock("../../plugins/hook-runner-global.js", () => ({
getGlobalHookRunner: () => null,
}));
// Perf: session-store locks are exercised elsewhere; most session tests don't need FS lock files.
vi.mock("../../agents/session-write-lock.js", async () => {
const actual = await vi.importActual<typeof import("../../agents/session-write-lock.js")>(
@@ -216,6 +241,30 @@ function registerCurrentConversationBindingAdapterForTest(params: {
beforeEach(() => {
sessionBindingTesting.resetSessionBindingAdaptersForTests();
sessionForkMocks.nextSessionId = 0;
sessionForkMocks.forkSessionFromParent
.mockReset()
.mockImplementation(async ({ parentEntry, sessionsDir }: ForkSessionParamsForTest) => {
if (!parentEntry.sessionFile) {
return null;
}
await fs.mkdir(sessionsDir, { recursive: true });
const sessionId = `forked-session-${++sessionForkMocks.nextSessionId}`;
const sessionFile = path.join(sessionsDir, `${sessionId}.jsonl`);
await fs.writeFile(
sessionFile,
`${JSON.stringify({
type: "session",
version: 3,
id: sessionId,
timestamp: new Date().toISOString(),
cwd: process.cwd(),
parentSession: parentEntry.sessionFile,
})}\n`,
"utf-8",
);
return { sessionId, sessionFile: await fs.realpath(sessionFile) };
});
});
afterEach(async () => {
await sessionMcpTesting.resetSessionMcpRuntimeManager();

View File

@@ -21,7 +21,7 @@ import { resolveAndPersistSessionFile } from "../../config/sessions/session-file
import { resolveSessionKey } from "../../config/sessions/session-key.js";
import { resolveMaintenanceConfigFromInput } from "../../config/sessions/store-maintenance.js";
import { loadSessionStore, updateSessionStore } from "../../config/sessions/store.js";
import { parseSessionThreadInfo } from "../../config/sessions/thread-info.js";
import { parseSessionThreadInfoFast } from "../../config/sessions/thread-info.js";
import {
DEFAULT_RESET_TRIGGERS,
type GroupKeyResolution,
@@ -689,7 +689,7 @@ export async function initSessionState(params: {
}
}
}
const threadIdFromSessionKey = parseSessionThreadInfo(
const threadIdFromSessionKey = parseSessionThreadInfoFast(
sessionCtxForState.SessionKey ?? sessionKey,
).threadId;
const fallbackSessionFile = !sessionEntry.sessionFile

View File

@@ -1,3 +1,4 @@
import type { ResolvedConfiguredAcpBinding } from "../acp/persistent-bindings.types.js";
import { buildChatChannelMetaById } from "../channels/chat-meta-shared.js";
import type { ChatChannelId } from "../channels/ids.js";
import { emptyChannelConfigSchema } from "../channels/plugins/config-schema.js";
@@ -209,9 +210,16 @@ export {
export { parseStrictPositiveInteger } from "../infra/parse-finite-number.js";
export { isTrustedProxyAddress, resolveClientIp } from "../gateway/net.js";
export { formatZonedTimestamp } from "../infra/format-time/format-datetime.js";
export { ensureConfiguredAcpBindingReady } from "../acp/persistent-bindings.lifecycle.js";
export { resolveConfiguredAcpBindingRecord } from "../acp/persistent-bindings.resolve.js";
export async function ensureConfiguredAcpBindingReady(params: {
cfg: OpenClawConfig;
configuredBinding: ResolvedConfiguredAcpBinding | null;
}): Promise<{ ok: true } | { ok: false; error: string }> {
const runtime = await import("../acp/persistent-bindings.lifecycle.js");
return runtime.ensureConfiguredAcpBindingReady(params);
}
export { resolveTailnetHostWithRunner } from "../shared/tailscale-status.js";
export type {
TailscaleStatusCommandResult,