feat(memfs): flatten directory structure - detached blocks at root (#743)
Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
@@ -48,9 +48,9 @@ const MEMORY_FS_STATE_FILE = ".sync-state.json";
|
||||
type SyncState = {
|
||||
systemBlocks: Record<string, string>;
|
||||
systemFiles: Record<string, string>;
|
||||
userBlocks: Record<string, string>;
|
||||
userFiles: Record<string, string>;
|
||||
userBlockIds: Record<string, string>;
|
||||
detachedBlocks: Record<string, string>;
|
||||
detachedFiles: Record<string, string>;
|
||||
detachedBlockIds: Record<string, string>;
|
||||
lastSync: string | null;
|
||||
};
|
||||
|
||||
@@ -68,9 +68,9 @@ function loadSyncState(agentId: string): SyncState {
|
||||
return {
|
||||
systemBlocks: {},
|
||||
systemFiles: {},
|
||||
userBlocks: {},
|
||||
userFiles: {},
|
||||
userBlockIds: {},
|
||||
detachedBlocks: {},
|
||||
detachedFiles: {},
|
||||
detachedBlockIds: {},
|
||||
lastSync: null,
|
||||
};
|
||||
}
|
||||
@@ -84,18 +84,18 @@ function loadSyncState(agentId: string): SyncState {
|
||||
return {
|
||||
systemBlocks: parsed.systemBlocks || parsed.blocks || {},
|
||||
systemFiles: parsed.systemFiles || parsed.files || {},
|
||||
userBlocks: parsed.userBlocks || {},
|
||||
userFiles: parsed.userFiles || {},
|
||||
userBlockIds: parsed.userBlockIds || {},
|
||||
detachedBlocks: parsed.detachedBlocks || {},
|
||||
detachedFiles: parsed.detachedFiles || {},
|
||||
detachedBlockIds: parsed.detachedBlockIds || {},
|
||||
lastSync: parsed.lastSync || null,
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
systemBlocks: {},
|
||||
systemFiles: {},
|
||||
userBlocks: {},
|
||||
userFiles: {},
|
||||
userBlockIds: {},
|
||||
detachedBlocks: {},
|
||||
detachedFiles: {},
|
||||
detachedBlockIds: {},
|
||||
lastSync: null,
|
||||
};
|
||||
}
|
||||
@@ -166,14 +166,15 @@ async function findConflicts(agentId: string): Promise<Conflict[]> {
|
||||
|
||||
const root = getMemoryRoot(agentId);
|
||||
const systemDir = join(root, "system");
|
||||
const userDir = join(root, "user");
|
||||
// Detached files go at root level (flat structure)
|
||||
const detachedDir = root;
|
||||
|
||||
for (const dir of [root, systemDir, userDir]) {
|
||||
for (const dir of [root, systemDir]) {
|
||||
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
const systemFiles = await readMemoryFiles(systemDir);
|
||||
const userFiles = await readMemoryFiles(userDir);
|
||||
const detachedFiles = await readMemoryFiles(detachedDir);
|
||||
systemFiles.delete("memory_filesystem");
|
||||
|
||||
const blocksResponse = await client.agents.blocks.list(agentId, {
|
||||
@@ -198,11 +199,11 @@ async function findConflicts(agentId: string): Promise<Conflict[]> {
|
||||
|
||||
const lastState = loadSyncState(agentId);
|
||||
|
||||
const userBlockMap = new Map<string, string>();
|
||||
for (const [label, blockId] of Object.entries(lastState.userBlockIds)) {
|
||||
const detachedBlockMap = new Map<string, string>();
|
||||
for (const [label, blockId] of Object.entries(lastState.detachedBlockIds)) {
|
||||
try {
|
||||
const block = await client.blocks.retrieve(blockId);
|
||||
userBlockMap.set(label, block.value || "");
|
||||
detachedBlockMap.set(label, block.value || "");
|
||||
} catch {
|
||||
// Block no longer exists
|
||||
}
|
||||
@@ -249,19 +250,19 @@ async function findConflicts(agentId: string): Promise<Conflict[]> {
|
||||
|
||||
// Check user labels
|
||||
const userLabels = new Set([
|
||||
...userFiles.keys(),
|
||||
...userBlockMap.keys(),
|
||||
...Object.keys(lastState.userBlocks),
|
||||
...Object.keys(lastState.userFiles),
|
||||
...detachedFiles.keys(),
|
||||
...detachedBlockMap.keys(),
|
||||
...Object.keys(lastState.detachedBlocks),
|
||||
...Object.keys(lastState.detachedFiles),
|
||||
]);
|
||||
|
||||
for (const label of [...userLabels].sort()) {
|
||||
checkConflict(
|
||||
label,
|
||||
userFiles.get(label)?.content ?? null,
|
||||
userBlockMap.get(label) ?? null,
|
||||
lastState.userFiles[label] ?? null,
|
||||
lastState.userBlocks[label] ?? null,
|
||||
detachedFiles.get(label)?.content ?? null,
|
||||
detachedBlockMap.get(label) ?? null,
|
||||
lastState.detachedFiles[label] ?? null,
|
||||
lastState.detachedBlocks[label] ?? null,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user