This commit is contained in:
seb
2026-10-07 20:36:50 +02:00
parent 857963b1c3
commit a29ad50b74
18 changed files with 1024 additions and 220 deletions

View File

@@ -126,7 +126,7 @@ async function vfsRootFor(store, googleAuthId) {
}
/**
* Loads default SKILL files into the selected company's VFS (both modelvfs table and disk cache).
* Loads default SKILL files into the selected company's on-disk VFS.
*
* @param {{ googleAuthId: number, store?: object, vfsRoot?: string }} ctx
* @returns {Promise<Array<string>>} List of loaded skill file names
@@ -140,19 +140,12 @@ export async function loadDefaultSkills({ googleAuthId, store: passedStore, vfsR
const loaded = [];
for (const skill of defaultSkills) {
try {
await store.modelvfs.write(googleAuthId, {
name: skill.name,
mime: 'text/markdown',
content: Buffer.from(skill.content, 'utf8'),
});
} catch (err) {
console.error(`[vfs] failed to write default skill "${skill.name}" to modelvfs:`, err.message);
}
try {
const diskPath = path.resolve(vfsRoot, skill.name);
fs.writeFileSync(diskPath, skill.content, 'utf8');
if (!fs.existsSync(diskPath)) {
fs.mkdirSync(path.dirname(diskPath), { recursive: true });
fs.writeFileSync(diskPath, skill.content, 'utf8');
}
loaded.push(skill.name);
} catch (err) {
console.error(`[vfs] failed to write default skill "${skill.name}" to disk:`, err.message);
@@ -178,7 +171,7 @@ export async function initCompanyVfs({ googleAuthId, store: passedStore, vfsRoot
}
/**
* Ensure the local directory for this company's VFS exists and is hydrated from modelvfs.
* Ensure the local directory for this company's VFS exists and default skills are loaded.
*
* @param {{ googleAuthId: number }} ctx
* @returns {Promise<string>} vfsRoot directory path
@@ -189,86 +182,21 @@ export async function prepareVfs({ googleAuthId }) {
fs.mkdirSync(vfsRoot, { recursive: true });
try {
const files = await store.modelvfs.list(googleAuthId);
const existingNames = new Set(files.map((f) => f.name));
const defaultSkills = getDefaultSkills();
for (const skill of defaultSkills) {
if (!existingNames.has(skill.name)) {
try {
await store.modelvfs.write(googleAuthId, {
name: skill.name,
mime: 'text/markdown',
content: Buffer.from(skill.content, 'utf8'),
});
files.push({ name: skill.name });
existingNames.add(skill.name);
} catch (err) {
console.warn(`[vfs] failed to write default skill "${skill.name}" to modelvfs:`, err.message);
}
}
}
for (const file of files) {
const diskPath = path.resolve(vfsRoot, file.name);
if (!diskPath.startsWith(vfsRoot)) continue;
if (!fs.existsSync(diskPath)) {
fs.mkdirSync(path.dirname(diskPath), { recursive: true });
const fullRecord = await store.modelvfs.read(googleAuthId, file.name);
if (fullRecord?.content) {
fs.writeFileSync(diskPath, fullRecord.content);
}
}
}
await loadDefaultSkills({ googleAuthId, store, vfsRoot });
} catch (err) {
console.warn('[vfs] hydration warning:', err.message);
console.warn('[vfs] prepare warning:', err.message);
}
return vfsRoot;
}
/**
* Syncs any modified or newly written files from the disk vfsRoot back to the modelvfs table.
* Purely disk-based VFS; no database syncing needed. Kept as no-op for backward compatibility.
*
* The store re-scopes by the currently selected company on every call, so this only stays
* correct while `vfsRoot` was produced by `prepareVfs`/`resolveVfsRoot` in the same turn.
*
* @param {{ googleAuthId: number, vfsRoot: string }} ctx
* @param {{ googleAuthId?: number, vfsRoot?: string }} [ctx]
*/
export async function syncVfsToDb({ googleAuthId, vfsRoot }) {
if (!fs.existsSync(vfsRoot)) return;
const store = await getStore();
function walk(dir, rel = '') {
const entries = fs.readdirSync(dir, { withFileTypes: true });
const list = [];
for (const e of entries) {
const relPath = rel ? `${rel}/${e.name}` : e.name;
const fullPath = path.join(dir, e.name);
if (e.isDirectory()) {
list.push(...walk(fullPath, relPath));
} else if (e.isFile()) {
list.push({ relPath, fullPath });
}
}
return list;
}
const currentFiles = walk(vfsRoot);
for (const f of currentFiles) {
if (isReadOnlyDatabasePath(f.relPath)) continue;
try {
const content = fs.readFileSync(f.fullPath);
const mime = getMimeType(f.relPath);
await store.modelvfs.write(googleAuthId, {
name: f.relPath,
mime,
content,
});
} catch (err) {
console.error(`[vfs] failed to sync file ${f.relPath} to db:`, err.message);
}
}
export async function syncVfsToDb({ googleAuthId, vfsRoot } = {}) {
// Purely disk-based VFS; no database syncing.
}
/**