feat (memory): Implement new (opt-in) QMD memory backend

This commit is contained in:
Vignesh Natarajan
2026-01-27 21:57:15 -08:00
committed by Vignesh
parent e9f182def7
commit 5d3af3bc62
24 changed files with 1828 additions and 601 deletions

View File

@@ -1,5 +1,3 @@
import type { MemoryIndexManager } from "../memory/manager.js";
import type { RuntimeEnv } from "../runtime.js";
import { withProgress } from "../cli/progress.js";
import { loadConfig } from "../config/config.js";
import { buildGatewayConnectionDetails, callGateway } from "../gateway/call.js";
@@ -8,14 +6,17 @@ import { probeGateway } from "../gateway/probe.js";
import { collectChannelStatusIssues } from "../infra/channels-status-issues.js";
import { resolveOsSummary } from "../infra/os-summary.js";
import { getTailnetHostname } from "../infra/tailscale.js";
import { getMemorySearchManager } from "../memory/index.js";
import type { MemoryProviderStatus } from "../memory/types.js";
import { runExec } from "../process/exec.js";
import { buildChannelsTable } from "./status-all/channels.js";
import type { RuntimeEnv } from "../runtime.js";
import { getAgentLocalStatuses } from "./status.agent-local.js";
import { pickGatewaySelfPresence, resolveGatewayProbeAuth } from "./status.gateway-probe.js";
import { getStatusSummary } from "./status.summary.js";
import { getUpdateCheckResult } from "./status.update.js";
import { buildChannelsTable } from "./status-all/channels.js";
type MemoryStatusSnapshot = ReturnType<MemoryIndexManager["status"]> & {
type MemoryStatusSnapshot = MemoryProviderStatus & {
agentId: string;
};
@@ -27,9 +28,7 @@ type MemoryPluginStatus = {
function resolveMemoryPluginStatus(cfg: ReturnType<typeof loadConfig>): MemoryPluginStatus {
const pluginsEnabled = cfg.plugins?.enabled !== false;
if (!pluginsEnabled) {
return { enabled: false, slot: null, reason: "plugins disabled" };
}
if (!pluginsEnabled) return { enabled: false, slot: null, reason: "plugins disabled" };
const raw = typeof cfg.plugins?.slots?.memory === "string" ? cfg.plugins.slots.memory.trim() : "";
if (raw && raw.toLowerCase() === "none") {
return { enabled: false, slot: null, reason: 'plugins.slots.memory="none"' };
@@ -127,7 +126,7 @@ export async function scanStatus(
progress.setLabel("Querying channel status…");
const channelsStatus = gatewayReachable
? await callGateway({
? await callGateway<Record<string, unknown>>({
method: "channels.status",
params: {
probe: false,
@@ -142,31 +141,24 @@ export async function scanStatus(
progress.setLabel("Summarizing channels…");
const channels = await buildChannelsTable(cfg, {
// Show token previews in regular status; keep `status --all` redacted.
// Set `OPENCLAW_SHOW_SECRETS=0` to force redaction.
showSecrets: process.env.OPENCLAW_SHOW_SECRETS?.trim() !== "0",
// Set `CLAWDBOT_SHOW_SECRETS=0` to force redaction.
showSecrets: process.env.CLAWDBOT_SHOW_SECRETS?.trim() !== "0",
});
progress.tick();
progress.setLabel("Checking memory…");
const memoryPlugin = resolveMemoryPluginStatus(cfg);
const memory = await (async (): Promise<MemoryStatusSnapshot | null> => {
if (!memoryPlugin.enabled) {
return null;
}
if (memoryPlugin.slot !== "memory-core") {
return null;
}
if (!memoryPlugin.enabled) return null;
if (memoryPlugin.slot !== "memory-core") return null;
const agentId = agentStatus.defaultId ?? "main";
const { MemoryIndexManager } = await import("../memory/manager.js");
const manager = await MemoryIndexManager.get({ cfg, agentId }).catch(() => null);
if (!manager) {
return null;
}
const { manager } = await getMemorySearchManager({ cfg, agentId });
if (!manager) return null;
try {
await manager.probeVectorAvailability();
} catch {}
const status = manager.status();
await manager.close().catch(() => {});
await manager.close?.().catch(() => {});
return { agentId, ...status };
})();
progress.tick();