feat: integrate Cortex local memory into OpenClaw

This commit is contained in:
Marc J Saint-jour 2026-03-12 18:41:17 -04:00
parent 1bc443aaa1
commit cbd861bc26

View File

@ -188,10 +188,7 @@ async function promptWebToolsConfig(
if (stored && SEARCH_PROVIDER_OPTIONS.some((e) => e.value === stored)) {
return stored;
}
return (
SEARCH_PROVIDER_OPTIONS.find((e) => hasKeyForProvider(e.value))?.value ??
SEARCH_PROVIDER_OPTIONS[0].value
);
return SEARCH_PROVIDER_OPTIONS.find((e) => hasKeyForProvider(e.value))?.value ?? "brave";
})();
note(
@ -303,6 +300,122 @@ async function promptWebToolsConfig(
};
}
async function promptCortexMemoryConfig(
nextConfig: OpenClawConfig,
runtime: RuntimeEnv,
workspaceDir: string,
): Promise<OpenClawConfig> {
const existing = nextConfig.agents?.defaults?.cortex;
const defaultGraphPath = nodePath.join(workspaceDir, ".cortex", "context.json");
const graphExists = await fsPromises
.access(defaultGraphPath)
.then(() => true)
.catch(() => false);
note(
[
"Cortex can prepend a filtered local memory graph into agent system prompts.",
`Default workspace graph: ${defaultGraphPath}`,
graphExists
? "A local Cortex graph was detected in this workspace."
: "No default Cortex graph was detected yet; you can still enable the bridge now.",
].join("\n"),
"Cortex memory",
);
const enable = guardCancel(
await confirm({
message: "Enable Cortex prompt bridge?",
initialValue: existing?.enabled ?? graphExists,
}),
runtime,
);
if (!enable) {
return {
...nextConfig,
agents: {
...nextConfig.agents,
defaults: {
...nextConfig.agents?.defaults,
cortex: {
...existing,
enabled: false,
},
},
},
};
}
const mode = guardCancel(
await select({
message: "Cortex prompt mode",
options: [
{ value: "technical", label: "Technical", hint: "Project and coding context" },
{ value: "professional", label: "Professional", hint: "Work-safe context slice" },
{ value: "minimal", label: "Minimal", hint: "Smallest safe context" },
{ value: "full", label: "Full", hint: "Largest context slice" },
],
initialValue: existing?.mode ?? "technical",
}),
runtime,
) as NonNullable<NonNullable<OpenClawConfig["agents"]>["defaults"]>["cortex"]["mode"];
const maxCharsInput = guardCancel(
await text({
message: "Cortex max prompt chars",
initialValue: String(existing?.maxChars ?? 1500),
validate: (value) => {
const parsed = Number.parseInt(String(value), 10);
if (!Number.isFinite(parsed) || parsed <= 0) {
return "Enter a positive integer";
}
return undefined;
},
}),
runtime,
);
const maxChars = Number.parseInt(String(maxCharsInput), 10);
const useDefaultGraph = guardCancel(
await confirm({
message: "Use the default workspace Cortex graph path?",
initialValue: !existing?.graphPath,
}),
runtime,
);
let graphPath: string | undefined;
if (!useDefaultGraph) {
const graphInput = guardCancel(
await text({
message: "Cortex graph path",
initialValue: existing?.graphPath ?? defaultGraphPath,
}),
runtime,
);
const trimmed = String(graphInput ?? "").trim();
graphPath = trimmed || defaultGraphPath;
}
return {
...nextConfig,
agents: {
...nextConfig.agents,
defaults: {
...nextConfig.agents?.defaults,
cortex: {
...existing,
enabled: true,
mode,
maxChars,
...(graphPath ? { graphPath } : {}),
},
},
},
};
}
export async function runConfigureWizard(
opts: ConfigureWizardParams,
runtime: RuntimeEnv = defaultRuntime,
@ -530,6 +643,10 @@ export async function runConfigureWizard(
nextConfig = await promptWebToolsConfig(nextConfig, runtime);
}
if (selected.includes("memory")) {
nextConfig = await promptCortexMemoryConfig(nextConfig, runtime, workspaceDir);
}
if (selected.includes("gateway")) {
const gateway = await promptGatewayConfig(nextConfig, runtime);
nextConfig = gateway.config;
@ -584,6 +701,11 @@ export async function runConfigureWizard(
await persistConfig();
}
if (choice === "memory") {
nextConfig = await promptCortexMemoryConfig(nextConfig, runtime, workspaceDir);
await persistConfig();
}
if (choice === "gateway") {
const gateway = await promptGatewayConfig(nextConfig, runtime);
nextConfig = gateway.config;