"use client"; import { useActionState, useState } from "react"; import type { SiteSettings } from "yt-dlp-transcript-common/lib/settings"; // From the CLIENT-SAFE digest module, NOT settings.ts's re-exports of them: // settings.ts opens with `import fs from "node:fs"`, so pulling the option // lists through it drags node:fs into the client bundle and the page dies at // runtime. Same rule the digest modules are already split along. import { DEFAULT_DIGEST_TIMESTAMP_MODE, DIGEST_SECTION_KINDS as DIGEST_SECTION_OPTIONS, DIGEST_TIMESTAMP_MODES as DIGEST_TIMESTAMP_MODE_OPTIONS, } from "yt-dlp-transcript-common/lib/digest"; import type { DigestAppDescriptor } from "yt-dlp-transcript-common/lib/digestApps"; import { Field, SeededSelect } from "../../../components/forms/Field"; import { ControlledCheck } from "../../../components/forms/Controlled"; import { seedChecked } from "../../../lib/formState"; import { DigestAppsField } from "./DigestAppsField"; import { saveDigestSettingsAction } from "../../settingsActions"; import type { SaveResult } from "../../../settings/actions"; // The `digest` block of settings.json, on /operations/digest. Moved off // /settings by slice 3: an operation's settings belong on its operation page, // beside the state, the sweep and the pause an operator reads there. // // The legend and every field NAME are verbatim from the old fieldset — the // action reads those names and two e2e specs select by them. export function DigestSettingsForm({ initial, digestApps, }: { initial: SiteSettings["digest"]; digestApps: DigestAppDescriptor[]; }) { const [state, formAction, pending] = useActionState< SaveResult | undefined, FormData >(saveDigestSettingsAction, undefined); // THE ONE NAME POSTED MORE THAN ONCE in the editor's forms — a box per // section, all named `digestSections` — so a failed submit's `values` (each // name's first value) cannot say which were ticked. Controlled instead: // what the operator ticked lives here, and ControlledCheck keeps it through // the reset. The posted shape is unchanged. const [sections, setSections] = useState(() => [ ...initial.sections, ]); // AFTER A SUCCESS THE BOXES SHOW WHAT WAS STORED, as the uncontrolled boxes // did after their reset: unticking every box saves the stored list again, so // what was ticked is not always what was saved. Re-read on a new result or a // new stored list, unless the result is a failure (then the ticks stay). const stored = initial.sections.join(","); const [shown, setShown] = useState({ state, stored }); if (shown.state !== state || shown.stored !== stored) { setShown({ state, stored }); if (state?.ok !== false) setSections([...initial.sections]); } return (
Digest

AI chapters and topic tags generated from existing transcripts by a local model, written to ai-digest.json beside each one. Run a sweep from a channel's Digest stage. Every section records the exact engine, model, prompt version and prompt shape that produced it, and a re-run regenerates only what no longer matches — so changing anything here is what makes the next run redo work, and leaving it alone is what makes a re-run nearly free.

Per-engine configuration
{state?.ok === true && ( Saved. )} {state?.ok === false && ( {state.error} )}
); }