PageSourceSearch

https://loveacrossborders.com/assets/talkable-books.admin-DndvzwRx.js

js loveacrossborders.com collected 2026-10-08 14:16:55 UTC 5,859 bytes, 1 lines download raw bytes

1import{p as c,v as l,q as p,j as t,r as x,t as j}from"./index-hs4a0mYW.js";import{u as C}from"./useQuery-C-iGd3mh.js";import{u as i}from"./useServerFn-DgMZqDJQ.js";import{A as E}from"./AdminGate-Db1E1sSR.js";import"./useMutation-CsVV5qgy.js";import"./books.functions-BjM2fbuH.js";import"./SiteHeader-BqOOKgqK.js";const F=c({method:"GET"}).middleware([l]).handler(p("a6bd83af4bd54eea306916239d1558566bd423819279fba22221c5d4bcc070bd")),I=c({method:"POST"}).middleware([l]).handler(p("41cf6659b2d04735d9f816ce3ed5427af02b0cd4e19cbdcd01327176687d1564")),R=c({method:"POST"}).middleware([l]).handler(p("876b1c96fca6eb156e36bbd8295f6181ed19a2a0453cc950bf7ce0785a3198a9")),q=c({method:"POST"}).middleware([l]).handler(p("7f939643d01f5263328109334bdb631f17a332c6176754d19e015304255cffcf"));function A(){const k=i(F),N=i(I),$=i(R),S=i(q),{data:u,isLoading:v,refetch:g}=C({queryKey:["talkable","ingest-status"],queryFn:()=>k()}),[h,w]=x.useState([]),[r,f]=x.useState(null),a=x.useRef(!1),n=e=>w(s=>[`${e}`,...s].slice(0,200)),o=async(e,s)=>{if(!e.epub){n(`Skipped ${e.title}: no EPUB file attached to its product.`);return}f(e.id);try{const d=await N({data:{bookId:e.id,reset:s}});n(d.status==="skipped"?`${e.title}: already has ${d.chunks} passages, embedding what is left.`:`${e.title}: ${d.chapters} sections, ${d.chunks} passages.`);let y=0;for(;;){if(a.current){n("Stopped.");return}const b=await $({data:{bookId:e.id,limit:24}});if(b.done)break;if(n(`${e.title}: embedded ${b.embedded}, ${b.remaining} to go.`),y+=1,y>400){n(`${e.title}: stopped after 400 batches. Run it again to continue.`);return}}n(`${e.title}: ready.`);try{await S({data:{bookId:e.id}}),n(`${e.title}: opening questions written.`)}catch{n(`${e.title}: opening questions could not be generated, not fatal.`)}}catch(d){n(`${e.title}: FAILED. ${d instanceof Error?d.message:String(d)}`)}finally{f(null),g()}},B=async()=>{a.current=!1;const e=(u??[]).filter(s=>s.epub&&s.pending_embeddings+s.chunk_count===0);if(e.length===0){j.info("Nothing left to ingest.");return}n(`Starting ${e.length} book${e.length===1?"":"s"}.`);for(const s of e){if(a.current)break;await o(s,!1)}n("Run complete.")},P=async()=>{a.current=!1;const e=(u??[]).filter(s=>s.pending_embeddings>0);if(e.length===0){j.info("No pending embeddings.");return}for(const s of e){if(a.current)break;await o(s,!1)}n("Pending work complete.")},m=u??[],_=m.filter(e=>e.chunk_count>0&&e.pending_embeddings===0).length;return t.jsxs("div",{className:"space-y-8",children:[t.jsxs("header",{children:[t.jsx("h1",{className:"font-serif text-3xl",children:"Talkable Books ingestion"}),t.jsxs("p",{className:"mt-2 text-sm text-muted-foreground",children:["Each book reads its own EPUB, splits into passages, and stores an embedding per passage. Books with zero passages do not appear in the reading room. ",_," of ",m.length," are ready."]})]}),t.jsxs("div",{className:"flex flex-wrap gap-3",children:[t.jsx("button",{type:"button",onClick:B,disabled:!!r,className:"rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:opacity-90 disabled:opacity-60",children:"Ingest every un-ingested book"}),t.jsx("button",{type:"button",onClick:P,disabled:!!r,className:"rounded-md border border-border px-4 py-2 text-sm hover:bg-muted disabled:opacity-60",children:"Finish pending embeddings"}),t.jsx("button",{type:"button",onClick:()=>{a.current=!0},className:"rounded-md border border-border px-4 py-2 text-sm hover:bg-muted",children:"Stop after current book"}),t.jsx("button",{type:"button",onClick:()=>g(),className:"rounded-md border border-border px-4 py-2 text-sm hover:bg-muted",children:"Refresh"})]}),t.jsx("div",{className:"overflow-x-auto rounded-lg border border-border",children:t.jsxs("table",{className:"w-full text-sm",children:[t.jsx("thead",{className:"bg-muted/40 text-left text-xs uppercase tracking-widest text-muted-foreground",children:t.jsxs("tr",{children:[t.jsx("th",{className:"px-4 py-3",children:"Book"}),t.jsx("th",{className:"px-4 py-3",children:"EPUB"}),t.jsx("th",{className:"px-4 py-3",children:"Passages"}),t.jsx("th",{className:"px-4 py-3",children:"Pending"}),t.jsx("th",{className:"px-4 py-3",children:"State"}),t.jsx("th",{className:"px-4 py-3"})]})}),t.jsxs("tbody",{children:[v&&t.jsx("tr",{children:t.jsx("td",{className:"px-4 py-4 text-muted-foreground",colSpan:6,children:"Loading..."})}),m.map(e=>t.jsxs("tr",{className:"border-t border-border",children:[t.jsxs("td",{className:"px-4 py-3",children:[t.jsx("span",{className:"font-medium",children:e.title}),t.jsx("span",{className:"block text-xs text-muted-foreground",children:e.slug??"no slug"})]}),t.jsx("td",{className:"px-4 py-3 text-muted-foreground",children:e.epub?"yes":"missing"}),t.jsx("td",{className:"px-4 py-3",children:e.chunk_count}),t.jsx("td",{className:"px-4 py-3",children:e.pending_embeddings}),t.jsx("td",{className:"px-4 py-3 text-muted-foreground",children:e.chunk_count>0&&e.pending_embeddings===0?"ready":e.ingest_status||"new"}),t.jsxs("td",{className:"px-4 py-3 text-right",children:[t.jsx("button",{type:"button",onClick:()=>o(e,!1),disabled:!!r,className:"rounded border border-border px-3 py-1.5 text-xs hover:bg-muted disabled:opacity-60",children:r===e.id?"Working...":"Ingest"}),t.jsx("button",{type:"button",onClick:()=>
1o(e,!0),disabled:!!r,className:"ml-2 rounded border border-border px-3 py-1.5 text-xs hover:bg-muted disabled:opacity-60",children:"Re-ingest"})]})]},e.id))]})]})}),h.length>0&&t.jsxs("div",{className:"rounded-lg border border-border bg-card p-4",children:[t.jsx("h2",{className:"text-xs uppercase tracking-widest text-muted-foreground",children:"Run log"}),t.jsx("ul",{className:"mt-3 space-y-1 font-mono text-xs text-muted-foreground",children:h.map((e,s)=>t.jsx("li",{children:e},`${s}-${e}`))})]})]})}const K=()=>t.jsx(E,{children:t.jsx(A,{})});export{K as component};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.