if (!resolved) {
note("Memory search is explicitly disabled (enabled: false).", "Memory search"); return;
}
// QMD backend handles embeddings internally (e.g. embeddinggemma) — no // separate embedding provider is needed. Skip the provider check entirely. const backendConfig = resolveActiveMemoryBackendConfig({ cfg, agentId }); if (!backendConfig) {
note("No active memory plugin is registered for the current config.", "Memory search"); return;
} if (backendConfig.backend === "qmd") { const qmdCheck = await checkQmdBinaryAvailability({
command: backendConfig.qmd?.command ?? "qmd",
env: process.env,
cwd: resolveAgentWorkspaceDir(cfg, agentId),
}); if (!qmdCheck.available) {
note(
[
`QMD memory backend is configured, but the qmd binary could not be started (${backendConfig.qmd?.command ?? "qmd"}).`,
qmdCheck.error ? `Probe error: ${qmdCheck.error}` : null, "", "Fix (pick one):", "- Install the supported QMD package: npm install -g @tobilu/qmd (or bun install -g @tobilu/qmd)",
`- Set an explicit binary path: ${formatCliCommand("openclaw config set memory.qmd.command /absolute/path/to/qmd")}`,
`- Or switch back to builtin memory: ${formatCliCommand("openclaw config set memory.backend builtin")}`, "",
`Verify: ${formatCliCommand("openclaw memory status --deep")}`,
]
.filter(Boolean)
.join("\n"), "Memory search",
);
} return;
}
// If a specific provider is configured (not "auto"), check only that one. if (resolved.provider !== "auto") { if (resolved.provider === "local") { const suggestedRemoteProvider = resolveSuggestedRemoteMemoryProvider(); if (hasLocalEmbeddings(resolved.local, true)) { // Model path looks valid (explicit file, hf: URL, or default model). // If a gateway probe is available and reports not-ready, warn anyway — // the model download or node-llama-cpp setup may have failed at runtime. if (opts?.gatewayMemoryProbe?.checked && !opts.gatewayMemoryProbe.ready) { const detail = opts.gatewayMemoryProbe.error?.trim();
note(
[ 'Memory search provider is set to "local" and a model path is configured,', "but the gateway reports local embeddings are not ready.",
detail ? `Gateway probe: ${detail}` : null, "",
`Verify: ${formatCliCommand("openclaw memory status --deep")}`,
]
.filter(Boolean)
.join("\n"), "Memory search",
);
} return;
}
note(
[ 'Memory search provider is set to "local" but no local model file was found.', "", "Fix (pick one):",
`- Install node-llama-cpp and set a local model path in config`,
suggestedRemoteProvider
? `- Switch to a remote provider: ${formatCliCommand(`openclaw config set agents.defaults.memorySearch.provider ${suggestedRemoteProvider}`)}`
: `- Switch to a remote embedding provider in config`, "",
`Verify: ${formatCliCommand("openclaw memory status --deep")}`,
].join("\n"), "Memory search",
); return;
} if (resolved.provider === "lmstudio") { if (opts?.gatewayMemoryProbe?.checked && opts.gatewayMemoryProbe.ready) { return;
} const gatewayProbeWarning = buildGatewayProbeWarning(opts?.gatewayMemoryProbe);
note(
[
gatewayProbeWarning
? 'Memory search provider "lmstudio" is configured, but the gateway reports embeddings are not ready.'
: 'Memory search provider "lmstudio" is configured, but the gateway could not confirm embeddings are ready.',
gatewayProbeWarning,
`Verify: ${formatCliCommand("openclaw memory status --deep")}`,
]
.filter(Boolean)
.join("\n"), "Memory search",
); return;
} // Remote provider — check for API key if (hasRemoteApiKey || (await hasApiKeyForProvider(resolved.provider, cfg, agentDir))) { return;
} if (opts?.gatewayMemoryProbe?.checked && opts.gatewayMemoryProbe.ready) {
note(
[
`Memory search provider is set to "${resolved.provider}" but the API key was not found in the CLI environment.`, "The running gateway reports memory embeddings are ready for the default agent.",
`Verify: ${formatCliCommand("openclaw memory status --deep")}`,
].join("\n"), "Memory search",
); return;
} const gatewayProbeWarning = buildGatewayProbeWarning(opts?.gatewayMemoryProbe); const envVar = resolvePrimaryMemoryProviderEnvVar(resolved.provider);
note(
[
`Memory search provider is set to "${resolved.provider}" but no API key was found.`,
`Semantic recall will not work without a valid API key.`,
gatewayProbeWarning ? gatewayProbeWarning : null, "", "Fix (pick one):",
`- Set ${envVar} in your environment`,
`- Configure credentials: ${formatCliCommand("openclaw configure --section model")}`,
`- To disable: ${formatCliCommand("openclaw config set agents.defaults.memorySearch.enabled false")}`, "",
`Verify: ${formatCliCommand("openclaw memory status --deep")}`,
].join("\n"), "Memory search",
); return;
}
// provider === "auto": check all providers in resolution order if (hasLocalEmbeddings(resolved.local)) { return;
} const autoSelectProviders = listAutoSelectMemoryEmbeddingProviderDoctorMetadata().filter(
(provider) => provider.transport === "remote",
); for (const provider of autoSelectProviders) { if (hasRemoteApiKey || (await hasApiKeyForProvider(provider.authProviderId, cfg, agentDir))) { return;
}
}
if (opts?.gatewayMemoryProbe?.checked && opts.gatewayMemoryProbe.ready) {
note(
[ 'Memory search provider is set to "auto" but the API key was not found in the CLI environment.', "The running gateway reports memory embeddings are ready for the default agent.",
`Verify: ${formatCliCommand("openclaw memory status --deep")}`,
].join("\n"), "Memory search",
); return;
} const gatewayProbeWarning = buildGatewayProbeWarning(opts?.gatewayMemoryProbe);
note(
[ "Memory search is enabled, but no embedding provider is ready.", "Semantic recall needs at least one embedding provider.",
gatewayProbeWarning ? gatewayProbeWarning : null, "", "Fix (pick one):",
`- Set ${formatMemoryProviderEnvVarList(autoSelectProviders)} in your environment`,
`- Configure credentials: ${formatCliCommand("openclaw configure --section model")}`,
`- For local embeddings: configure agents.defaults.memorySearch.provider and local model path`,
`- To disable: ${formatCliCommand("openclaw config set agents.defaults.memorySearch.enabled false")}`, "",
`Verify: ${formatCliCommand("openclaw memory status --deep")}`,
].join("\n"), "Memory search",
);
}
/** *Checkwhetherlocalembeddingsareavailable. * *When`useDefaultFallback`istrue(explicit`provider:"local"`),anempty *modelPathistreatedasavailablebecausetheruntimefallsbackto *DEFAULT_LOCAL_MODEL(anauto-downloadedHuggingFacemodel). * *Whenfalse(provider:"auto"),weonlyconsiderlocalavailableiftheuser *explicitlyconfiguredalocalfilepath—matching`canAutoSelectLocal()` *intheruntime,whichskipslocalforempty/hf:modelpaths.
*/ function hasLocalEmbeddings(local: { modelPath?: string }, useDefaultFallback = false): boolean { const modelPath =
normalizeOptionalString(local.modelPath) ||
(useDefaultFallback ? DEFAULT_LOCAL_MODEL : undefined); if (!modelPath) { returnfalse;
} // Remote/downloadable models (hf: or http:) aren't pre-resolved on disk, // so we can't confirm availability without a network call. Treat as // potentially available — the user configured it intentionally. if (/^(hf:|https?:)/i.test(modelPath)) { returntrue;
} const resolved = resolveUserPath(modelPath); try { return fsSync.statSync(resolved).isFile();
} catch { returnfalse;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.