@fs/mycroft 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/batch-embedder-6IIWAZPW.js +14 -0
- package/dist/batch-embedder-6IIWAZPW.js.map +1 -0
- package/dist/batch-embedder-7DGZAQKL.js +14 -0
- package/dist/batch-embedder-7DGZAQKL.js.map +1 -0
- package/dist/batch-embedder-IZDBS3IL.js +13 -0
- package/dist/batch-embedder-IZDBS3IL.js.map +1 -0
- package/dist/batch-embedder-LYCZDYI4.js +15 -0
- package/dist/batch-embedder-LYCZDYI4.js.map +1 -0
- package/dist/batch-embedder-RHKD2OJD.js +14 -0
- package/dist/batch-embedder-RHKD2OJD.js.map +1 -0
- package/dist/batch-embedder-VQZUI7R6.js +14 -0
- package/dist/batch-embedder-VQZUI7R6.js.map +1 -0
- package/dist/batch-embedder-ZJZLNLOK.js +14 -0
- package/dist/batch-embedder-ZJZLNLOK.js.map +1 -0
- package/dist/batch-summarizer-7MCT4HJB.js +14 -0
- package/dist/batch-summarizer-7MCT4HJB.js.map +1 -0
- package/dist/batch-summarizer-BMIBVFAE.js +14 -0
- package/dist/batch-summarizer-BMIBVFAE.js.map +1 -0
- package/dist/chunk-35EO53CC.js +8058 -0
- package/dist/chunk-35EO53CC.js.map +1 -0
- package/dist/chunk-57ZGGKEF.js +8060 -0
- package/dist/chunk-57ZGGKEF.js.map +1 -0
- package/dist/chunk-6DLQHHCC.js +249 -0
- package/dist/chunk-6DLQHHCC.js.map +1 -0
- package/dist/chunk-7CO4PMU5.js +92 -0
- package/dist/chunk-7CO4PMU5.js.map +1 -0
- package/dist/chunk-7DUQNGEK.js +253 -0
- package/dist/chunk-7DUQNGEK.js.map +1 -0
- package/dist/chunk-7IPX4MKA.js +4637 -0
- package/dist/chunk-7IPX4MKA.js.map +1 -0
- package/dist/chunk-7NLMBXXY.js +6438 -0
- package/dist/chunk-7NLMBXXY.js.map +1 -0
- package/dist/chunk-BR2PM6D3.js +11047 -0
- package/dist/chunk-BR2PM6D3.js.map +1 -0
- package/dist/chunk-KGG7WEYE.js +162 -0
- package/dist/chunk-KGG7WEYE.js.map +1 -0
- package/dist/chunk-QRDUQX63.js +256 -0
- package/dist/chunk-QRDUQX63.js.map +1 -0
- package/dist/chunk-R3FOJK5A.js +2088 -0
- package/dist/chunk-R3FOJK5A.js.map +1 -0
- package/dist/chunk-XXO66RCF.js +94 -0
- package/dist/chunk-XXO66RCF.js.map +1 -0
- package/dist/cli.js +638 -179
- package/dist/cli.js.map +1 -1
- package/dist/fileFromPath-FLANAQWT.js +128 -0
- package/dist/fileFromPath-FLANAQWT.js.map +1 -0
- package/dist/main-36PRDAPE.js +1857 -0
- package/dist/main-36PRDAPE.js.map +1 -0
- package/dist/main-B3QJZGLU.js +1859 -0
- package/dist/main-B3QJZGLU.js.map +1 -0
- package/package.json +7 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/main.ts","../src/services/epub-parser.ts","../src/services/ingest.ts","../src/services/chunker.ts","../src/services/embedder.ts","../src/services/vector-store.ts","../src/services/summarizer.ts","../src/db/queries.ts","../src/db/schema.ts","../src/commands/ingest.ts","../src/commands/prompt.ts","../src/commands/book/ingest.ts","../src/commands/list.ts","../src/commands/book/list.ts","../src/commands/utils.ts","../src/commands/show.ts","../src/commands/book/show.ts","../src/commands/ask.ts","../src/commands/query-options.ts","../src/commands/book/ask.ts","../src/commands/search.ts","../src/commands/book/search.ts","../src/commands/delete.ts","../src/commands/book/delete.ts","../src/commands/resume.ts","../src/commands/book/resume.ts","../src/commands/config.ts","../src/commands/config/path.ts","../src/commands/init-config.ts","../src/commands/config/init.ts","../src/commands/resolve-config.ts","../src/commands/config/resolve.ts","../src/commands/onboard.ts","../src/commands/config/onboard.ts","../src/services/chat.ts","../src/commands/chat/start.ts","../src/commands/chat/utils.ts","../src/commands/chat/ask.ts","../src/commands/chat/list.ts","../src/commands/chat/show.ts","../src/commands/chat/repl.ts","../src/commands/chat/index.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { setConfigOverrides } from \"./config.js\";\nimport { printError } from \"./commands/io.js\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { registerBookIngest } from \"./commands/book/ingest.js\";\nimport { registerBookList } from \"./commands/book/list.js\";\nimport { registerBookShow } from \"./commands/book/show.js\";\nimport { registerBookAsk } from \"./commands/book/ask.js\";\nimport { registerBookSearch } from \"./commands/book/search.js\";\nimport { registerBookDelete } from \"./commands/book/delete.js\";\nimport { registerBookResume } from \"./commands/book/resume.js\";\nimport { registerConfigPath } from \"./commands/config/path.js\";\nimport { registerConfigInit } from \"./commands/config/init.js\";\nimport { registerConfigResolve } from \"./commands/config/resolve.js\";\nimport { registerConfigOnboard } from \"./commands/config/onboard.js\";\nimport { registerChatCommands } from \"./commands/chat/index.js\";\n\nconst resolveVersion = async () => {\n try {\n const currentDir = dirname(fileURLToPath(import.meta.url));\n const pkgPath = resolve(currentDir, \"../package.json\");\n const raw = await readFile(pkgPath, \"utf-8\");\n return JSON.parse(raw).version || \"0.1.0\";\n } catch {\n return \"0.1.0\";\n }\n};\n\nconst program = new Command();\nconst configureProgram = async () => {\n program\n .name(\"mycroft\")\n .description(\"Ingest EPUBs, build a local index, and answer questions\")\n .version(await resolveVersion())\n .option(\"--data-dir <path>\", \"Override data directory\")\n .hook(\"preAction\", (cmd) => {\n const opts = cmd.opts();\n if (opts.dataDir) {\n setConfigOverrides({ dataDir: opts.dataDir });\n }\n });\n};\n\nconst registerCommands = () => {\n const book = program.command(\"book\").description(\"Manage books and queries\");\n const ingest = registerBookIngest(book);\n registerBookList(book);\n registerBookShow(book);\n registerBookAsk(book);\n registerBookSearch(book);\n registerBookDelete(book);\n registerBookResume(book, ingest);\n\n const config = program.command(\"config\").description(\"Manage configuration\");\n registerConfigPath(config);\n registerConfigInit(config);\n registerConfigResolve(config);\n registerConfigOnboard(config);\n\n registerChatCommands(program);\n};\n\nprogram.exitOverride((error) => {\n if (error.code === \"commander.helpDisplayed\") {\n process.exit(0);\n }\n throw error;\n});\n\nexport const main = async () => {\n try {\n await configureProgram();\n registerCommands();\n await program.parseAsync(process.argv);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n printError(message);\n process.exit(1);\n }\n};\n","import { initEpubFile } from \"@lingo-reader/epub-parser\";\nimport { basename } from \"node:path\";\nimport type { Chapter } from \"../shared/types.js\";\nimport { logInfo } from \"./constants.js\";\n\nexport type ParsedBook = {\n title: string;\n author: string | null;\n coverImagePath: string | null;\n chapters: Chapter[];\n chapterTitles: string[];\n narrativeStartIndex: number;\n narrativeEndIndex: number;\n};\n\nconst detectNarrativeBoundaries = (chapterTitles: string[]): { start: number; end: number } => {\n const frontMatterPattern = /^(about|contents|table of contents|dedication|preface|foreword|title|half.?title|copyright|epigraph|frontispiece|map)/i;\n const backMatterPattern = /^(acknowledgment|afterword|appendix|glossary|index|bibliography|about the author|also by|praise|copyright page|notes|bonus|preview|excerpt|major characters|locations)/i;\n const narrativePattern = /^(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|1|2|3|4|5|6|7|8|9|one|two|three|chapter|prologue|epilogue|part\\s)/i;\n\n let start = 0;\n let end = chapterTitles.length - 1;\n\n for (let i = 0; i < chapterTitles.length; i++) {\n const title = chapterTitles[i]?.trim() || \"\";\n\n if (narrativePattern.test(title) && !frontMatterPattern.test(title)) {\n start = i;\n break;\n }\n\n if (!frontMatterPattern.test(title) && title.length > 0) {\n if (title.length > 3) {\n start = i;\n break;\n }\n }\n }\n\n for (let i = chapterTitles.length - 1; i >= start; i--) {\n const title = chapterTitles[i]?.trim() || \"\";\n if (!backMatterPattern.test(title)) {\n end = i;\n break;\n }\n }\n\n logInfo(`[EPUB Parser] Detected narrative boundaries: chapters ${start} to ${end} (out of ${chapterTitles.length} total)`);\n if (start > 0) {\n logInfo(`[EPUB Parser] Front matter: ${chapterTitles.slice(0, start).join(\", \")}`);\n }\n if (end < chapterTitles.length - 1) {\n logInfo(`[EPUB Parser] Back matter: ${chapterTitles.slice(end + 1).join(\", \")}`);\n }\n\n return { start, end };\n};\n\nconst stripHtml = (html: string) =>\n html\n .replace(/<script[\\s\\S]*?<\\/script>/gi, \" \")\n .replace(/<style[\\s\\S]*?<\\/style>/gi, \" \")\n .replace(/<[^>]+>/g, \" \")\n .replace(/ /g, \" \")\n .replace(/&/g, \"&\")\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/\\s+/g, \" \")\n .trim();\n\nconst originalWarn = console.warn;\nconst createWarnFilter = () => {\n const suppressedWarnings: string[] = [];\n console.warn = (msg: any, ...args: unknown[]) => {\n if (typeof msg === \"string\" && msg.includes(\"No element with id\") && msg.includes(\"parsing <metadata>\")) {\n suppressedWarnings.push(msg);\n return;\n }\n originalWarn(msg, ...args);\n };\n return suppressedWarnings;\n};\n\nexport const parseEpub = async (epubPath: string, resourceSaveDir?: string): Promise<ParsedBook> => {\n logInfo(`[EPUB Parser] Starting parse for: ${basename(epubPath)}`);\n\n const suppressedWarnings = createWarnFilter();\n\n try {\n const epubFile = await initEpubFile(epubPath, resourceSaveDir);\n await epubFile.loadEpub();\n logInfo(`[EPUB Parser] EPUB loaded successfully`);\n\n await epubFile.parse();\n\n if (suppressedWarnings.length > 0) {\n logInfo(`[EPUB Parser] Suppressed ${suppressedWarnings.length} metadata warnings (non-critical)`);\n }\n logInfo(`[EPUB Parser] Parse completed`);\n\n const fileBaseName = basename(epubPath, \".epub\");\n type EpubMetadata = ReturnType<typeof epubFile.getMetadata>;\n let metadata: EpubMetadata | null = null;\n try {\n metadata = epubFile.getMetadata();\n } catch {\n metadata = null;\n }\n const safeMetadata = metadata ?? ({} as EpubMetadata);\n const spine = epubFile.getSpine();\n const toc = epubFile.getToc();\n\n logInfo(`[EPUB Parser] Found ${spine.length} spine items, ${toc.length} TOC entries`);\n\n const titleById = new Map<string, string>();\n const walkToc = (items: typeof toc) => {\n items.forEach((item: (typeof toc)[number]) => {\n const resolved = epubFile.resolveHref(item.href);\n if (resolved?.id) titleById.set(resolved.id, item.label);\n if (item.children?.length) walkToc(item.children);\n });\n };\n walkToc(toc);\n const coverImagePath = epubFile.getCoverImage() || null;\n\n const chapters: Chapter[] = [];\n const chapterTitles: string[] = [];\n for (const [index, item] of spine.entries()) {\n const chapter = await epubFile.loadChapter(item.id);\n const content = stripHtml(chapter.html);\n if (!content) continue;\n const chapterTitle = titleById.get(item.id) || item.id || `Chapter ${index + 1}`;\n chapters.push({\n title: chapterTitle,\n content,\n });\n chapterTitles.push(chapterTitle);\n }\n\n epubFile.destroy();\n\n const author = safeMetadata.creator?.[0]?.contributor ?? null;\n\n logInfo(`[EPUB Parser] Extracted ${chapters.length} chapters with content`);\n logInfo(`[EPUB Parser] Title: \"${safeMetadata.title || fileBaseName || \"Untitled\"}\", Author: \"${author || \"Unknown\"}\"`);\n\n const { start: narrativeStartIndex, end: narrativeEndIndex } = detectNarrativeBoundaries(chapterTitles);\n\n return {\n title: safeMetadata.title || fileBaseName || \"Untitled\",\n author,\n coverImagePath,\n chapters,\n chapterTitles,\n narrativeStartIndex,\n narrativeEndIndex,\n };\n } finally {\n console.warn = originalWarn;\n }\n};\n","import { randomUUID } from \"node:crypto\";\nimport { mkdir, unlink, copyFile, readFile, writeFile } from \"node:fs/promises\";\nimport { parseEpub } from \"./epub-parser.js\";\nimport { chunkChapters } from \"./chunker.js\";\nimport { embedChunks } from \"./embedder.js\";\nimport { submitBatchEmbeddings } from \"./batch-embedder.js\";\nimport { addChunksToIndex, deleteBookIndex } from \"./vector-store.js\";\nimport { summarizeAllChapters } from \"./summarizer.js\";\nimport { ensureDataDirs, logInfo, logWarn } from \"./constants.js\";\nimport { deleteBook, insertBook, updateBook } from \"../db/queries.js\";\nimport type { BookChunk } from \"../shared/types.js\";\nimport type { EmbeddedChunk } from \"./embedder.js\";\n\ntype ResumeState = {\n chunks: BookChunk[];\n resumeIndex: number;\n};\n\nconst resumePathForBook = async (bookId: string) => {\n const paths = await ensureDataDirs();\n return `${paths.ingestDir}/${bookId}.json`;\n};\n\nconst loadResumeState = async (bookId: string, resumePath: string): Promise<ResumeState> => {\n const raw = await readFile(resumePath, \"utf-8\");\n const parsed = JSON.parse(raw) as ResumeState;\n if (!Array.isArray(parsed.chunks) || typeof parsed.resumeIndex !== \"number\") {\n throw new Error(`Invalid resume state for book ${bookId}. Re-ingest to start over.`);\n }\n return parsed;\n};\n\nconst persistResumeState = async (bookId: string, state: ResumeState) => {\n const resumePath = await resumePathForBook(bookId);\n await writeFile(resumePath, JSON.stringify(state));\n await updateBook(bookId, {\n ingestState: \"pending\",\n ingestResumePath: resumePath,\n });\n return resumePath;\n};\n\nconst finalizeResumeState = async (bookId: string, resumePath?: string | null) => {\n const path = resumePath || (await resumePathForBook(bookId));\n await unlink(path).catch(() => undefined);\n await updateBook(bookId, { ingestState: null, ingestResumePath: null });\n};\n\nconst formatDuration = (ms: number) => {\n const seconds = Math.round(ms / 100) / 10;\n return `${seconds}s`;\n};\n\nexport const ingestEpub = async (\n filePath: string,\n selectedChapterIndices?: number[],\n options?: { summarize?: boolean; batch?: boolean }\n) => {\n const bookId = randomUUID();\n const paths = await ensureDataDirs();\n const fileName = `${bookId}.epub`;\n const bookPath = `${paths.booksDir}/${fileName}`;\n let resumePath: string | null = null;\n\n logInfo(`[Ingest] Starting ingestion for book ${bookId}`);\n\n await mkdir(paths.booksDir, { recursive: true });\n await copyFile(filePath, bookPath);\n logInfo(`[Ingest] EPUB file saved to ${bookPath}`);\n\n const parseStart = Date.now();\n const parsed = await parseEpub(bookPath);\n logInfo(`[Ingest] Parsed \"${parsed.title}\" with ${parsed.chapters.length} chapters (${formatDuration(Date.now() - parseStart)})`);\n logInfo(`[Ingest] Narrative chapters: ${parsed.narrativeStartIndex} to ${parsed.narrativeEndIndex}`);\n\n await insertBook({\n id: bookId,\n title: parsed.title,\n author: parsed.author,\n coverPath: parsed.coverImagePath,\n epubPath: bookPath,\n chapters: parsed.chapterTitles,\n narrativeStartIndex: parsed.narrativeStartIndex,\n narrativeEndIndex: parsed.narrativeEndIndex,\n });\n logInfo(`[Ingest] Book record inserted into database`);\n\n try {\n const chaptersToProcess = selectedChapterIndices\n ? parsed.chapters.filter((_, index) => selectedChapterIndices.includes(index))\n : parsed.chapters.slice(parsed.narrativeStartIndex, parsed.narrativeEndIndex + 1);\n\n const selectedIndices = selectedChapterIndices ||\n Array.from({ length: parsed.narrativeEndIndex - parsed.narrativeStartIndex + 1 },\n (_, i) => i + parsed.narrativeStartIndex);\n\n logInfo(`[Ingest] Processing ${chaptersToProcess.length} selected chapters (indices: ${selectedIndices.join(\", \")})`);\n\n let adjustedSummaries: BookChunk[] = [];\n if (options?.summarize !== false) {\n logInfo(`[Ingest] Generating summaries for ${chaptersToProcess.length} chapters...`);\n const summarizeStart = Date.now();\n const summaries = await summarizeAllChapters(chaptersToProcess, { batch: options?.batch });\n logInfo(`[Ingest] Generated ${summaries.length}/${chaptersToProcess.length} summaries (${formatDuration(Date.now() - summarizeStart)})`);\n\n const summaryRecords = summaries.map((s, idx) => ({\n ...s,\n chapterIndex: selectedIndices[idx] ?? s.chapterIndex,\n }));\n\n await updateBook(bookId, {\n summaries: JSON.stringify(summaryRecords),\n });\n\n adjustedSummaries = summaryRecords.map((s) => ({\n id: `${bookId}-summary-${s.chapterIndex}`,\n bookId,\n chapterIndex: s.chapterIndex,\n chapterTitle: s.chapterTitle,\n chunkIndex: -1,\n content: s.fullSummary,\n type: \"summary\" as const,\n }));\n logInfo(`[Ingest] Created ${adjustedSummaries.length} summary chunks`);\n }\n\n const chunksToProcess = parsed.chapters.map((chapter, index) =>\n selectedIndices.includes(index) ? chapter : { title: chapter.title, content: \"\" }\n );\n const chunks = chunkChapters(bookId, chunksToProcess).filter((chunk) => chunk.content.length > 0);\n logInfo(`[Ingest] Created ${chunks.length} chunks from selected chapters`);\n\n const allChunks = [...chunks, ...adjustedSummaries];\n\n if (options?.batch) {\n logInfo(`[Ingest] Submitting ${allChunks.length} chunks to OpenAI Batch API`);\n const { batchId, inputFileId } = await submitBatchEmbeddings(allChunks);\n await updateBook(bookId, {\n batchId,\n batchFileId: inputFileId,\n batchChunks: JSON.stringify(allChunks),\n });\n logInfo(`[Ingest] Batch submitted (${batchId}). Run \"mycroft book ingest resume ${bookId.slice(0, 8)}\" to complete ingestion.`);\n } else {\n const embedStart = Date.now();\n resumePath = await persistResumeState(bookId, { chunks: allChunks, resumeIndex: 0 });\n const embedded = await embedChunks(allChunks, {\n onBatch: async (embeddedBatch, progress) => {\n await addChunksToIndex(bookId, embeddedBatch);\n await updateBook(bookId, { chunkCount: progress.completed });\n if (!resumePath) return;\n await writeFile(\n resumePath,\n JSON.stringify({ chunks: allChunks, resumeIndex: progress.completed })\n );\n },\n });\n logInfo(`[Ingest] Embedded ${embedded.length} total chunks (${formatDuration(Date.now() - embedStart)})`);\n\n await updateBook(bookId, { chunkCount: embedded.length, indexedAt: Date.now() });\n logInfo(`[Ingest] Updated book record with chunk count: ${embedded.length}`);\n await finalizeResumeState(bookId, resumePath);\n }\n } catch (error) {\n logWarn(`[Ingest] Error during chunking/embedding: ${error instanceof Error ? error.message : String(error)}`);\n if (resumePath) {\n logWarn(`[Ingest] Partial progress saved. Run \"mycroft book ingest resume ${bookId.slice(0, 8)}\" to continue.`);\n return { id: bookId, status: \"interrupted\" as const };\n } else {\n await deleteBookIndex(bookId);\n await unlink(bookPath).catch(() => undefined);\n await deleteBook(bookId).catch(() => undefined);\n }\n throw error;\n }\n\n logInfo(`[Ingest] Ingestion complete for ${bookId}`);\n return { id: bookId, status: \"completed\" as const };\n};\n\nexport const resumeIngest = async (bookId: string, storedChunks: BookChunk[], batchId: string, batchFileId: string) => {\n const { checkBatchStatus, downloadBatchResults, cleanupBatchFiles } = await import(\"./batch-embedder.js\");\n\n logInfo(`[Resume] Checking batch ${batchId} for book ${bookId}`);\n const status = await checkBatchStatus(batchId);\n\n logInfo(`[Resume] Batch status: ${status.status} (completed: ${status.completed}/${status.total})`);\n\n if ([\"validating\", \"in_progress\", \"finalizing\"].includes(status.status)) {\n return { status: status.status as \"validating\" | \"in_progress\" | \"finalizing\", completed: status.completed, total: status.total };\n }\n\n if (status.status === \"failed\" || status.status === \"expired\" || status.status === \"cancelled\") {\n logWarn(`[Resume] Batch ${batchId} ended with status \"${status.status}\". Re-submitting...`);\n await cleanupBatchFiles(batchFileId, status.outputFileId);\n\n const { submitBatchEmbeddings } = await import(\"./batch-embedder.js\");\n const { batchId: newBatchId, inputFileId: newFileId } = await submitBatchEmbeddings(storedChunks);\n\n await updateBook(bookId, { batchId: newBatchId, batchFileId: newFileId });\n logInfo(`[Resume] New batch submitted (${newBatchId}). Run resume again later.`);\n return { status: \"resubmitted\" as const, batchId: newBatchId };\n }\n\n if (status.status !== \"completed\" || !status.outputFileId) {\n throw new Error(`Unexpected batch status: ${status.status}`);\n }\n\n const embedded = await downloadBatchResults(status.outputFileId, storedChunks);\n\n await addChunksToIndex(bookId, embedded);\n logInfo(`[Resume] Added ${embedded.length} chunks to vector index`);\n\n await updateBook(bookId, {\n chunkCount: embedded.length,\n indexedAt: Date.now(),\n batchId: null,\n batchFileId: null,\n batchChunks: null,\n });\n logInfo(`[Resume] Book ${bookId} indexing complete`);\n\n await cleanupBatchFiles(batchFileId, status.outputFileId);\n\n return { status: \"completed\" as const };\n};\n\nexport const resumeLocalIngest = async (bookId: string, resumePath: string, currentChunkCount: number) => {\n const state = await loadResumeState(bookId, resumePath);\n const total = state.chunks.length;\n const startIndex = Math.max(state.resumeIndex, currentChunkCount);\n\n if (startIndex >= total) {\n await finalizeResumeState(bookId, resumePath);\n throw new Error(`Resume state already completed for book ${bookId}.`);\n }\n\n logInfo(`[Resume] Resuming local embeddings at chunk ${startIndex + 1}/${total}`);\n const embedStart = Date.now();\n const remaining = state.chunks.slice(startIndex);\n const embeddedRemaining = await embedChunks(remaining, {\n onBatch: async (embeddedBatch, progress) => {\n const completed = startIndex + progress.completed;\n await addChunksToIndex(bookId, embeddedBatch);\n await updateBook(bookId, { chunkCount: completed });\n await writeFile(\n resumePath,\n JSON.stringify({ chunks: state.chunks, resumeIndex: completed })\n );\n },\n });\n\n logInfo(`[Resume] Embedded ${embeddedRemaining.length} remaining chunks (${formatDuration(Date.now() - embedStart)})`);\n\n const finalCount = startIndex + embeddedRemaining.length;\n await updateBook(bookId, {\n chunkCount: finalCount,\n indexedAt: Date.now(),\n });\n await finalizeResumeState(bookId, resumePath);\n\n return { status: \"completed\" as const, chunkCount: finalCount };\n};\n","import type { Chapter, BookChunk } from \"../shared/types.js\";\nimport { CHUNK_OVERLAP, CHUNK_SIZE, SEPARATORS } from \"./constants.js\";\n\nconst splitRecursive = (text: string, separators: readonly string[]): string[] => {\n if (text.length <= CHUNK_SIZE || separators.length === 0) return [text];\n const [separator, ...rest] = separators;\n if (!separator) return [text];\n\n const parts = text.split(separator);\n if (parts.length === 1) return splitRecursive(text, rest);\n\n const chunks: string[] = [];\n let current = \"\";\n\n for (const part of parts) {\n const next = current ? `${current}${separator}${part}` : part;\n if (next.length <= CHUNK_SIZE) {\n current = next;\n continue;\n }\n\n if (current) chunks.push(current);\n current = part;\n }\n\n if (current) chunks.push(current);\n\n const refined: string[] = [];\n for (const chunk of chunks) {\n if (chunk.length <= CHUNK_SIZE) {\n refined.push(chunk);\n continue;\n }\n refined.push(...splitRecursive(chunk, rest));\n }\n\n return refined;\n};\n\nconst withOverlap = (chunks: string[]): string[] => {\n if (chunks.length <= 1 || CHUNK_OVERLAP === 0) return chunks;\n\n const merged: string[] = [];\n for (let i = 0; i < chunks.length; i += 1) {\n const current = chunks[i] ?? \"\";\n const previous = merged[merged.length - 1];\n if (!previous) {\n merged.push(current);\n continue;\n }\n\n const overlap = previous.slice(-CHUNK_OVERLAP);\n merged.push(`${overlap}${current}`);\n }\n\n return merged;\n};\n\nexport const chunkChapters = (bookId: string, chapters: Chapter[]): BookChunk[] => {\n const chunks: BookChunk[] = [];\n\n chapters.forEach((chapter, chapterIndex) => {\n const trimmed = chapter.content.trim();\n if (!trimmed) return;\n\n const rawChunks = splitRecursive(trimmed, SEPARATORS);\n const overlapped = withOverlap(rawChunks);\n overlapped.forEach((content, chunkIndex) => {\n const normalized = content.replace(/\\s+/g, \" \").trim();\n if (!normalized) return;\n chunks.push({\n id: `${bookId}-${chapterIndex}-${chunkIndex}`,\n bookId,\n chapterIndex,\n chapterTitle: chapter.title,\n chunkIndex,\n content: normalized,\n });\n });\n });\n\n return chunks;\n};\n","import { embedMany } from \"ai\";\nimport { openai } from \"@ai-sdk/openai\";\nimport type { BookChunk } from \"../shared/types.js\";\nimport { getModels, logInfo } from \"./constants.js\";\n\nexport type EmbeddedChunk = BookChunk & {\n vector: number[];\n};\n\nconst MAX_TOKENS_PER_BATCH = 250_000;\nconst CHARS_PER_TOKEN = 4;\n\ntype EmbedProgress = {\n batchIndex: number;\n batchCount: number;\n completed: number;\n total: number;\n};\n\nexport const embedChunks = async (\n chunks: BookChunk[],\n options?: { onBatch?: (embedded: EmbeddedChunk[], progress: EmbedProgress) => Promise<void> | void }\n): Promise<EmbeddedChunk[]> => {\n if (chunks.length === 0) return [];\n\n const batches: BookChunk[][] = [];\n let currentBatch: BookChunk[] = [];\n let currentTokens = 0;\n\n for (const chunk of chunks) {\n const estimatedTokens = Math.ceil(chunk.content.length / CHARS_PER_TOKEN);\n\n if (currentTokens + estimatedTokens > MAX_TOKENS_PER_BATCH && currentBatch.length > 0) {\n batches.push(currentBatch);\n currentBatch = [];\n currentTokens = 0;\n }\n\n currentBatch.push(chunk);\n currentTokens += estimatedTokens;\n }\n\n if (currentBatch.length > 0) {\n batches.push(currentBatch);\n }\n\n logInfo(`[Embedder] Processing ${chunks.length} chunks in ${batches.length} batch(es)`);\n\n const allEmbedded: EmbeddedChunk[] = [];\n const models = await getModels();\n\n for (let i = 0; i < batches.length; i++) {\n const batch = batches[i]!;\n const estimatedTokens = batch.reduce((sum, c) => sum + Math.ceil(c.content.length / CHARS_PER_TOKEN), 0);\n\n logInfo(`[Embedder] Batch ${i + 1}/${batches.length}: ${batch.length} chunks (~${estimatedTokens.toLocaleString()} tokens)`);\n\n const { embeddings } = await embedMany({\n model: openai.embeddingModel(models.embedding),\n values: batch.map((chunk) => chunk.content),\n });\n\n const embeddedBatch: EmbeddedChunk[] = [];\n for (let j = 0; j < batch.length; j++) {\n const embeddedChunk = {\n ...batch[j]!,\n vector: embeddings[j] ?? [],\n };\n embeddedBatch.push(embeddedChunk);\n allEmbedded.push({\n ...embeddedChunk,\n });\n }\n\n if (options?.onBatch) {\n await options.onBatch(embeddedBatch, {\n batchIndex: i + 1,\n batchCount: batches.length,\n completed: allEmbedded.length,\n total: chunks.length,\n });\n }\n }\n\n logInfo(`[Embedder] Successfully embedded all ${allEmbedded.length} chunks`);\n\n return allEmbedded;\n};\n","import { LocalIndex } from \"vectra\";\nimport type { EmbeddedChunk } from \"./embedder.js\";\nimport type { BookChunk } from \"../shared/types.js\";\nimport { ensureDataDirs } from \"./constants.js\";\n\nexport type VectorMetadata = {\n bookId: string;\n chapterIndex: number;\n chapterTitle: string;\n chunkIndex: number;\n content: string;\n type?: \"chunk\" | \"summary\";\n};\n\nconst indexPathForBook = async (bookId: string) => {\n const paths = await ensureDataDirs();\n return `${paths.vectorsDir}/${bookId}`;\n};\n\nexport const createBookIndex = async (bookId: string): Promise<LocalIndex<VectorMetadata>> => {\n const index = new LocalIndex<VectorMetadata>(await indexPathForBook(bookId));\n const exists = await index.isIndexCreated();\n if (!exists) {\n await index.createIndex({\n version: 1,\n metadata_config: {\n indexed: [\"bookId\"],\n },\n });\n }\n return index;\n};\n\nexport const addChunksToIndex = async (bookId: string, chunks: EmbeddedChunk[]) => {\n const index = await createBookIndex(bookId);\n await index.batchInsertItems(\n chunks.map((chunk) => ({\n id: chunk.id,\n vector: chunk.vector,\n metadata: {\n bookId: chunk.bookId,\n chapterIndex: chunk.chapterIndex,\n chapterTitle: chunk.chapterTitle,\n chunkIndex: chunk.chunkIndex,\n content: chunk.content,\n type: chunk.type || \"chunk\",\n },\n }))\n );\n};\n\nexport const queryBookIndex = async (\n bookId: string,\n queryVector: number[],\n queryText: string,\n topK: number,\n maxChapterIndex?: number\n): Promise<(BookChunk & { score: number })[]> => {\n const index = await createBookIndex(bookId);\n const expandedTopK =\n maxChapterIndex === undefined || maxChapterIndex === null ? topK : Math.max(topK * 4, topK);\n const results = await index.queryItems(queryVector, queryText, expandedTopK);\n\n const mapped = results.map((result: (typeof results)[number]) => ({\n id: result.item.id ?? \"\",\n bookId,\n chapterIndex: result.item.metadata?.chapterIndex ?? 0,\n chapterTitle: result.item.metadata?.chapterTitle ?? \"\",\n chunkIndex: result.item.metadata?.chunkIndex ?? 0,\n content: result.item.metadata?.content ?? \"\",\n type: result.item.metadata?.type as \"chunk\" | \"summary\" | undefined,\n score: result.score,\n }));\n\n if (maxChapterIndex === undefined || maxChapterIndex === null) {\n return mapped.slice(0, topK);\n }\n\n return mapped.filter((item: (typeof mapped)[number]) => item.chapterIndex <= maxChapterIndex).slice(0, topK);\n};\n\nexport const deleteBookIndex = async (bookId: string) => {\n const index = new LocalIndex<VectorMetadata>(await indexPathForBook(bookId));\n const exists = await index.isIndexCreated();\n if (!exists) return;\n await index.deleteIndex();\n};\n","import { generateText } from \"ai\";\nimport { openai } from \"@ai-sdk/openai\";\nimport type { Chapter, ChapterSummary } from \"../shared/types.js\";\nimport { SUMMARY_MAX_TOKENS, SUMMARY_CONCURRENCY, SUMMARY_TARGET_WORDS, getModels, logInfo, logWarn } from \"./constants.js\";\n\nconst CHARS_PER_TOKEN = 4;\n\nconst estimateTokens = (text: string): number => Math.ceil(text.length / CHARS_PER_TOKEN);\n\nconst SUMMARY_PROMPT = (title: string, chapterNum: number, content: string) => `You are analyzing a chapter from a book (fiction or nonfiction). Extract key information to help readers understand the chapter's content.\n\nChapter Title: ${title}\nChapter Number: ${chapterNum}\n\n---\n${content}\n---\n\nExtract the following information and respond ONLY with valid JSON (no markdown, no code blocks):\n\n{\n \"characters\": [\"Name - brief description (role, traits, first appearance)\", ...],\n \"events\": \"What happens in this chapter? (2-3 sentences)\",\n \"setting\": \"Where does this chapter take place?\",\n \"revelations\": \"Any important information revealed? (secrets, backstory, foreshadowing)\"\n}\n\nKeep the total response around ${SUMMARY_TARGET_WORDS} words.`;\n\ntype SummaryJSON = {\n characters: string[];\n events: string;\n setting: string;\n revelations: string;\n};\n\nconst splitIntoSections = (text: string, maxTokens: number): string[] => {\n const estimatedTokens = estimateTokens(text);\n\n if (estimatedTokens <= maxTokens) {\n return [text];\n }\n\n const numSections = Math.ceil(estimatedTokens / maxTokens);\n const charsPerSection = Math.floor(text.length / numSections);\n const sections: string[] = [];\n\n for (let i = 0; i < numSections; i++) {\n const start = i * charsPerSection;\n const end = i === numSections - 1 ? text.length : (i + 1) * charsPerSection;\n sections.push(text.slice(start, end));\n }\n\n return sections;\n};\n\nconst summarizeSection = async (text: string, title: string, sectionNum: number): Promise<string> => {\n const models = await getModels();\n const { text: summary } = await generateText({\n model: openai(models.summary),\n prompt: `Summarize this section from chapter \"${title}\" (Part ${sectionNum}). Focus on key events, characters, and revelations. Keep it concise (100-150 words):\\n\\n${text}`,\n temperature: 0.3,\n });\n\n return summary;\n};\n\nconst generateStructuredSummary = async (\n content: string,\n title: string,\n chapterIndex: number\n): Promise<ChapterSummary | null> => {\n try {\n const models = await getModels();\n const { text } = await generateText({\n model: openai(models.summary),\n prompt: SUMMARY_PROMPT(title, chapterIndex + 1, content),\n temperature: 0.3,\n });\n\n let jsonText = text.trim();\n if (jsonText.startsWith(\"```json\")) {\n jsonText = jsonText.slice(7, -3).trim();\n } else if (jsonText.startsWith(\"```\")) {\n jsonText = jsonText.slice(3, -3).trim();\n }\n\n const parsed: SummaryJSON = JSON.parse(jsonText);\n\n const fullSummary = `Chapter ${chapterIndex + 1}: ${title}\n\nCharacters: ${parsed.characters.join(\", \")}\n\nEvents: ${parsed.events}\n\nSetting: ${parsed.setting}\n\nRevelations: ${parsed.revelations}`;\n\n return {\n chapterIndex,\n chapterTitle: title,\n characters: parsed.characters,\n events: parsed.events,\n setting: parsed.setting,\n revelations: parsed.revelations,\n fullSummary,\n };\n } catch (error) {\n logWarn(`[Summarizer] Failed to parse summary JSON for \"${title}\": ${error instanceof Error ? error.message : String(error)}`);\n return null;\n }\n};\n\nexport const summarizeChapter = async (\n chapter: Chapter,\n chapterIndex: number\n): Promise<ChapterSummary | null> => {\n const tokens = estimateTokens(chapter.content);\n\n logInfo(`[Summarizer] Chapter ${chapterIndex + 1} \"${chapter.title}\": ~${tokens.toLocaleString()} tokens`);\n\n try {\n if (tokens < SUMMARY_MAX_TOKENS) {\n return await generateStructuredSummary(chapter.content, chapter.title, chapterIndex);\n }\n\n logInfo(`[Summarizer] Chapter ${chapterIndex + 1} exceeds token limit, using two-pass approach`);\n\n const sections = splitIntoSections(chapter.content, SUMMARY_MAX_TOKENS);\n logInfo(`[Summarizer] Split into ${sections.length} sections`);\n\n const sectionSummaries = await Promise.all(\n sections.map((section, i) => summarizeSection(section, chapter.title, i + 1))\n );\n\n const combined = sectionSummaries.join(\"\\n\\n\");\n\n return await generateStructuredSummary(combined, chapter.title, chapterIndex);\n } catch (error) {\n logWarn(`[Summarizer] Failed to summarize chapter ${chapterIndex + 1}: ${error instanceof Error ? error.message : String(error)}`);\n return null;\n }\n};\n\nexport const summarizeAllChapters = async (\n chapters: Chapter[],\n options?: { batch?: boolean }\n): Promise<ChapterSummary[]> => {\n const summaries: ChapterSummary[] = [];\n const concurrency = options?.batch ? 1 : SUMMARY_CONCURRENCY;\n\n logInfo(\n `[Summarizer] Starting summarization of ${chapters.length} chapters (concurrency: ${concurrency}${options?.batch ? \", batch mode\" : \"\"})`\n );\n\n for (let i = 0; i < chapters.length; i += concurrency) {\n const batch = chapters.slice(i, i + concurrency);\n const batchPromises = batch.map((chapter, batchIndex) => summarizeChapter(chapter, i + batchIndex));\n\n const batchResults = await Promise.all(batchPromises);\n\n for (const summary of batchResults) {\n if (summary) {\n summaries.push(summary);\n }\n }\n\n logInfo(`[Summarizer] Progress: ${Math.min(i + concurrency, chapters.length)}/${chapters.length} chapters processed`);\n }\n\n logInfo(`[Summarizer] Completed: ${summaries.length}/${chapters.length} summaries generated`);\n\n return summaries;\n};\n","import Database from \"better-sqlite3\";\nimport type { BookRecord, ChatMessage, ChatMessageRole, ChatSession, ChatSessionSummary } from \"../shared/types.js\";\nimport { createDb } from \"./schema.js\";\n\nexport type BookInsert = Omit<\n BookRecord,\n \"createdAt\" | \"indexedAt\" | \"chunkCount\" | \"progressChapter\" | \"narrativeStartIndex\" | \"narrativeEndIndex\" | \"batchId\" | \"batchFileId\" | \"ingestState\" | \"ingestResumePath\"\n> & {\n chunkCount?: number;\n indexedAt?: number | null;\n progressChapter?: number | null;\n summaries?: string;\n narrativeStartIndex?: number | null;\n narrativeEndIndex?: number | null;\n batchId?: string | null;\n batchFileId?: string | null;\n batchChunks?: string | null;\n ingestState?: string | null;\n ingestResumePath?: string | null;\n};\n\nconst mapRow = (row: any): BookRecord => ({\n id: row.id,\n title: row.title,\n author: row.author ?? null,\n coverPath: row.cover_path ?? null,\n epubPath: row.epub_path,\n chunkCount: row.chunk_count ?? 0,\n createdAt: row.created_at ?? 0,\n indexedAt: row.indexed_at ?? null,\n chapters: row.chapters ? JSON.parse(row.chapters) : [],\n progressChapter: row.progress_chapter ?? null,\n narrativeStartIndex: row.narrative_start_index ?? null,\n narrativeEndIndex: row.narrative_end_index ?? null,\n batchId: row.batch_id ?? null,\n batchFileId: row.batch_file_id ?? null,\n ingestState: row.ingest_state ?? null,\n ingestResumePath: row.ingest_resume_path ?? null,\n});\n\nlet dbPromise: Promise<ReturnType<typeof Database>> | null = null;\n\nconst getDb = async () => {\n if (!dbPromise) {\n dbPromise = createDb();\n }\n return dbPromise;\n};\n\nexport const insertBook = async (book: BookInsert): Promise<string> => {\n const db = await getDb();\n const statement = db.prepare(\n \"INSERT INTO books (id, title, author, cover_path, chapters, epub_path, chunk_count, indexed_at, progress_chapter, narrative_start_index, narrative_end_index) VALUES (@id, @title, @author, @coverPath, @chapters, @epubPath, @chunkCount, @indexedAt, @progressChapter, @narrativeStartIndex, @narrativeEndIndex)\"\n );\n statement.run({\n id: book.id,\n title: book.title,\n author: book.author,\n coverPath: book.coverPath,\n chapters: JSON.stringify(book.chapters ?? []),\n epubPath: book.epubPath,\n chunkCount: book.chunkCount ?? 0,\n indexedAt: book.indexedAt ?? null,\n progressChapter: book.progressChapter ?? null,\n narrativeStartIndex: book.narrativeStartIndex ?? null,\n narrativeEndIndex: book.narrativeEndIndex ?? null,\n });\n return book.id;\n};\n\nexport const updateBook = async (id: string, updates: Partial<BookInsert>) => {\n const fields: string[] = [];\n const params: Record<string, string | number | boolean | null> = { id };\n\n if (updates.title !== undefined) {\n fields.push(\"title = @title\");\n params.title = updates.title;\n }\n if (updates.author !== undefined) {\n fields.push(\"author = @author\");\n params.author = updates.author;\n }\n if (updates.coverPath !== undefined) {\n fields.push(\"cover_path = @coverPath\");\n params.coverPath = updates.coverPath;\n }\n if (updates.chapters !== undefined) {\n fields.push(\"chapters = @chapters\");\n params.chapters = JSON.stringify(updates.chapters);\n }\n if (updates.epubPath !== undefined) {\n fields.push(\"epub_path = @epubPath\");\n params.epubPath = updates.epubPath;\n }\n if (updates.chunkCount !== undefined) {\n fields.push(\"chunk_count = @chunkCount\");\n params.chunkCount = updates.chunkCount;\n }\n if (updates.indexedAt !== undefined) {\n fields.push(\"indexed_at = @indexedAt\");\n params.indexedAt = updates.indexedAt;\n }\n if (updates.progressChapter !== undefined) {\n fields.push(\"progress_chapter = @progressChapter\");\n params.progressChapter = updates.progressChapter;\n }\n if (updates.summaries !== undefined) {\n fields.push(\"summaries = @summaries\");\n params.summaries = updates.summaries;\n }\n if (updates.narrativeStartIndex !== undefined) {\n fields.push(\"narrative_start_index = @narrativeStartIndex\");\n params.narrativeStartIndex = updates.narrativeStartIndex;\n }\n if (updates.narrativeEndIndex !== undefined) {\n fields.push(\"narrative_end_index = @narrativeEndIndex\");\n params.narrativeEndIndex = updates.narrativeEndIndex;\n }\n if (updates.batchId !== undefined) {\n fields.push(\"batch_id = @batchId\");\n params.batchId = updates.batchId;\n }\n if (updates.batchFileId !== undefined) {\n fields.push(\"batch_file_id = @batchFileId\");\n params.batchFileId = updates.batchFileId;\n }\n if (updates.batchChunks !== undefined) {\n fields.push(\"batch_chunks = @batchChunks\");\n params.batchChunks = updates.batchChunks;\n }\n if (updates.ingestState !== undefined) {\n fields.push(\"ingest_state = @ingestState\");\n params.ingestState = updates.ingestState;\n }\n if (updates.ingestResumePath !== undefined) {\n fields.push(\"ingest_resume_path = @ingestResumePath\");\n params.ingestResumePath = updates.ingestResumePath;\n }\n\n if (fields.length === 0) return;\n\n const db = await getDb();\n db.prepare(`UPDATE books SET ${fields.join(\", \")} WHERE id = @id`).run(params);\n};\n\nexport const getBooks = async (): Promise<BookRecord[]> => {\n const db = await getDb();\n const rows = db.prepare(\"SELECT * FROM books ORDER BY created_at DESC\").all();\n return rows.map(mapRow);\n};\n\nexport const getBook = async (id: string): Promise<BookRecord | null> => {\n const db = await getDb();\n const row = db.prepare(\"SELECT * FROM books WHERE id = ?\").get(id);\n return row ? mapRow(row) : null;\n};\n\nexport const getBookBatchChunks = async (id: string): Promise<string | null> => {\n const db = await getDb();\n const row = db.prepare(\"SELECT batch_chunks FROM books WHERE id = ?\").get(id) as { batch_chunks?: string } | undefined;\n return row?.batch_chunks ?? null;\n};\n\nexport const deleteBook = async (id: string) => {\n const db = await getDb();\n db.prepare(\"DELETE FROM chat_messages WHERE session_id IN (SELECT id FROM chat_sessions WHERE book_id = ?)\").run(id);\n db.prepare(\"DELETE FROM chat_sessions WHERE book_id = ?\").run(id);\n db.prepare(\"DELETE FROM books WHERE id = ?\").run(id);\n};\n\nexport type ChatSessionInsert = Omit<ChatSession, \"createdAt\" | \"updatedAt\"> & {\n createdAt?: number;\n updatedAt?: number;\n};\n\nexport type ChatMessageInsert = Omit<ChatMessage, \"createdAt\"> & {\n createdAt?: number;\n};\n\nconst mapSession = (row: any): ChatSession => ({\n id: row.id,\n bookId: row.book_id,\n title: row.title ?? null,\n summary: row.summary ?? null,\n createdAt: row.created_at ?? 0,\n updatedAt: row.updated_at ?? 0,\n});\n\nconst mapSessionSummary = (row: any): ChatSessionSummary => ({\n ...mapSession(row),\n bookTitle: row.book_title ?? null,\n});\n\nconst mapMessage = (row: any): ChatMessage => ({\n id: row.id,\n sessionId: row.session_id,\n role: row.role as ChatMessageRole,\n content: row.content,\n tokenCount: row.token_count ?? null,\n createdAt: row.created_at ?? 0,\n});\n\nexport const insertChatSession = async (session: ChatSessionInsert): Promise<string> => {\n const db = await getDb();\n db.prepare(\n \"INSERT INTO chat_sessions (id, book_id, title, summary, created_at, updated_at) VALUES (@id, @bookId, @title, @summary, @createdAt, @updatedAt)\"\n ).run({\n id: session.id,\n bookId: session.bookId,\n title: session.title ?? null,\n summary: session.summary ?? null,\n createdAt: session.createdAt ?? Date.now(),\n updatedAt: session.updatedAt ?? Date.now(),\n });\n return session.id;\n};\n\nexport const updateChatSession = async (id: string, updates: Partial<ChatSessionInsert>) => {\n const fields: string[] = [];\n const params: Record<string, string | number | null> = { id };\n\n if (updates.title !== undefined) {\n fields.push(\"title = @title\");\n params.title = updates.title;\n }\n if (updates.summary !== undefined) {\n fields.push(\"summary = @summary\");\n params.summary = updates.summary;\n }\n if (updates.updatedAt !== undefined) {\n fields.push(\"updated_at = @updatedAt\");\n params.updatedAt = updates.updatedAt;\n }\n\n if (fields.length === 0) return;\n\n const db = await getDb();\n db.prepare(`UPDATE chat_sessions SET ${fields.join(\", \")} WHERE id = @id`).run(params);\n};\n\nexport const getChatSession = async (id: string): Promise<ChatSession | null> => {\n const db = await getDb();\n const row = db.prepare(\"SELECT * FROM chat_sessions WHERE id = ?\").get(id);\n return row ? mapSession(row) : null;\n};\n\nexport const listChatSessions = async (): Promise<ChatSessionSummary[]> => {\n const db = await getDb();\n const rows = db\n .prepare(\n \"SELECT chat_sessions.*, books.title as book_title FROM chat_sessions LEFT JOIN books ON books.id = chat_sessions.book_id ORDER BY chat_sessions.updated_at DESC\"\n )\n .all();\n return rows.map(mapSessionSummary);\n};\n\nexport const insertChatMessage = async (message: ChatMessageInsert): Promise<string> => {\n const db = await getDb();\n db.prepare(\n \"INSERT INTO chat_messages (id, session_id, role, content, token_count, created_at) VALUES (@id, @sessionId, @role, @content, @tokenCount, @createdAt)\"\n ).run({\n id: message.id,\n sessionId: message.sessionId,\n role: message.role,\n content: message.content,\n tokenCount: message.tokenCount ?? null,\n createdAt: message.createdAt ?? Date.now(),\n });\n return message.id;\n};\n\nexport const getChatMessages = async (sessionId: string, limit?: number): Promise<ChatMessage[]> => {\n const db = await getDb();\n const rows = limit !== undefined\n ? db\n .prepare(\"SELECT * FROM chat_messages WHERE session_id = ? ORDER BY created_at DESC LIMIT ?\")\n .all(sessionId, limit)\n : db.prepare(\"SELECT * FROM chat_messages WHERE session_id = ? ORDER BY created_at ASC\").all(sessionId);\n\n const mapped = rows.map(mapMessage);\n return limit !== undefined ? mapped.reverse() : mapped;\n};\n","import Database from \"better-sqlite3\";\nimport { resolvePaths } from \"../services/constants.js\";\n\nconst resolveDbPath = async () => {\n const paths = await resolvePaths();\n return paths.dbPath;\n};\n\nexport const createDb = async (): Promise<ReturnType<typeof Database>> => {\n const db = new Database(await resolveDbPath());\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS books (\n id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n author TEXT,\n cover_path TEXT,\n chapters TEXT,\n epub_path TEXT NOT NULL,\n chunk_count INTEGER DEFAULT 0,\n created_at INTEGER DEFAULT (strftime('%s','now')),\n indexed_at INTEGER,\n progress_chapter INTEGER\n );\n `);\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS chat_sessions (\n id TEXT PRIMARY KEY,\n book_id TEXT NOT NULL,\n title TEXT,\n summary TEXT,\n created_at INTEGER DEFAULT (strftime('%s','now')),\n updated_at INTEGER DEFAULT (strftime('%s','now'))\n );\n `);\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS chat_messages (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n token_count INTEGER,\n created_at INTEGER DEFAULT (strftime('%s','now'))\n );\n `);\n\n db.exec(\"CREATE INDEX IF NOT EXISTS chat_messages_session_idx ON chat_messages(session_id, created_at)\");\n\n const columns = db\n .prepare(\"PRAGMA table_info(books)\")\n .all()\n .map((col: { name: string }) => col.name);\n\n const ensureColumn = (name: string, definition: string) => {\n if (!columns.includes(name)) {\n db.exec(`ALTER TABLE books ADD COLUMN ${definition}`);\n }\n };\n\n ensureColumn(\"chapters\", \"chapters TEXT\");\n ensureColumn(\"progress_chapter\", \"progress_chapter INTEGER\");\n ensureColumn(\"summaries\", \"summaries TEXT\");\n ensureColumn(\"narrative_start_index\", \"narrative_start_index INTEGER DEFAULT 0\");\n ensureColumn(\"narrative_end_index\", \"narrative_end_index INTEGER\");\n ensureColumn(\"batch_id\", \"batch_id TEXT\");\n ensureColumn(\"batch_file_id\", \"batch_file_id TEXT\");\n ensureColumn(\"batch_chunks\", \"batch_chunks TEXT\");\n ensureColumn(\"ingest_state\", \"ingest_state TEXT\");\n ensureColumn(\"ingest_resume_path\", \"ingest_resume_path TEXT\");\n\n return db;\n};\n","import { parseEpub } from \"../services/epub-parser.js\";\nimport { ingestEpub } from \"../services/ingest.js\";\nimport { ensureDataDirs, requireOpenAIKey } from \"../services/constants.js\";\nimport { access } from \"node:fs/promises\";\nimport { prompt } from \"./prompt.js\";\nimport { isInteractive, stdout } from \"./io.js\";\n\nconst parseIndexSelection = (input: string, max: number): number[] => {\n const trimmed = input.trim();\n if (!trimmed) return [];\n const tokens = trimmed.split(\",\").map((part) => part.trim()).filter(Boolean);\n const indices = new Set<number>();\n for (const token of tokens) {\n if (token.includes(\"-\")) {\n const [startRaw, endRaw] = token.split(\"-\");\n const start = Number(startRaw);\n const end = Number(endRaw);\n if (!Number.isFinite(start) || !Number.isFinite(end)) continue;\n for (let i = Math.min(start, end); i <= Math.max(start, end); i++) {\n if (i >= 0 && i < max) indices.add(i);\n }\n } else {\n const index = Number(token);\n if (Number.isFinite(index) && index >= 0 && index < max) indices.add(index);\n }\n }\n return Array.from(indices).sort((a, b) => a - b);\n};\n\nexport const ingestCommand = async (filePath: string, options: { manual?: boolean; summarize?: boolean; batch?: boolean }) => {\n requireOpenAIKey();\n await ensureDataDirs();\n try {\n await access(filePath);\n } catch {\n throw new Error(`File not found: ${filePath}`);\n }\n\n let selectedChapterIndices: number[] | undefined;\n if (options.manual) {\n if (!isInteractive()) {\n throw new Error(\"Manual chapter selection requires an interactive terminal.\");\n }\n const parsed = await parseEpub(filePath);\n if (parsed.chapterTitles.length === 0) {\n throw new Error(\"No chapters found in EPUB\");\n }\n\n stdout(\"Chapters:\");\n parsed.chapterTitles.forEach((title, index) => {\n const marker = index >= parsed.narrativeStartIndex && index <= parsed.narrativeEndIndex ? \"*\" : \" \";\n stdout(`${marker} [${index}] ${title}`);\n });\n stdout(\"\\nEnter chapter indices to ingest (e.g. 0-10,12). Press Enter for narrative range.\");\n const answer = await prompt(\"Selection: \");\n const indices = parseIndexSelection(answer, parsed.chapterTitles.length);\n if (indices.length > 0) {\n selectedChapterIndices = indices;\n } else {\n selectedChapterIndices = Array.from(\n { length: parsed.narrativeEndIndex - parsed.narrativeStartIndex + 1 },\n (_, i) => i + parsed.narrativeStartIndex\n );\n }\n }\n\n const result = await ingestEpub(filePath, selectedChapterIndices, { summarize: options.summarize ?? false, batch: options.batch ?? false });\n if (result.status === \"interrupted\") {\n stdout(`\\nIngest interrupted. Run \"mycroft book ingest resume ${result.id.slice(0, 8)}\" to continue.`);\n return;\n }\n\n if (options.batch) {\n stdout(`\\nBatch submitted. Book registered as ${result.id}`);\n stdout(`Use \"mycroft book ingest resume ${result.id.slice(0, 8)}\" to complete ingestion once the batch finishes.`);\n } else {\n stdout(`\\nDone. Book indexed as ${result.id}`);\n }\n};\n","import { createInterface } from \"node:readline/promises\";\nimport { handleSigint } from \"./io.js\";\n\nexport const prompt = async (question: string): Promise<string> => {\n const release = handleSigint();\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n const response = await rl.question(question);\n return response.trim();\n } finally {\n rl.close();\n release();\n }\n};\n\nexport const confirm = async (question: string): Promise<boolean> => {\n const response = await prompt(question);\n const normalized = response.trim().toLowerCase();\n return normalized === \"y\" || normalized === \"yes\";\n};\n","import { ingestCommand } from \"../ingest.js\";\n\nexport const registerBookIngest = (program: import(\"commander\").Command) => {\n const ingest = program\n .command(\"ingest\")\n .description(\"Ingest an EPUB file\")\n .argument(\"<path>\", \"Path to the EPUB file\")\n .option(\"--manual\", \"Interactive chapter selection\")\n .option(\"--summary\", \"Enable AI chapter summaries\")\n .option(\"--batch\", \"Use OpenAI Batch API for embeddings (50% cost savings, up to 24h)\")\n .addHelpText(\n \"after\",\n `\\nEXAMPLES\\n mycroft book ingest ./book.epub\\n mycroft book ingest ./book.epub --summary\\n mycroft book ingest ./book.epub --batch\\n mycroft book ingest resume 8f2c1a4b\\n\\nNOTES\\n --batch submits embeddings and returns immediately.\\n Use \"mycroft book ingest resume <id>\" after the batch completes to finish indexing.\\n Non-batch ingests can also be resumed if interrupted.\\n`\n )\n .action(async (path: string, options: { manual?: boolean; summary?: boolean; batch?: boolean }) => {\n const summarize = Boolean(options.summary);\n await ingestCommand(path, { manual: options.manual, summarize, batch: options.batch });\n });\n\n return ingest;\n};\n","import { getBooks } from \"../db/queries.js\";\nimport { ensureDataDirs } from \"../services/constants.js\";\nimport { stdout } from \"./io.js\";\n\nconst formatDate = (timestamp: number | null) => {\n if (!timestamp) return \"-\";\n return new Date(timestamp).toISOString().slice(0, 10);\n};\n\nexport const listCommand = async () => {\n await ensureDataDirs();\n const books = await getBooks();\n if (books.length === 0) {\n stdout(\"No books indexed yet.\");\n return;\n }\n\n stdout(\"ID | Title | Author | Chunks | Indexed | Status\");\n stdout(\"---------|-------|--------|--------|--------|-------\");\n for (const book of books) {\n const shortId = book.id.slice(0, 8);\n const title = book.title;\n const author = book.author || \"-\";\n const chunks = String(book.chunkCount ?? 0);\n const indexed = formatDate(book.indexedAt);\n const status = book.indexedAt\n ? \"[indexed]\"\n : book.batchId\n ? \"[batch pending]\"\n : book.ingestState === \"pending\"\n ? \"[resume pending]\"\n : \"[pending]\";\n stdout(`${shortId} | ${title} | ${author} | ${chunks} | ${indexed} | ${status}`);\n }\n};\n","import { listCommand } from \"../list.js\";\n\nexport const registerBookList = (program: import(\"commander\").Command) => {\n program\n .command(\"list\")\n .description(\"List indexed books\")\n .action(async () => {\n await listCommand();\n });\n};\n","import { getBooks } from \"../db/queries.js\";\n\nexport const resolveBookId = async (input: string): Promise<string | null> => {\n const books = await getBooks();\n const exact = books.find((book) => book.id === input);\n if (exact) return exact.id;\n const matches = books.filter((book) => book.id.startsWith(input));\n if (matches.length === 1) return matches[0]!.id;\n if (matches.length > 1) {\n throw new Error(`Ambiguous id prefix \"${input}\" (${matches.length} matches)`);\n }\n return null;\n};\n","import { getBook } from \"../db/queries.js\";\nimport { resolveBookId } from \"./utils.js\";\nimport { ensureDataDirs } from \"../services/constants.js\";\nimport { stdout } from \"./io.js\";\n\nexport const showCommand = async (id: string) => {\n await ensureDataDirs();\n const resolvedId = await resolveBookId(id);\n if (!resolvedId) {\n throw new Error(`Book not found: ${id}`);\n }\n const book = await getBook(resolvedId);\n if (!book) {\n throw new Error(`Book not found: ${id}`);\n }\n\n stdout(`Title: ${book.title}`);\n stdout(`Author: ${book.author ?? \"-\"}`);\n stdout(`ID: ${book.id}`);\n stdout(`Chunks: ${book.chunkCount}`);\n stdout(`Indexed: ${book.indexedAt ? new Date(book.indexedAt).toISOString() : \"-\"}`);\n stdout(`Narrative range: ${book.narrativeStartIndex ?? 0} to ${book.narrativeEndIndex ?? book.chapters.length - 1}`);\n stdout(`Progress chapter: ${book.progressChapter ?? \"-\"}`);\n stdout(`Ingest status: ${book.ingestState ?? \"-\"}`);\n stdout(\"\\nChapters:\");\n\n book.chapters.forEach((title: string, index: number) => {\n const marker = index === book.narrativeStartIndex ? \"[start]\" : index === book.narrativeEndIndex ? \"[end]\" : \"\";\n stdout(` [${index}] ${title} ${marker}`.trim());\n });\n};\n","import { showCommand } from \"../show.js\";\n\nexport const registerBookShow = (program: import(\"commander\").Command) => {\n program\n .command(\"show\")\n .description(\"Show full book metadata\")\n .argument(\"<id>\", \"Book id or prefix\")\n .action(async (id: string) => {\n await showCommand(id);\n });\n};\n","import { embed, streamText } from \"ai\";\nimport { openai } from \"@ai-sdk/openai\";\nimport { getBook } from \"../db/queries.js\";\nimport { resolveBookId } from \"./utils.js\";\nimport { queryBookIndex } from \"../services/vector-store.js\";\nimport { ensureDataDirs, getModels, isAskEnabled, requireOpenAIKey } from \"../services/constants.js\";\nimport { handleSigint } from \"./io.js\";\n\nconst formatContext = (chunks: Array<{ content: string; chapterTitle: string; chapterIndex: number }>) =>\n chunks\n .map(\n (chunk, index) =>\n `Excerpt [${index + 1}] (${chunk.chapterTitle || `Chapter ${chunk.chapterIndex + 1}`}):\\n${chunk.content}`\n )\n .join(\"\\n\\n\");\n\nexport const askCommand = async (\n id: string,\n question: string,\n options: { topK: number; maxChapter?: number }\n) => {\n if (!(await isAskEnabled())) {\n throw new Error(\"Ask is disabled in config (askEnabled: false). Enable it to use this command.\");\n }\n\n requireOpenAIKey();\n await ensureDataDirs();\n\n const resolvedId = await resolveBookId(id);\n if (!resolvedId) {\n throw new Error(`Book not found: ${id}`);\n }\n const book = await getBook(resolvedId);\n if (!book) {\n throw new Error(`Book not found: ${id}`);\n }\n\n const models = await getModels();\n const { embedding } = await embed({\n model: openai.embeddingModel(models.embedding),\n value: question,\n });\n\n const narrativeStart = book.narrativeStartIndex ?? 0;\n const userProgress = book.progressChapter ?? null;\n const maxChapterIndex = options.maxChapter !== undefined\n ? narrativeStart + options.maxChapter\n : userProgress !== null\n ? narrativeStart + userProgress\n : undefined;\n\n const retrievalLimit = options.topK * 3;\n const allMatches = await queryBookIndex(resolvedId, embedding, question, retrievalLimit, maxChapterIndex);\n\n const summaries = allMatches.filter((m) => m.type === \"summary\");\n const chunks = allMatches.filter((m) => m.type !== \"summary\");\n\n const topSummaries = summaries.slice(0, 2);\n const topChunks = chunks.slice(0, Math.max(0, options.topK - topSummaries.length));\n const selectedMatches = [...topSummaries, ...topChunks];\n\n const context = formatContext(selectedMatches);\n\n const releaseSigint = handleSigint();\n const stream = streamText({\n model: openai(models.chat),\n system: `You are a reading companion helping readers understand this book.\n\nGuidelines:\n- Use the provided chapter summaries and excerpts to answer questions\n- Chapter summaries provide high-level context about characters, events, and plot\n- Excerpts provide specific details and quotes\n- When asked for recaps or \"what happened\", synthesize from summaries\n- Don't cite table of contents, front matter, or structural elements\n- If truly unsure, briefly say so - but try to answer from available context first\n- Cite sources using [1], [2], etc. at the end of relevant sentences\n- The context may be limited to earlier chapters only - don't infer beyond what's provided`,\n prompt: `Question: ${question}\\n\\n${context}`,\n });\n\n try {\n for await (const part of stream.textStream) {\n process.stdout.write(part);\n }\n } finally {\n releaseSigint();\n }\n\n if (selectedMatches.length > 0) {\n process.stdout.write(\"\\n\\nSources:\\n\");\n selectedMatches.forEach((match, index) => {\n const title = match.chapterTitle || `Chapter ${match.chapterIndex + 1}`;\n const excerpt = match.content.slice(0, 120).replace(/\\s+/g, \" \");\n process.stdout.write(`[${index + 1}] ${title}: ${excerpt}\\n`);\n });\n }\n};\n","export type QueryOptions = {\n topK: number;\n maxChapter?: number;\n};\n\nexport const parseQueryOptions = (options: { topK: string; maxChapter?: string }): QueryOptions => {\n const topK = Number(options.topK);\n if (!Number.isFinite(topK) || topK <= 0) {\n throw new Error(\"--top-k must be a positive number.\");\n }\n let maxChapter: number | undefined;\n if (options.maxChapter !== undefined) {\n const parsed = Number(options.maxChapter);\n if (!Number.isFinite(parsed) || parsed < 0) {\n throw new Error(\"--max-chapter must be a non-negative number.\");\n }\n maxChapter = parsed;\n }\n\n return { topK, maxChapter };\n};\n","import { askCommand } from \"../ask.js\";\nimport { parseQueryOptions } from \"../query-options.js\";\n\nexport const registerBookAsk = (program: import(\"commander\").Command) => {\n program\n .command(\"ask\")\n .description(\"Ask a question about a book\")\n .argument(\"<id>\", \"Book id or prefix\")\n .argument(\"<question>\", \"Question to ask\")\n .option(\"--top-k <n>\", \"Number of passages to retrieve\", \"5\")\n .option(\"--max-chapter <n>\", \"Spoiler-free limit (0-based within narrative)\")\n .action(async (\n id: string,\n question: string,\n options: { topK: string; maxChapter?: string }\n ) => {\n const { topK, maxChapter } = parseQueryOptions(options);\n await askCommand(id, question, { topK, maxChapter });\n });\n};\n","import { embed } from \"ai\";\nimport { openai } from \"@ai-sdk/openai\";\nimport { getBook } from \"../db/queries.js\";\nimport { resolveBookId } from \"./utils.js\";\nimport { queryBookIndex } from \"../services/vector-store.js\";\nimport { ensureDataDirs, getModels, requireOpenAIKey } from \"../services/constants.js\";\nimport { stdout } from \"./io.js\";\n\nexport const searchCommand = async (\n id: string,\n query: string,\n options: { topK: number; maxChapter?: number }\n) => {\n requireOpenAIKey();\n await ensureDataDirs();\n const resolvedId = await resolveBookId(id);\n if (!resolvedId) {\n throw new Error(`Book not found: ${id}`);\n }\n const book = await getBook(resolvedId);\n if (!book) {\n throw new Error(`Book not found: ${id}`);\n }\n\n const models = await getModels();\n const { embedding } = await embed({\n model: openai.embeddingModel(models.embedding),\n value: query,\n });\n\n const maxChapterIndex = options.maxChapter !== undefined\n ? (book.narrativeStartIndex ?? 0) + options.maxChapter\n : book.progressChapter !== null\n ? (book.narrativeStartIndex ?? 0) + (book.progressChapter ?? 0)\n : undefined;\n const results = await queryBookIndex(resolvedId, embedding, query, options.topK, maxChapterIndex);\n\n if (results.length === 0) {\n stdout(\"No results.\");\n return;\n }\n\n results.forEach((result, index) => {\n const chapterTitle = result.chapterTitle || `Chapter ${result.chapterIndex + 1}`;\n const excerpt = result.content.slice(0, 200).replace(/\\s+/g, \" \");\n stdout(`\\n#${index + 1} score=${result.score.toFixed(4)} type=${result.type || \"chunk\"}`);\n stdout(`${chapterTitle} (chapter ${result.chapterIndex})`);\n stdout(excerpt);\n });\n};\n","import { searchCommand } from \"../search.js\";\nimport { parseQueryOptions } from \"../query-options.js\";\n\nexport const registerBookSearch = (program: import(\"commander\").Command) => {\n program\n .command(\"search\")\n .description(\"Vector search without LLM\")\n .argument(\"<id>\", \"Book id or prefix\")\n .argument(\"<query>\", \"Search query\")\n .option(\"--top-k <n>\", \"Number of passages to retrieve\", \"5\")\n .option(\"--max-chapter <n>\", \"Spoiler-free limit (0-based within narrative)\")\n .action(async (\n id: string,\n query: string,\n options: { topK: string; maxChapter?: string }\n ) => {\n const { topK, maxChapter } = parseQueryOptions(options);\n await searchCommand(id, query, { topK, maxChapter });\n });\n};\n","import { unlink } from \"node:fs/promises\";\nimport { deleteBook, getBook } from \"../db/queries.js\";\nimport { resolveBookId } from \"./utils.js\";\nimport { deleteBookIndex } from \"../services/vector-store.js\";\nimport { ensureDataDirs } from \"../services/constants.js\";\nimport { confirm } from \"./prompt.js\";\nimport { isInteractive, stdout } from \"./io.js\";\n\nexport const deleteCommand = async (id: string, options: { force?: boolean }) => {\n await ensureDataDirs();\n const resolvedId = await resolveBookId(id);\n if (!resolvedId) {\n throw new Error(`Book not found: ${id}`);\n }\n const book = await getBook(resolvedId);\n if (!book) {\n throw new Error(`Book not found: ${id}`);\n }\n\n if (!options.force) {\n if (!isInteractive()) {\n throw new Error(\"Delete confirmation requires an interactive terminal. Use --force to bypass.\");\n }\n const ok = await confirm(`Delete \"${book.title}\" (${book.id})? [y/N] `);\n if (!ok) {\n stdout(\"Cancelled.\");\n return;\n }\n }\n\n await deleteBook(resolvedId);\n await deleteBookIndex(resolvedId);\n if (book.epubPath) {\n await unlink(book.epubPath).catch(() => undefined);\n }\n stdout(`Deleted book ${book.id}`);\n};\n","import { deleteCommand } from \"../delete.js\";\n\nexport const registerBookDelete = (program: import(\"commander\").Command) => {\n program\n .command(\"delete\")\n .description(\"Remove book, EPUB, and vectors\")\n .argument(\"<id>\", \"Book id or prefix\")\n .option(\"--force\", \"Skip confirmation\")\n .action(async (id: string, options: { force?: boolean }) => {\n await deleteCommand(id, { force: options.force });\n });\n};\n","import { getBook, getBookBatchChunks } from \"../db/queries.js\";\nimport { resumeIngest, resumeLocalIngest } from \"../services/ingest.js\";\nimport { ensureDataDirs, requireOpenAIKey } from \"../services/constants.js\";\nimport { resolveBookId } from \"./utils.js\";\nimport { stdout } from \"./io.js\";\nimport type { BookChunk } from \"../shared/types.js\";\n\nexport const resumeCommand = async (id: string) => {\n requireOpenAIKey();\n await ensureDataDirs();\n\n const resolvedId = await resolveBookId(id);\n if (!resolvedId) {\n throw new Error(`Book not found: ${id}`);\n }\n\n const book = await getBook(resolvedId);\n if (!book) {\n throw new Error(`Book not found: ${id}`);\n }\n\n if (book.indexedAt) {\n stdout(`Book \"${book.title}\" is already indexed (${book.chunkCount} chunks).`);\n return;\n }\n\n if (book.batchId) {\n const rawChunks = await getBookBatchChunks(resolvedId);\n if (!rawChunks) {\n throw new Error(`No stored chunks found for book \"${book.title}\". Re-ingest with \"mycroft book ingest --batch\".`);\n }\n\n const chunks: BookChunk[] = JSON.parse(rawChunks);\n const result = await resumeIngest(resolvedId, chunks, book.batchId, book.batchFileId ?? book.batchId);\n\n if (result.status === \"completed\") {\n stdout(`\\nDone. Book \"${book.title}\" indexed as ${book.id}`);\n } else if (result.status === \"resubmitted\") {\n stdout(`\\nBatch failed and was re-submitted (${result.batchId}). Run resume again later.`);\n } else {\n stdout(`\\nBatch still in progress (${result.status}: ${result.completed}/${result.total}). Run resume again later.`);\n }\n return;\n }\n\n if (!book.ingestResumePath || book.ingestState !== \"pending\") {\n throw new Error(`Book \"${book.title}\" has no resumable ingest. Re-ingest to start one.`);\n }\n\n const result = await resumeLocalIngest(resolvedId, book.ingestResumePath, book.chunkCount ?? 0);\n if (result.status === \"completed\") {\n stdout(`\\nDone. Book \"${book.title}\" indexed as ${book.id}`);\n }\n};\n","import { resumeCommand } from \"../resume.js\";\n\nexport const registerBookResume = (\n program: import(\"commander\").Command,\n ingest?: import(\"commander\").Command,\n) => {\n const target = ingest ?? program.command(\"ingest\");\n\n target\n .command(\"resume\")\n .description(\"Resume a pending ingestion\")\n .argument(\"<id>\", \"Book id or prefix\")\n .addHelpText(\n \"after\",\n `\\nEXAMPLES\\n mycroft book ingest resume 8f2c1a4b\\n\\nNOTES\\n Resumes either batch or non-batch ingests if interrupted.\\n`\n )\n .action(async (id: string) => {\n await resumeCommand(id);\n });\n};\n","import { configPath } from \"../config.js\";\nimport { stdout } from \"./io.js\";\n\nexport const configCommand = async () => {\n const path = configPath();\n stdout(path);\n};\n","import { configCommand } from \"../config.js\";\n\nexport const registerConfigPath = (program: import(\"commander\").Command) => {\n program\n .command(\"path\")\n .description(\"Print config path\")\n .action(async () => {\n await configCommand();\n });\n};\n","import { ensureConfigDirs, configPath, loadConfig } from \"../config.js\";\nimport { mkdir, writeFile, access } from \"node:fs/promises\";\nimport { stdout } from \"./io.js\";\n\nexport const initConfigCommand = async () => {\n const path = configPath();\n await ensureConfigDirs(path);\n try {\n await access(path);\n stdout(`Config already exists: ${path}`);\n return;\n } catch {\n // file does not exist\n }\n const resolved = await loadConfig();\n const template = {\n dataDir: \"~/.local/share/mycroft\",\n askEnabled: resolved.askEnabled,\n models: resolved.models,\n };\n await writeFile(path, JSON.stringify(template, null, 2), \"utf-8\");\n await mkdir(resolved.dataDir, { recursive: true });\n stdout(`Created config at ${path}`);\n};\n","import { initConfigCommand } from \"../init-config.js\";\n\nexport const registerConfigInit = (program: import(\"commander\").Command) => {\n program\n .command(\"init\")\n .description(\"Create default config file\")\n .action(async () => {\n await initConfigCommand();\n });\n};\n","import { configPath, loadConfig } from \"../config.js\";\nimport { stdout } from \"./io.js\";\n\nexport const resolveConfigCommand = async () => {\n const path = configPath();\n const config = await loadConfig();\n stdout(`Config: ${path}`);\n stdout(`Data dir: ${config.dataDir}`);\n stdout(`Ask enabled: ${config.askEnabled}`);\n stdout(`Models: embedding=${config.models.embedding} summary=${config.models.summary} chat=${config.models.chat}`);\n};\n","import { resolveConfigCommand } from \"../resolve-config.js\";\n\nexport const registerConfigResolve = (program: import(\"commander\").Command) => {\n program\n .command(\"resolve\")\n .description(\"Print resolved config values\")\n .action(async () => {\n await resolveConfigCommand();\n });\n};\n","import { ensureConfigDirs, configPath, loadConfig } from \"../config.js\";\nimport { writeFile } from \"node:fs/promises\";\nimport { prompt } from \"./prompt.js\";\nimport { isInteractive, stdout } from \"./io.js\";\n\nconst isDefault = (input: string) => input === \"\" || input.toLowerCase() === \"-y\";\n\nconst parseBoolean = (input: string, fallback: boolean) => {\n if (isDefault(input)) return fallback;\n const normalized = input.toLowerCase();\n if ([\"y\", \"yes\", \"true\", \"1\"].includes(normalized)) return true;\n if ([\"n\", \"no\", \"false\", \"0\"].includes(normalized)) return false;\n return fallback;\n};\n\nexport const onboardCommand = async () => {\n if (!isInteractive()) {\n throw new Error(\"Onboarding requires an interactive terminal.\");\n }\n const defaults = await loadConfig();\n const path = configPath();\n\n stdout(\"\\nmycroft\");\n stdout(\"Press Enter or type -y to accept defaults.\");\n\n const dataDirInput = await prompt(`Data directory [${defaults.dataDir}]: `);\n const dataDir = isDefault(dataDirInput) ? defaults.dataDir : dataDirInput;\n\n const askEnabledInput = await prompt(`Enable ask (LLM answers) [${defaults.askEnabled ? \"Y\" : \"N\"}]: `);\n const askEnabled = parseBoolean(askEnabledInput, defaults.askEnabled);\n\n const embeddingInput = await prompt(`Embedding model [${defaults.models.embedding}]: `);\n const embedding = isDefault(embeddingInput) ? defaults.models.embedding : embeddingInput;\n\n const summaryInput = await prompt(`Summary model [${defaults.models.summary}]: `);\n const summary = isDefault(summaryInput) ? defaults.models.summary : summaryInput;\n\n const chatInput = await prompt(`Chat model [${defaults.models.chat}]: `);\n const chat = isDefault(chatInput) ? defaults.models.chat : chatInput;\n\n await ensureConfigDirs(path);\n await writeFile(\n path,\n JSON.stringify(\n {\n dataDir,\n askEnabled,\n models: {\n embedding,\n summary,\n chat,\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n\n stdout(\"\\nSetup complete.\");\n stdout(`Config: ${path}`);\n stdout(`Data dir: ${dataDir}`);\n\n if (!process.env.OPENAI_API_KEY) {\n stdout(\"\\nOPENAI_API_KEY is not set.\");\n stdout(\"Export it to enable embeddings and chat:\");\n stdout(\" export OPENAI_API_KEY=\\\"...\\\"\");\n }\n\n stdout(\"\\nNext step:\");\n stdout(\" mycroft book ingest /path/to/book.epub\");\n};\n","import { onboardCommand } from \"../onboard.js\";\n\nexport const registerConfigOnboard = (program: import(\"commander\").Command) => {\n program\n .command(\"onboard\")\n .description(\"Initialize config and show next step\")\n .action(async () => {\n await onboardCommand();\n });\n};\n","import { randomUUID } from \"node:crypto\";\nimport { embed, generateText } from \"ai\";\nimport { openai } from \"@ai-sdk/openai\";\nimport { getBook, getChatMessages, getChatSession, insertChatMessage, insertChatSession, listChatSessions, updateChatSession } from \"../db/queries.js\";\nimport type { ChatMessage, ChatSession, ChatSessionSummary } from \"../shared/types.js\";\nimport { ensureDataDirs, getModels, isAskEnabled, requireOpenAIKey } from \"./constants.js\";\nimport { queryBookIndex } from \"./vector-store.js\";\nimport { resolveBookId } from \"../commands/utils.js\";\n\nconst MAX_RECENT_MESSAGES = 12;\nconst SUMMARY_TRIGGER_MESSAGES = 24;\nconst SUMMARY_TARGET_WORDS = 160;\n\ntype ChatAskOptions = {\n topK: number;\n maxChapter?: number;\n};\n\nconst formatContext = (chunks: Array<{ content: string; chapterTitle: string; chapterIndex: number }>) =>\n chunks\n .map(\n (chunk, index) =>\n `Excerpt [${index + 1}] (${chunk.chapterTitle || `Chapter ${chunk.chapterIndex + 1}`}):\\n${chunk.content}`\n )\n .join(\"\\n\\n\");\n\nconst estimateTokens = (text: string): number => Math.ceil(text.length / 4);\n\nconst summarizeMessages = async (messages: ChatMessage[]): Promise<string> => {\n const transcript = messages\n .map((message) => `${message.role.toUpperCase()}: ${message.content}`)\n .join(\"\\n\\n\");\n const models = await getModels();\n const { text } = await generateText({\n model: openai(models.summary),\n prompt: `Summarize this conversation so far in ~${SUMMARY_TARGET_WORDS} words. Focus on facts, decisions, and unresolved questions.\\n\\n${transcript}`,\n temperature: 0.3,\n });\n return text.trim();\n};\n\nconst buildConversationContext = (session: ChatSession, messages: ChatMessage[]) => {\n const summary = session.summary ? `Conversation summary:\\n${session.summary}` : \"\";\n const recent = messages\n .slice(-MAX_RECENT_MESSAGES)\n .map((message) => `${message.role.toUpperCase()}: ${message.content}`)\n .join(\"\\n\\n\");\n return [summary, recent].filter(Boolean).join(\"\\n\\n\");\n};\n\nconst maybeSummarizeSession = async (session: ChatSession, messages: ChatMessage[], updatedAt: number) => {\n if (messages.length < SUMMARY_TRIGGER_MESSAGES) return;\n const summary = await summarizeMessages(messages.slice(0, -MAX_RECENT_MESSAGES));\n await updateChatSession(session.id, { summary, updatedAt });\n};\n\nexport const listSessions = async (): Promise<ChatSessionSummary[]> => listChatSessions();\n\nexport const getSession = async (id: string): Promise<ChatSession | null> => getChatSession(id);\n\nexport const getSessionMessages = async (sessionId: string, limit?: number) => getChatMessages(sessionId, limit);\n\nexport const startSession = async (bookId: string, title?: string): Promise<ChatSession> => {\n await ensureDataDirs();\n const resolvedId = await resolveBookId(bookId);\n if (!resolvedId) {\n throw new Error(`Book not found: ${bookId}`);\n }\n const sessionId = randomUUID();\n await insertChatSession({\n id: sessionId,\n bookId: resolvedId,\n title: title ?? null,\n summary: null,\n });\n const session = await getChatSession(sessionId);\n if (!session) {\n throw new Error(\"Failed to create chat session.\");\n }\n return session;\n};\n\nexport const chatAsk = async (sessionId: string, question: string, options: ChatAskOptions) => {\n if (!(await isAskEnabled())) {\n throw new Error(\"Ask is disabled in config (askEnabled: false). Enable it to use this command.\");\n }\n requireOpenAIKey();\n await ensureDataDirs();\n\n const session = await getChatSession(sessionId);\n if (!session) {\n throw new Error(`Chat session not found: ${sessionId}`);\n }\n const book = await getBook(session.bookId);\n if (!book) {\n throw new Error(`Book not found: ${session.bookId}`);\n }\n\n const models = await getModels();\n const { embedding } = await embed({\n model: openai.embeddingModel(models.embedding),\n value: question,\n });\n\n const narrativeStart = book.narrativeStartIndex ?? 0;\n const userProgress = book.progressChapter ?? null;\n const maxChapterIndex = options.maxChapter !== undefined\n ? narrativeStart + options.maxChapter\n : userProgress !== null\n ? narrativeStart + userProgress\n : undefined;\n\n const retrievalLimit = options.topK * 3;\n const allMatches = await queryBookIndex(session.bookId, embedding, question, retrievalLimit, maxChapterIndex);\n const summaries = allMatches.filter((m) => m.type === \"summary\");\n const chunks = allMatches.filter((m) => m.type !== \"summary\");\n const topSummaries = summaries.slice(0, 2);\n const topChunks = chunks.slice(0, Math.max(0, options.topK - topSummaries.length));\n const selectedMatches = [...topSummaries, ...topChunks];\n const context = formatContext(selectedMatches);\n\n const messages = await getChatMessages(sessionId);\n const conversation = buildConversationContext(session, messages);\n\n const now = Date.now();\n const userMessage: ChatMessage = {\n id: randomUUID(),\n sessionId,\n role: \"user\",\n content: question,\n tokenCount: estimateTokens(question),\n createdAt: now,\n };\n await insertChatMessage(userMessage);\n\n const prompt = [\n conversation ? `Conversation:\\n${conversation}` : \"\",\n `Question: ${question}`,\n context,\n ].filter(Boolean).join(\"\\n\\n\");\n\n const { text } = await generateText({\n model: openai(models.chat),\n system: `You are a reading companion helping readers understand this book.\\n\\nGuidelines:\\n- Use the provided chapter summaries and excerpts to answer questions\\n- Chapter summaries provide high-level context about characters, events, and plot\\n- Excerpts provide specific details and quotes\\n- When asked for recaps or \\\"what happened\\\", synthesize from summaries\\n- Don't cite table of contents, front matter, or structural elements\\n- If truly unsure, briefly say so - but try to answer from available context first\\n- Cite sources using [1], [2], etc. at the end of relevant sentences\\n- The context may be limited to earlier chapters only - don't infer beyond what's provided`,\n prompt,\n });\n\n const assistantMessage: ChatMessage = {\n id: randomUUID(),\n sessionId,\n role: \"assistant\",\n content: text,\n tokenCount: estimateTokens(text),\n createdAt: now,\n };\n await insertChatMessage(assistantMessage);\n const updatedAt = Date.now();\n await updateChatSession(sessionId, { updatedAt });\n await maybeSummarizeSession(session, [...messages, userMessage, assistantMessage], updatedAt);\n\n return { answer: text, sources: selectedMatches };\n};\n","import { startSession } from \"../../services/chat.js\";\nimport { stdout } from \"../io.js\";\n\nexport const registerChatStart = (program: import(\"commander\").Command) => {\n program\n .command(\"start\")\n .description(\"Start a chat session for a book\")\n .argument(\"<id>\", \"Book id or prefix\")\n .option(\"--title <title>\", \"Session title\")\n .action(async (id: string, options: { title?: string }) => {\n const session = await startSession(id, options.title);\n stdout(`Started chat session ${session.id} for book ${session.bookId}`);\n });\n};\n","import { listChatSessions } from \"../../db/queries.js\";\nimport type { ChatSessionSummary } from \"../../shared/types.js\";\n\nexport const resolveChatSessionId = async (input: string): Promise<string | null> => {\n const sessions: ChatSessionSummary[] = await listChatSessions();\n const exact = sessions.find((session) => session.id === input);\n if (exact) return exact.id;\n const matches = sessions.filter((session) => session.id.startsWith(input));\n if (matches.length === 1) return matches[0]!.id;\n if (matches.length > 1) {\n throw new Error(`Ambiguous session id prefix \"${input}\" (${matches.length} matches)`);\n }\n return null;\n};\n","import { chatAsk } from \"../../services/chat.js\";\nimport { resolveChatSessionId } from \"./utils.js\";\nimport { stdout } from \"../io.js\";\nimport { parseQueryOptions } from \"../query-options.js\";\n\nexport const registerChatAsk = (program: import(\"commander\").Command) => {\n program\n .command(\"ask\")\n .description(\"Ask a question in a chat session\")\n .argument(\"<session>\", \"Chat session id or prefix\")\n .argument(\"<question>\", \"Question to ask\")\n .option(\"--top-k <n>\", \"Number of passages to retrieve\", \"5\")\n .option(\"--max-chapter <n>\", \"Spoiler-free limit (0-based within narrative)\")\n .action(async (\n sessionId: string,\n question: string,\n options: { topK: string; maxChapter?: string }\n ) => {\n const { topK, maxChapter } = parseQueryOptions(options);\n\n const resolvedId = await resolveChatSessionId(sessionId);\n if (!resolvedId) {\n throw new Error(`Chat session not found: ${sessionId}`);\n }\n const { answer, sources } = await chatAsk(resolvedId, question, { topK, maxChapter });\n stdout(answer);\n\n if (sources.length > 0) {\n stdout(\"\\nSources:\");\n sources.forEach((match, index) => {\n const title = match.chapterTitle || `Chapter ${match.chapterIndex + 1}`;\n const excerpt = match.content.slice(0, 120).replace(/\\s+/g, \" \");\n stdout(`[${index + 1}] ${title}: ${excerpt}`);\n });\n }\n });\n};\n","import { listSessions } from \"../../services/chat.js\";\nimport { stdout } from \"../io.js\";\n\nconst formatDate = (timestamp: number | null) => {\n if (!timestamp) return \"-\";\n return new Date(timestamp).toISOString().slice(0, 10);\n};\n\nexport const registerChatList = (program: import(\"commander\").Command) => {\n program\n .command(\"list\")\n .description(\"List chat sessions\")\n .action(async () => {\n const sessions = await listSessions();\n if (sessions.length === 0) {\n stdout(\"No chat sessions yet.\");\n return;\n }\n\n stdout(\"ID | Book | Updated | Title\");\n stdout(\"---------|------|---------|------\");\n for (const session of sessions) {\n const shortId = session.id.slice(0, 8);\n const book = session.bookTitle || session.bookId.slice(0, 8);\n const updated = formatDate(session.updatedAt);\n const title = session.title || \"-\";\n stdout(`${shortId} | ${book} | ${updated} | ${title}`);\n }\n });\n};\n","import { getSession, getSessionMessages } from \"../../services/chat.js\";\nimport { resolveChatSessionId } from \"./utils.js\";\nimport { stdout } from \"../io.js\";\n\nexport const registerChatShow = (program: import(\"commander\").Command) => {\n program\n .command(\"show\")\n .description(\"Show chat session details\")\n .argument(\"<session>\", \"Chat session id or prefix\")\n .option(\"--tail <n>\", \"Show last N messages\", \"10\")\n .action(async (sessionId: string, options: { tail: string }) => {\n const tail = Number(options.tail);\n if (!Number.isFinite(tail) || tail <= 0) {\n throw new Error(\"--tail must be a positive number.\");\n }\n\n const resolvedId = await resolveChatSessionId(sessionId);\n if (!resolvedId) {\n throw new Error(`Chat session not found: ${sessionId}`);\n }\n const session = await getSession(resolvedId);\n if (!session) {\n throw new Error(`Chat session not found: ${sessionId}`);\n }\n stdout(`ID: ${session.id}`);\n stdout(`Book ID: ${session.bookId}`);\n stdout(`Title: ${session.title ?? \"-\"}`);\n const updated = session.updatedAt ? new Date(session.updatedAt).toISOString() : \"-\";\n stdout(`Updated: ${updated}`);\n\n const messages = await getSessionMessages(resolvedId, tail);\n if (messages.length === 0) {\n stdout(\"\\nNo messages yet.\");\n return;\n }\n\n stdout(\"\\nMessages:\");\n messages.forEach((message) => {\n stdout(`[${message.role}] ${message.content}`);\n });\n });\n};\n","import { chatAsk, getSession } from \"../../services/chat.js\";\nimport { resolveChatSessionId } from \"./utils.js\";\nimport { isInteractive, stdout } from \"../io.js\";\nimport { prompt } from \"../prompt.js\";\nimport { parseQueryOptions } from \"../query-options.js\";\n\nconst shouldExit = (input: string) => {\n const normalized = input.trim().toLowerCase();\n return normalized === \"exit\" || normalized === \"quit\" || normalized === \":q\";\n};\n\nexport const registerChatRepl = (program: import(\"commander\").Command) => {\n program\n .command(\"repl\")\n .description(\"Start interactive chat session\")\n .argument(\"<session>\", \"Chat session id or prefix\")\n .option(\"--top-k <n>\", \"Number of passages to retrieve\", \"5\")\n .option(\"--max-chapter <n>\", \"Spoiler-free limit (0-based within narrative)\")\n .action(async (\n sessionId: string,\n options: { topK: string; maxChapter?: string }\n ) => {\n if (!isInteractive()) {\n throw new Error(\"Chat repl requires an interactive terminal.\");\n }\n const { topK, maxChapter } = parseQueryOptions(options);\n\n const resolvedId = await resolveChatSessionId(sessionId);\n if (!resolvedId) {\n throw new Error(`Chat session not found: ${sessionId}`);\n }\n const session = await getSession(resolvedId);\n if (!session) {\n throw new Error(`Chat session not found: ${sessionId}`);\n }\n\n stdout(`Chatting in session ${session.id}. Type 'exit' to quit.`);\n\n while (true) {\n const question = await prompt(\"You: \");\n if (!question.trim()) continue;\n if (shouldExit(question)) break;\n const { answer, sources } = await chatAsk(session.id, question, { topK, maxChapter });\n stdout(`\\n${answer}`);\n if (sources.length > 0) {\n stdout(\"\\nSources:\");\n sources.forEach((match, index) => {\n const title = match.chapterTitle || `Chapter ${match.chapterIndex + 1}`;\n const excerpt = match.content.slice(0, 120).replace(/\\s+/g, \" \");\n stdout(`[${index + 1}] ${title}: ${excerpt}`);\n });\n }\n stdout(\"\");\n }\n });\n};\n","import { registerChatStart } from \"./start.js\";\nimport { registerChatAsk } from \"./ask.js\";\nimport { registerChatList } from \"./list.js\";\nimport { registerChatShow } from \"./show.js\";\nimport { registerChatRepl } from \"./repl.js\";\n\nexport const registerChatCommands = (program: import(\"commander\").Command) => {\n const chat = program.command(\"chat\").description(\"Run multi-turn chat sessions\");\n registerChatStart(chat);\n registerChatAsk(chat);\n registerChatList(chat);\n registerChatShow(chat);\n registerChatRepl(chat);\n};\n"],"mappings":"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","names":["readFile","openai","CHARS_PER_TOKEN","openai","submitBatchEmbeddings","program","program","program","openai","openai","program","embed","openai","embed","openai","program","unlink","unlink","program","result","program","program","mkdir","writeFile","access","access","writeFile","mkdir","program","program","writeFile","writeFile","program","randomUUID","embed","generateText","openai","SUMMARY_TARGET_WORDS","formatContext","estimateTokens","generateText","openai","randomUUID","embed","prompt","program","program","formatDate","program","program","program","program","readFile"]}
|
package/package.json
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fs/mycroft",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"mycroft": "./bin/mycroft.js"
|
|
8
8
|
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/fabe/mycroft.git"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/fabe/mycroft",
|
|
9
14
|
"files": [
|
|
10
15
|
"bin",
|
|
11
16
|
"dist",
|
|
@@ -30,6 +35,7 @@
|
|
|
30
35
|
"better-sqlite3": "^11.2.0",
|
|
31
36
|
"chalk": "^5.4.1",
|
|
32
37
|
"commander": "^12.1.0",
|
|
38
|
+
"openai": "^4.104.0",
|
|
33
39
|
"vectra": "^0.12.3"
|
|
34
40
|
},
|
|
35
41
|
"devDependencies": {
|