96 lines
2.9 KiB
TypeScript
96 lines
2.9 KiB
TypeScript
import { mkdirSync, existsSync, copyFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { homedir } from 'node:os';
|
|
import { DATA_PATH, PI_CONFIG_DIR } from './data-path';
|
|
import { syncLocalProvidersToPiConfig } from './api/server-settings/sync-pi-config';
|
|
import { syncAllUserPiConfigs } from './api/server-settings/sync-user-pi-config';
|
|
import { initAuthStore } from 'officerdb';
|
|
import { syncSeedSkills } from './sync-skills';
|
|
import { syncSeedTools } from './sync-tools';
|
|
import { syncSeedExtensions } from './sync-extensions';
|
|
import { syncSeedResources } from './sync-resources';
|
|
import { migrateSettingsToResources } from './migrate-resources';
|
|
import { initQueue } from './queue';
|
|
|
|
mkdirSync(DATA_PATH, { recursive: true });
|
|
mkdirSync(PI_CONFIG_DIR, { recursive: true });
|
|
|
|
await initAuthStore();
|
|
|
|
async function ensurePiInstalled(): Promise<boolean> {
|
|
try {
|
|
const proc = Bun.spawn(['pi', '--version'], { stdout: 'pipe', stderr: 'pipe' });
|
|
await proc.exited;
|
|
return proc.exitCode === 0;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async function installPi(): Promise<boolean> {
|
|
console.log('[bootstrap] Pi not found, installing...');
|
|
try {
|
|
const proc = Bun.spawn(['npm', 'install', '-g', '@mariozechner/pi-coding-agent'], {
|
|
stdout: 'pipe',
|
|
stderr: 'pipe',
|
|
});
|
|
const stderr = await new Response(proc.stderr).text();
|
|
await proc.exited;
|
|
if (proc.exitCode !== 0) {
|
|
console.error('[bootstrap] Pi installation failed:', stderr.trim());
|
|
return false;
|
|
}
|
|
console.log('[bootstrap] Pi installed successfully');
|
|
return true;
|
|
} catch (err) {
|
|
console.error('[bootstrap] Pi installation error:', err);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function seedPiConfig(): void {
|
|
const hostPiDir = join(homedir(), '.pi', 'agent');
|
|
const filesToCopy = ['models.json', 'settings.json'];
|
|
|
|
for (const file of filesToCopy) {
|
|
const target = join(PI_CONFIG_DIR, file);
|
|
if (existsSync(target)) continue;
|
|
|
|
const source = join(hostPiDir, file);
|
|
if (existsSync(source)) {
|
|
copyFileSync(source, target);
|
|
console.log(`[bootstrap] Seeded ${file} from host Pi config`);
|
|
}
|
|
}
|
|
}
|
|
|
|
(async () => {
|
|
const installed = await ensurePiInstalled();
|
|
if (!installed) {
|
|
const ok = await installPi();
|
|
if (!ok) {
|
|
console.error('[bootstrap] Could not install Pi — model discovery will not work');
|
|
return;
|
|
}
|
|
}
|
|
|
|
seedPiConfig();
|
|
syncSeedSkills();
|
|
syncSeedTools();
|
|
syncSeedExtensions();
|
|
syncSeedResources();
|
|
migrateSettingsToResources();
|
|
|
|
await syncLocalProvidersToPiConfig().catch(err => {
|
|
console.error('[bootstrap] Failed to sync local providers to Pi config:', err);
|
|
});
|
|
|
|
await syncAllUserPiConfigs().catch(err => {
|
|
console.error('[bootstrap] Failed to sync user Pi configs:', err);
|
|
});
|
|
|
|
await initQueue().catch(err => {
|
|
console.error('[bootstrap] Failed to initialize queue:', err);
|
|
});
|
|
})();
|