All checks were successful
Release / Test backend (push) Successful in 40s
Release / Check ui (push) Successful in 1m36s
Release / Docker / caddy (push) Successful in 45s
Release / Docker / backend (push) Successful in 4m27s
Release / Docker / runner (push) Successful in 3m32s
Release / Upload source maps (push) Successful in 44s
Release / Docker / ui (push) Successful in 2m46s
Release / Gitea Release (push) Successful in 58s
- Add /admin/ai-jobs page with live-polling jobs table, status badges, progress bars, and cancel action - Add listAIJobs() helper in pocketbase.ts; AIJob type - Add POST /api/admin/ai-jobs/[id]/cancel SvelteKit proxy - Add ai-jobs link to admin sidebar nav (all 5 locales) - Cache image-gen and text-gen model lists in Valkey (10 min TTL) via scraper.ts helpers - Cache changelog Gitea API response (5 min TTL) - Improve 502/504 error message on image-gen page with CF AI timeout hint - Show CF AI timeout warning in advanced options when a Cloudflare/FLUX model is selected
43 lines
1.1 KiB
TypeScript
43 lines
1.1 KiB
TypeScript
import type { PageServerLoad } from './$types';
|
|
import { listImageModels } from '$lib/server/scraper';
|
|
import { log } from '$lib/server/logger';
|
|
import { listBooks } from '$lib/server/pocketbase';
|
|
|
|
export interface ImageModelInfo {
|
|
id: string;
|
|
label: string;
|
|
provider: string;
|
|
supports_ref: boolean;
|
|
recommended_for: string[]; // "cover" | "chapter"
|
|
description: string;
|
|
}
|
|
|
|
export interface BookSummary {
|
|
slug: string;
|
|
title: string;
|
|
summary: string;
|
|
cover: string;
|
|
}
|
|
|
|
export const load: PageServerLoad = async () => {
|
|
// parent layout already guards admin role
|
|
const [models, booksResult] = await Promise.allSettled([
|
|
listImageModels<ImageModelInfo>(),
|
|
listBooks()
|
|
]);
|
|
|
|
if (models.status === 'rejected') {
|
|
log.warn('admin/image-gen', 'failed to load models', { err: String(models.reason) });
|
|
}
|
|
|
|
return {
|
|
models: models.status === 'fulfilled' ? models.value : ([] as ImageModelInfo[]),
|
|
books: (booksResult.status === 'fulfilled' ? booksResult.value : []).map((b) => ({
|
|
slug: b.slug,
|
|
title: b.title,
|
|
summary: b.summary ?? '',
|
|
cover: b.cover ?? ''
|
|
})) as BookSummary[]
|
|
};
|
|
};
|