feat(KB-620): complete Step 7 — Migration and first-run experience

- Add fn init command for initializing new kb projects
- Add auto-migration check at CLI startup
- Add /api/setup-state and /api/complete-setup dashboard endpoints
- Add SetupState and CompleteSetupInput types to dashboard API
- Add migration and rollback documentation to AGENTS.md
- Create changeset for multi-project migration feature
This commit is contained in:
gsxdsm
2026-04-02 09:18:45 -07:00
parent b05fbb7ecb
commit c03c9602b4
1427 changed files with 230046 additions and 2 deletions

View File

@@ -6197,6 +6197,80 @@ Output ONLY the prompt text (no markdown, no explanations).`;
}
});
/**
* GET /api/setup-state
* Returns the first-run state and any detected projects for migration.
* This is used by the dashboard to determine what UI to show on startup.
*/
router.get("/setup-state", async (_req, res) => {
try {
const { FirstRunDetector } = await import("@fusion/core");
const { CentralCore } = await import("@fusion/core");
const detector = new FirstRunDetector();
const state = await detector.detectFirstRunState();
const detectedProjects = await detector.detectExistingProjects(process.cwd());
// Get central DB info
const central = new CentralCore();
await central.init();
const projects = await central.listProjects();
await central.close();
res.json({
state,
detectedProjects,
hasCentralDb: detector.hasCentralDb(),
registeredProjects: projects.map((p) => ({
id: p.id,
name: p.name,
path: p.path,
})),
});
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
/**
* POST /api/complete-setup
* Complete the first-run setup by registering projects.
* Body: { projects: Array<{ path: string, name: string, isolationMode?: "in-process" | "child-process" }> }
*/
router.post("/complete-setup", async (req, res) => {
try {
const { CentralCore } = await import("@fusion/core");
const { MigrationCoordinator } = await import("@fusion/core");
const { projects } = req.body as {
projects: Array<{ path: string; name: string; isolationMode?: "in-process" | "child-process" }>;
};
if (!Array.isArray(projects)) {
res.status(400).json({ error: "projects must be an array" });
return;
}
const central = new CentralCore();
await central.init();
try {
const coordinator = new MigrationCoordinator(central);
const result = await coordinator.completeSetup(projects);
res.json({
success: result.success,
projectsRegistered: result.projectsRegistered,
errors: result.errors,
});
} finally {
await central.close();
}
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
/**
* GET /api/tasks/:id/diff
* Fetch git diff for a task's changes.