mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-27 09:21:35 +07:00
refactor: consolidate qmd mcporter state
This commit is contained in:
@@ -11,6 +11,7 @@ const { logWarnMock, logDebugMock, logInfoMock } = vi.hoisted(() => ({
|
||||
logDebugMock: vi.fn(),
|
||||
logInfoMock: vi.fn(),
|
||||
}));
|
||||
const MCPORTER_STATE_KEY = Symbol.for("openclaw.mcporterState");
|
||||
|
||||
type MockChild = EventEmitter & {
|
||||
stdout: EventEmitter;
|
||||
@@ -196,8 +197,7 @@ describe("QmdMemoryManager", () => {
|
||||
} else {
|
||||
(process.env as NodeJS.ProcessEnv & { Path?: string }).Path = originalWindowsPath;
|
||||
}
|
||||
delete (globalThis as Record<string, unknown>).__openclawMcporterDaemonStart;
|
||||
delete (globalThis as Record<string, unknown>).__openclawMcporterColdStartWarned;
|
||||
delete (globalThis as Record<PropertyKey, unknown>)[MCPORTER_STATE_KEY];
|
||||
});
|
||||
|
||||
it("debounces back-to-back sync calls", async () => {
|
||||
|
||||
@@ -7,6 +7,7 @@ import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import { writeFileWithinRoot } from "../infra/fs-safe.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { resolveGlobalSingleton } from "../shared/global-singleton.js";
|
||||
import { isFileMissingError, statRegularFile } from "./fs-utils.js";
|
||||
import { resolveCliSpawnInvocation, runCliCommand } from "./qmd-process.js";
|
||||
import { deriveQmdScopeChannel, deriveQmdScopeChatType, isQmdScopeAllowed } from "./qmd-scope.js";
|
||||
@@ -44,9 +45,22 @@ const QMD_EMBED_BACKOFF_BASE_MS = 60_000;
|
||||
const QMD_EMBED_BACKOFF_MAX_MS = 60 * 60 * 1000;
|
||||
const HAN_SCRIPT_RE = /[\u3400-\u9fff]/u;
|
||||
const QMD_BM25_HAN_KEYWORD_LIMIT = 12;
|
||||
const MCPORTER_STATE_KEY = Symbol.for("openclaw.mcporterState");
|
||||
|
||||
type McporterState = {
|
||||
coldStartWarned: boolean;
|
||||
daemonStart: Promise<void> | null;
|
||||
};
|
||||
|
||||
let qmdEmbedQueueTail: Promise<void> = Promise.resolve();
|
||||
|
||||
function getMcporterState(): McporterState {
|
||||
return resolveGlobalSingleton<McporterState>(MCPORTER_STATE_KEY, () => ({
|
||||
coldStartWarned: false,
|
||||
daemonStart: null,
|
||||
}));
|
||||
}
|
||||
|
||||
function hasHanScript(value: string): boolean {
|
||||
return HAN_SCRIPT_RE.test(value);
|
||||
}
|
||||
@@ -1209,35 +1223,28 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
if (!mcporter.enabled) {
|
||||
return;
|
||||
}
|
||||
const state = getMcporterState();
|
||||
if (!mcporter.startDaemon) {
|
||||
type McporterWarnGlobal = typeof globalThis & {
|
||||
__openclawMcporterColdStartWarned?: boolean;
|
||||
};
|
||||
const g: McporterWarnGlobal = globalThis;
|
||||
if (!g.__openclawMcporterColdStartWarned) {
|
||||
g.__openclawMcporterColdStartWarned = true;
|
||||
if (!state.coldStartWarned) {
|
||||
state.coldStartWarned = true;
|
||||
log.warn(
|
||||
"mcporter qmd bridge enabled but startDaemon=false; each query may cold-start QMD MCP. Consider setting memory.qmd.mcporter.startDaemon=true to keep it warm.",
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
type McporterGlobal = typeof globalThis & {
|
||||
__openclawMcporterDaemonStart?: Promise<void>;
|
||||
};
|
||||
const g: McporterGlobal = globalThis;
|
||||
if (!g.__openclawMcporterDaemonStart) {
|
||||
g.__openclawMcporterDaemonStart = (async () => {
|
||||
if (!state.daemonStart) {
|
||||
state.daemonStart = (async () => {
|
||||
try {
|
||||
await this.runMcporter(["daemon", "start"], { timeoutMs: 10_000 });
|
||||
} catch (err) {
|
||||
log.warn(`mcporter daemon start failed: ${String(err)}`);
|
||||
// Allow future searches to retry daemon start on transient failures.
|
||||
delete g.__openclawMcporterDaemonStart;
|
||||
state.daemonStart = null;
|
||||
}
|
||||
})();
|
||||
}
|
||||
await g.__openclawMcporterDaemonStart;
|
||||
await state.daemonStart;
|
||||
}
|
||||
|
||||
private async runMcporter(
|
||||
|
||||
Reference in New Issue
Block a user