fix: add missing memfs init steps in headless mode + refactor (#941)

Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
Devansh Jain
2026-02-12 17:33:51 -08:00
committed by GitHub
parent 5a696e6116
commit 36c21939a9
4 changed files with 112 additions and 113 deletions

View File

@@ -2,7 +2,9 @@
* Memory filesystem helpers.
*
* With git-backed memory, most sync/hash logic is removed.
* This module retains: directory helpers and tree rendering.
* This module retains: directory helpers, tree rendering, and
* the shared memfs initialization logic used by both interactive
* and headless code paths.
*/
import { existsSync, mkdirSync } from "node:fs";
@@ -129,3 +131,87 @@ export function renderMemoryFilesystemTree(
return lines.join("\n");
}
// ----- Shared memfs initialization -----
export interface ApplyMemfsFlagsResult {
/** Whether memfs was enabled, disabled, or unchanged */
action: "enabled" | "disabled" | "unchanged";
/** Path to the memory directory (when enabled) */
memoryDir?: string;
/** Summary from git pull (when pullOnExistingRepo is true and repo already existed) */
pullSummary?: string;
}
/**
* Apply --memfs / --no-memfs CLI flags (or /memfs enable) to an agent.
*
* Shared between interactive (index.ts), headless (headless.ts), and
* the /memfs enable command (App.tsx) to avoid duplicating the setup logic.
*
* Steps when enabling:
* 1. Validate Letta Cloud requirement
* 2. Persist memfs setting
* 3. Detach old API-based memory tools
* 4. Update system prompt to include memfs section
* 5. Add git-memory-enabled tag + clone/pull repo
*
* @throws {Error} if Letta Cloud validation fails or git setup fails
*/
export async function applyMemfsFlags(
agentId: string,
memfsFlag: boolean | undefined,
noMemfsFlag: boolean | undefined,
options?: { pullOnExistingRepo?: boolean },
): Promise<ApplyMemfsFlagsResult> {
const { getServerUrl } = await import("./client");
const { settingsManager } = await import("../settings-manager");
// 1. Validate + persist setting
if (memfsFlag) {
const serverUrl = getServerUrl();
if (!serverUrl.includes("api.letta.com")) {
throw new Error(
"--memfs is only available on Letta Cloud (api.letta.com).",
);
}
settingsManager.setMemfsEnabled(agentId, true);
} else if (noMemfsFlag) {
settingsManager.setMemfsEnabled(agentId, false);
}
const isEnabled = settingsManager.isMemfsEnabled(agentId);
// 2. Detach old API-based memory tools when enabling
if (isEnabled && memfsFlag) {
const { detachMemoryTools } = await import("../tools/toolset");
await detachMemoryTools(agentId);
}
// 3. Update system prompt to include/exclude memfs section
if (memfsFlag || noMemfsFlag) {
const { updateAgentSystemPromptMemfs } = await import("./modify");
await updateAgentSystemPromptMemfs(agentId, isEnabled);
}
// 4. Add git tag + clone/pull repo
let pullSummary: string | undefined;
if (isEnabled) {
const { addGitMemoryTag, isGitRepo, cloneMemoryRepo, pullMemory } =
await import("./memoryGit");
await addGitMemoryTag(agentId);
if (!isGitRepo(agentId)) {
await cloneMemoryRepo(agentId);
} else if (options?.pullOnExistingRepo) {
const result = await pullMemory(agentId);
pullSummary = result.summary;
}
}
const action = memfsFlag ? "enabled" : noMemfsFlag ? "disabled" : "unchanged";
return {
action,
memoryDir: isEnabled ? getMemoryFilesystemRoot(agentId) : undefined,
pullSummary,
};
}