feat: sync OpenRouter models on dashboard startup and add mission interview module

- Add openrouterModelSync setting to eagerly fetch OpenRouter model catalog at
  dashboard startup so the model picker shows all available models
- Add toggle in Settings → Models to disable the sync
- Add mission-interview session management module for AI-guided mission specs
- Include tests for the sync opt-out behavior

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-04 00:39:17 -07:00
parent 38a095cc25
commit e46d357a6a
6 changed files with 586 additions and 1 deletions

View File

@@ -16,6 +16,7 @@ function makeMockStore() {
maxWorktrees: 2,
autoMerge: false,
pollIntervalMs: 60_000,
openrouterModelSync: true,
}),
listTasks: vi.fn().mockResolvedValue([]),
on: vi.fn((event: string, handler: (...args: unknown[]) => void) => {
@@ -104,7 +105,7 @@ vi.mock("@fusion/engine", async (importOriginal) => {
// ── Mock @mariozechner/pi-coding-agent ──────────────────────────────
const mockAuthStorage = { getAuth: vi.fn(), setAuth: vi.fn() };
const mockAuthStorage = { getAuth: vi.fn(), setAuth: vi.fn(), getApiKey: vi.fn() };
const mockModelRegistry = {
getModels: vi.fn().mockResolvedValue([]),
registerProvider: vi.fn(),
@@ -252,4 +253,22 @@ describe("runDashboard — AuthStorage & ModelRegistry wiring", () => {
expect(mockModelRegistry.refresh).toHaveBeenCalled();
consoleSpy.mockRestore();
});
it("skips OpenRouter model sync when openrouterModelSync is false", async () => {
const { TaskStore } = await import("@fusion/core");
(TaskStore as unknown as ReturnType<typeof vi.fn>).mockImplementation(() => ({
...makeMockStore(),
getSettings: vi.fn().mockResolvedValue({
maxConcurrent: 1,
maxWorktrees: 2,
autoMerge: false,
pollIntervalMs: 60_000,
openrouterModelSync: false,
}),
}));
await runDashboard(0, {});
expect(mockAuthStorage.getApiKey).not.toHaveBeenCalled();
});
});