@fs/mycroft 0.2.0 → 0.4.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.
Files changed (65) hide show
  1. package/README.md +23 -0
  2. package/completions/mycroft.bash +11 -1
  3. package/completions/mycroft.fish +15 -2
  4. package/completions/mycroft.zsh +14 -1
  5. package/dist/batch-embedder-6IIWAZPW.js +14 -0
  6. package/dist/batch-embedder-6IIWAZPW.js.map +1 -0
  7. package/dist/batch-embedder-7DGZAQKL.js +14 -0
  8. package/dist/batch-embedder-7DGZAQKL.js.map +1 -0
  9. package/dist/batch-embedder-C2E6OHBQ.js +14 -0
  10. package/dist/batch-embedder-C2E6OHBQ.js.map +1 -0
  11. package/dist/batch-embedder-IZDBS3IL.js +13 -0
  12. package/dist/batch-embedder-IZDBS3IL.js.map +1 -0
  13. package/dist/batch-embedder-LYCZDYI4.js +15 -0
  14. package/dist/batch-embedder-LYCZDYI4.js.map +1 -0
  15. package/dist/batch-embedder-RHKD2OJD.js +14 -0
  16. package/dist/batch-embedder-RHKD2OJD.js.map +1 -0
  17. package/dist/batch-embedder-VQZUI7R6.js +14 -0
  18. package/dist/batch-embedder-VQZUI7R6.js.map +1 -0
  19. package/dist/batch-embedder-ZJZLNLOK.js +14 -0
  20. package/dist/batch-embedder-ZJZLNLOK.js.map +1 -0
  21. package/dist/batch-summarizer-7MCT4HJB.js +14 -0
  22. package/dist/batch-summarizer-7MCT4HJB.js.map +1 -0
  23. package/dist/batch-summarizer-BMIBVFAE.js +14 -0
  24. package/dist/batch-summarizer-BMIBVFAE.js.map +1 -0
  25. package/dist/batch-summarizer-CM3NO7TK.js +14 -0
  26. package/dist/batch-summarizer-CM3NO7TK.js.map +1 -0
  27. package/dist/chunk-35EO53CC.js +8058 -0
  28. package/dist/chunk-35EO53CC.js.map +1 -0
  29. package/dist/chunk-57ZGGKEF.js +8060 -0
  30. package/dist/chunk-57ZGGKEF.js.map +1 -0
  31. package/dist/chunk-6DLQHHCC.js +249 -0
  32. package/dist/chunk-6DLQHHCC.js.map +1 -0
  33. package/dist/chunk-7CO4PMU5.js +92 -0
  34. package/dist/chunk-7CO4PMU5.js.map +1 -0
  35. package/dist/chunk-7DUQNGEK.js +253 -0
  36. package/dist/chunk-7DUQNGEK.js.map +1 -0
  37. package/dist/chunk-7IPX4MKA.js +4637 -0
  38. package/dist/chunk-7IPX4MKA.js.map +1 -0
  39. package/dist/chunk-7NLMBXXY.js +6438 -0
  40. package/dist/chunk-7NLMBXXY.js.map +1 -0
  41. package/dist/chunk-BR2PM6D3.js +11047 -0
  42. package/dist/chunk-BR2PM6D3.js.map +1 -0
  43. package/dist/chunk-KGG7WEYE.js +162 -0
  44. package/dist/chunk-KGG7WEYE.js.map +1 -0
  45. package/dist/chunk-LV52FEMB.js +169 -0
  46. package/dist/chunk-LV52FEMB.js.map +1 -0
  47. package/dist/chunk-QRDUQX63.js +256 -0
  48. package/dist/chunk-QRDUQX63.js.map +1 -0
  49. package/dist/chunk-R3FOJK5A.js +2088 -0
  50. package/dist/chunk-R3FOJK5A.js.map +1 -0
  51. package/dist/chunk-T6X7DRBN.js +275 -0
  52. package/dist/chunk-T6X7DRBN.js.map +1 -0
  53. package/dist/chunk-VBEGUDHG.js +103 -0
  54. package/dist/chunk-VBEGUDHG.js.map +1 -0
  55. package/dist/chunk-XXO66RCF.js +94 -0
  56. package/dist/chunk-XXO66RCF.js.map +1 -0
  57. package/dist/cli.js +769 -317
  58. package/dist/cli.js.map +1 -1
  59. package/dist/fileFromPath-FLANAQWT.js +128 -0
  60. package/dist/fileFromPath-FLANAQWT.js.map +1 -0
  61. package/dist/main-36PRDAPE.js +1857 -0
  62. package/dist/main-36PRDAPE.js.map +1 -0
  63. package/dist/main-B3QJZGLU.js +1859 -0
  64. package/dist/main-B3QJZGLU.js.map +1 -0
  65. package/package.json +14 -2
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/config.ts","../src/commands/io.ts","../src/services/epub-parser.ts","../src/services/constants.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/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":["#!/usr/bin/env node\nimport { 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 { 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 registerBookIngest(book);\n registerBookList(book);\n registerBookShow(book);\n registerBookAsk(book);\n registerBookSearch(book);\n registerBookDelete(book);\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\nconst 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\nmain();\n","import { mkdir, readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\n\nexport type ConfigModels = {\n embedding: string;\n summary: string;\n chat: string;\n};\n\nexport type AppConfig = {\n dataDir: string;\n askEnabled: boolean;\n models: ConfigModels;\n};\n\nconst DEFAULT_CONFIG: AppConfig = {\n dataDir: \"~/.local/share/mycroft\",\n askEnabled: true,\n models: {\n embedding: \"text-embedding-3-small\",\n summary: \"gpt-5-nano\",\n chat: \"gpt-5.1\",\n },\n};\n\nconst expandHome = (input: string): string => {\n if (!input.startsWith(\"~\")) return input;\n return join(homedir(), input.slice(1));\n};\n\nconst resolvePath = (input: string): string => resolve(expandHome(input));\n\nconst getConfigPath = (): string => {\n const override = process.env.MYCROFT_CONFIG;\n if (override) return resolvePath(override);\n return resolvePath(\"~/.config/mycroft/config.json\");\n};\n\nconst normalizeModels = (models?: Partial<ConfigModels>): ConfigModels => ({\n embedding: models?.embedding || DEFAULT_CONFIG.models.embedding,\n summary: models?.summary || DEFAULT_CONFIG.models.summary,\n chat: models?.chat || DEFAULT_CONFIG.models.chat,\n});\n\ntype ConfigOverrides = {\n dataDir?: string;\n};\n\nlet overrides: ConfigOverrides = {};\n\nexport const setConfigOverrides = (next: ConfigOverrides) => {\n overrides = { ...overrides, ...next };\n};\n\nconst normalizeConfig = (input: Partial<AppConfig> | null): AppConfig => {\n const dataDirEnv = process.env.MYCROFT_DATA_DIR;\n const dataDir = overrides.dataDir || dataDirEnv || input?.dataDir || DEFAULT_CONFIG.dataDir;\n return {\n dataDir,\n askEnabled: input?.askEnabled ?? DEFAULT_CONFIG.askEnabled,\n models: normalizeModels(input?.models),\n };\n};\n\nconst readConfigFile = async (path: string): Promise<Partial<AppConfig> | null> => {\n try {\n const contents = await readFile(path, \"utf-8\");\n return JSON.parse(contents) as Partial<AppConfig>;\n } catch {\n return null;\n }\n};\n\nexport const loadConfig = async (): Promise<AppConfig> => {\n const configPath = getConfigPath();\n const data = await readConfigFile(configPath);\n const normalized = normalizeConfig(data);\n return {\n ...normalized,\n dataDir: resolvePath(normalized.dataDir),\n };\n};\n\nexport const ensureConfigDirs = async (configPath?: string) => {\n const path = configPath || getConfigPath();\n await mkdir(dirname(path), { recursive: true });\n};\n\nexport const configPath = () => getConfigPath();\n","import chalk from \"chalk\";\n\nconst isTTY = () => Boolean(process.stdout.isTTY);\nexport const isInteractive = () => Boolean(process.stdin.isTTY && process.stdout.isTTY);\n\nexport const formatDim = (text: string) => (isTTY() ? chalk.dim(text) : text);\nexport const formatError = (text: string) => (isTTY() ? chalk.red(text) : text);\nexport const formatBold = (text: string) => (isTTY() ? chalk.bold(text) : text);\nexport const formatWarn = (text: string) => (isTTY() ? chalk.yellow(text) : text);\n\nexport const stdout = (message: string) => {\n process.stdout.write(message.endsWith(\"\\n\") ? message : `${message}\\n`);\n};\n\nexport const stderr = (message: string) => {\n process.stderr.write(message.endsWith(\"\\n\") ? message : `${message}\\n`);\n};\n\nexport const printError = (message: string) => {\n stderr(formatError(`Error: ${message}`));\n};\n\nexport const logInfo = (message: string) => {\n stderr(message);\n};\n\nexport const logWarn = (message: string) => {\n stderr(formatWarn(message));\n};\n\nexport const handleSigint = (onCancel?: () => void) => {\n const handler = () => {\n if (onCancel) onCancel();\n stderr(\"\\nCancelled.\");\n process.exit(130);\n };\n process.once(\"SIGINT\", handler);\n return () => process.off(\"SIGINT\", handler);\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(/&nbsp;/g, \" \")\n .replace(/&amp;/g, \"&\")\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/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 { mkdir } from \"node:fs/promises\";\nimport { loadConfig } from \"../config.js\";\nimport { logInfo, logWarn } from \"../commands/io.js\";\n\nexport const CHUNK_SIZE: number = 1000;\nexport const CHUNK_OVERLAP: number = 100;\nexport const SEPARATORS = [\"\\n\\n\", \"\\n\", \". \", \" \", \"\"] as const;\n\nexport const SUMMARY_MAX_TOKENS = 30000;\nexport const SUMMARY_CONCURRENCY = 3;\nexport const SUMMARY_TARGET_WORDS = 250;\n\nexport type ResolvedPaths = {\n dataDir: string;\n booksDir: string;\n vectorsDir: string;\n dbPath: string;\n};\n\nexport const resolvePaths = async (): Promise<ResolvedPaths> => {\n const config = await loadConfig();\n const dataDir = config.dataDir;\n return {\n dataDir,\n booksDir: `${dataDir}/books`,\n vectorsDir: `${dataDir}/vectors`,\n dbPath: `${dataDir}/metadata.db`,\n };\n};\n\nexport const ensureDataDirs = async () => {\n const paths = await resolvePaths();\n await mkdir(paths.dataDir, { recursive: true });\n await mkdir(paths.booksDir, { recursive: true });\n await mkdir(paths.vectorsDir, { recursive: true });\n return paths;\n};\n\nexport const getModels = async () => {\n const config = await loadConfig();\n return config.models;\n};\n\nexport const isAskEnabled = async () => {\n const config = await loadConfig();\n return config.askEnabled;\n};\n\nexport const requireOpenAIKey = () => {\n if (!process.env.OPENAI_API_KEY) {\n throw new Error(\"OPENAI_API_KEY is not set. Export it to use embeddings and chat.\");\n }\n};\n\nexport { logInfo, logWarn };\n","import { randomUUID } from \"node:crypto\";\nimport { mkdir, unlink, copyFile } from \"node:fs/promises\";\nimport { parseEpub } from \"./epub-parser.js\";\nimport { chunkChapters } from \"./chunker.js\";\nimport { embedChunks } from \"./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\";\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 }\n) => {\n const bookId = randomUUID();\n const paths = await ensureDataDirs();\n const fileName = `${bookId}.epub`;\n const bookPath = `${paths.booksDir}/${fileName}`;\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);\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 const embedStart = Date.now();\n const embedded = await embedChunks(allChunks);\n logInfo(`[Ingest] Embedded ${embedded.length} total chunks (${formatDuration(Date.now() - embedStart)})`);\n\n await addChunksToIndex(bookId, embedded);\n logInfo(`[Ingest] Added chunks to vector index`);\n\n await updateBook(bookId, { chunkCount: embedded.length, indexedAt: Date.now() });\n logInfo(`[Ingest] Updated book record with chunk count: ${embedded.length}`);\n } catch (error) {\n logWarn(`[Ingest] Error during chunking/embedding: ${error instanceof Error ? error.message : String(error)}`);\n await deleteBookIndex(bookId);\n await unlink(bookPath).catch(() => undefined);\n await deleteBook(bookId).catch(() => undefined);\n throw error;\n }\n\n logInfo(`[Ingest] Ingestion complete for ${bookId}`);\n return { id: bookId };\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\nexport const embedChunks = async (chunks: BookChunk[]): 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 for (let j = 0; j < batch.length; j++) {\n allEmbedded.push({\n ...batch[j]!,\n vector: embeddings[j] ?? [],\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 (chapters: Chapter[]): Promise<ChapterSummary[]> => {\n const summaries: ChapterSummary[] = [];\n\n logInfo(`[Summarizer] Starting summarization of ${chapters.length} chapters (concurrency: ${SUMMARY_CONCURRENCY})`);\n\n for (let i = 0; i < chapters.length; i += SUMMARY_CONCURRENCY) {\n const batch = chapters.slice(i, i + SUMMARY_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 + SUMMARY_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\"\n> & {\n chunkCount?: number;\n indexedAt?: number | null;\n progressChapter?: number | null;\n summaries?: string;\n narrativeStartIndex?: number | null;\n narrativeEndIndex?: number | 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});\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\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 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\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 }) => {\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 });\n stdout(`\\nDone. Book indexed as ${result.id}`);\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 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 .action(async (path: string, options: { manual?: boolean; summary?: boolean }) => {\n const summarize = Boolean(options.summary);\n await ingestCommand(path, { manual: options.manual, summarize });\n });\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 ? \"[indexed]\" : \"[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(\"\\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 { 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":["configPath","readFile","dirname","resolve","mkdir","mkdir","mkdir","openai","CHARS_PER_TOKEN","openai","mkdir","program","program","program","openai","openai","program","embed","openai","embed","openai","program","unlink","unlink","program","program","mkdir","access","access","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","dirname","resolve","readFile"]}
1
+ {"version":3,"sources":["../src/cli.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/shared/utils.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/status.ts","../src/commands/book/status.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":["#!/usr/bin/env node\nimport { 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 { registerBookStatus } from \"./commands/book/status.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 registerBookStatus(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\nconst 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\nmain();\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(/&nbsp;/g, \" \")\n .replace(/&amp;/g, \"&\")\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/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 let epubFile: Awaited<ReturnType<typeof initEpubFile>> | null = null;\n try {\n 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 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 epubFile?.destroy();\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 { submitBatchSummaries } from \"./batch-summarizer.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, Chapter } 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 && !options?.batch) {\n logInfo(`[Ingest] Generating summaries for ${chaptersToProcess.length} chapters...`);\n const summarizeStart = Date.now();\n const summaries = await summarizeAllChapters(chaptersToProcess);\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 if (options?.batch) {\n if (options?.summarize !== false) {\n // Batch mode with summaries: submit summary batch first, embedding batch later on resume\n logInfo(`[Ingest] Submitting ${chaptersToProcess.length} chapters for batch summarization`);\n const { batchId: summaryBatchId, inputFileId: summaryFileId, metadata } = await submitBatchSummaries(chaptersToProcess);\n await updateBook(bookId, {\n summaryBatchId,\n summaryBatchFileId: summaryFileId,\n summaryBatchChapters: JSON.stringify({ chapters: chaptersToProcess, metadata, selectedIndices, textChunks: chunks }),\n });\n logInfo(`[Ingest] Summary batch submitted (${summaryBatchId}). Use \"mycroft book ingest status ${bookId.slice(0, 8)}\" or \"mycroft book ingest resume ${bookId.slice(0, 8)}\".`);\n } else {\n // Batch mode without summaries: submit embedding batch directly\n logInfo(`[Ingest] Submitting ${chunks.length} chunks to OpenAI Batch API`);\n const { batchId, inputFileId } = await submitBatchEmbeddings(chunks);\n await updateBook(bookId, {\n batchId,\n batchFileId: inputFileId,\n batchChunks: JSON.stringify(chunks),\n });\n logInfo(`[Ingest] Batch submitted (${batchId}). Use \"mycroft book ingest status ${bookId.slice(0, 8)}\" or \"mycroft book ingest resume ${bookId.slice(0, 8)}\".`);\n }\n } else {\n const allChunks = [...chunks, ...adjustedSummaries];\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. Use \"mycroft book ingest status ${bookId.slice(0, 8)}\" or \"mycroft book ingest resume ${bookId.slice(0, 8)}\".`);\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 embedding 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\") {\n throw new Error(`Unexpected batch status: ${status.status}`);\n }\n\n // Batch completed but all requests failed — no output file\n if (!status.outputFileId) {\n logWarn(`[Resume] Batch ${batchId} completed but produced no output (${status.failed}/${status.total} failed). Re-submitting...`);\n await cleanupBatchFiles(batchFileId, null);\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 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 resumeSummaryBatch = async (\n bookId: string,\n summaryBatchId: string,\n summaryBatchFileId: string,\n storedData: { chapters: Chapter[]; metadata: import(\"./batch-summarizer.js\").SummaryBatchChapter[]; selectedIndices: number[]; textChunks: BookChunk[] },\n) => {\n const { checkBatchStatus, cleanupBatchFiles } = await import(\"./batch-embedder.js\");\n const { downloadBatchSummaryResults, submitMergePass, downloadMergeResults } = await import(\"./batch-summarizer.js\");\n\n logInfo(`[Resume] Checking summary batch ${summaryBatchId} for book ${bookId}`);\n const status = await checkBatchStatus(summaryBatchId);\n\n logInfo(`[Resume] Summary 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, phase: \"summary\" as const };\n }\n\n if (status.status === \"failed\" || status.status === \"expired\" || status.status === \"cancelled\") {\n logWarn(`[Resume] Summary batch ${summaryBatchId} ended with status \"${status.status}\". Re-submitting...`);\n await cleanupBatchFiles(summaryBatchFileId, status.outputFileId);\n\n const { submitBatchSummaries } = await import(\"./batch-summarizer.js\");\n const { batchId: newBatchId, inputFileId: newFileId, metadata: newMetadata } = await submitBatchSummaries(storedData.chapters);\n\n await updateBook(bookId, {\n summaryBatchId: newBatchId,\n summaryBatchFileId: newFileId,\n summaryBatchChapters: JSON.stringify({ ...storedData, metadata: newMetadata }),\n });\n logInfo(`[Resume] New summary batch submitted (${newBatchId}).`);\n return { status: \"resubmitted\" as const, batchId: newBatchId, phase: \"summary\" as const };\n }\n\n if (status.status !== \"completed\") {\n throw new Error(`Unexpected summary batch status: ${status.status}`);\n }\n\n // Batch completed but all requests failed — no output file\n if (!status.outputFileId) {\n logWarn(`[Resume] Summary batch ${summaryBatchId} completed but produced no output (${status.failed}/${status.total} failed). Re-submitting...`);\n await cleanupBatchFiles(summaryBatchFileId, null);\n\n const { submitBatchSummaries } = await import(\"./batch-summarizer.js\");\n const { batchId: newBatchId, inputFileId: newFileId, metadata: newMetadata } = await submitBatchSummaries(storedData.chapters);\n\n await updateBook(bookId, {\n summaryBatchId: newBatchId,\n summaryBatchFileId: newFileId,\n summaryBatchChapters: JSON.stringify({ ...storedData, metadata: newMetadata }),\n });\n logInfo(`[Resume] New summary batch submitted (${newBatchId}).`);\n return { status: \"resubmitted\" as const, batchId: newBatchId, phase: \"summary\" as const };\n }\n\n // Download summary results\n let { summaries, needsMergePass } = await downloadBatchSummaryResults(\n status.outputFileId,\n storedData.chapters,\n storedData.metadata,\n );\n await cleanupBatchFiles(summaryBatchFileId, status.outputFileId);\n\n // Handle two-pass chapters that need a merge\n if (needsMergePass.length > 0) {\n logInfo(`[Resume] ${needsMergePass.length} chapters need merge pass, submitting merge batch...`);\n const mergeResult = await submitMergePass(needsMergePass);\n\n // Store merge batch and wait for next resume\n await updateBook(bookId, {\n summaryBatchId: mergeResult.batchId,\n summaryBatchFileId: mergeResult.inputFileId,\n summaryBatchChapters: JSON.stringify({\n ...storedData,\n metadata: mergeResult.metadata,\n completedSummaries: summaries,\n isMergePass: true,\n }),\n });\n\n return { status: \"merge_submitted\" as const, batchId: mergeResult.batchId, phase: \"summary\" as const };\n }\n\n // All summaries are ready — build summary chunks and submit embedding batch\n return await finalizeSummariesAndSubmitEmbeddings(bookId, summaries, storedData);\n};\n\nexport const resumeMergeBatch = async (\n bookId: string,\n summaryBatchId: string,\n summaryBatchFileId: string,\n storedData: {\n chapters: Chapter[];\n metadata: import(\"./batch-summarizer.js\").SummaryBatchChapter[];\n selectedIndices: number[];\n textChunks: BookChunk[];\n completedSummaries: import(\"../shared/types.js\").ChapterSummary[];\n isMergePass: true;\n },\n) => {\n const { checkBatchStatus, cleanupBatchFiles } = await import(\"./batch-embedder.js\");\n const { downloadMergeResults } = await import(\"./batch-summarizer.js\");\n\n logInfo(`[Resume] Checking merge batch ${summaryBatchId} for book ${bookId}`);\n const status = await checkBatchStatus(summaryBatchId);\n\n logInfo(`[Resume] Merge 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, phase: \"summary\" as const };\n }\n\n if (status.status !== \"completed\") {\n throw new Error(`Unexpected merge batch status: ${status.status}`);\n }\n\n if (!status.outputFileId) {\n throw new Error(`Merge batch completed but produced no output (${status.failed}/${status.total} failed). Re-ingest to start over.`);\n }\n\n const mergedSummaries = await downloadMergeResults(\n status.outputFileId,\n storedData.metadata.map((m) => ({ chapterIndex: m.chapterIndex, title: m.title })),\n );\n await cleanupBatchFiles(summaryBatchFileId, status.outputFileId);\n\n // Combine previously completed single-pass summaries with the merged two-pass summaries\n const allSummaries = [...(storedData.completedSummaries || []), ...mergedSummaries];\n\n return await finalizeSummariesAndSubmitEmbeddings(bookId, allSummaries, storedData);\n};\n\nconst finalizeSummariesAndSubmitEmbeddings = async (\n bookId: string,\n summaries: import(\"../shared/types.js\").ChapterSummary[],\n storedData: { selectedIndices: number[]; textChunks: BookChunk[] },\n) => {\n const { submitBatchEmbeddings } = await import(\"./batch-embedder.js\");\n\n // Adjust chapter indices and store summaries\n const summaryRecords = summaries.map((s) => ({\n ...s,\n chapterIndex: storedData.selectedIndices[s.chapterIndex] ?? s.chapterIndex,\n }));\n\n await updateBook(bookId, {\n summaries: JSON.stringify(summaryRecords),\n });\n\n const summaryChunks: BookChunk[] = 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(`[Resume] Created ${summaryChunks.length} summary chunks from ${summaries.length} summaries`);\n\n // Submit embedding batch for text chunks + summary chunks\n const allChunks = [...storedData.textChunks, ...summaryChunks];\n logInfo(`[Resume] Submitting ${allChunks.length} chunks for batch embedding`);\n const { batchId, inputFileId } = await submitBatchEmbeddings(allChunks);\n\n await updateBook(bookId, {\n summaryBatchId: null,\n summaryBatchFileId: null,\n summaryBatchChapters: null,\n batchId,\n batchFileId: inputFileId,\n batchChunks: JSON.stringify(allChunks),\n });\n\n logInfo(`[Resume] Embedding batch submitted (${batchId}). Run resume again when batch completes.`);\n return { status: \"embeddings_submitted\" as const, batchId, phase: \"embedding\" 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, logWarn } 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 vector = embeddings[j] ?? [];\n if (vector.length === 0) {\n logWarn(`[Embedder] Chunk ${allEmbedded.length + j} has empty embedding`);\n }\n const embeddedChunk = {\n ...batch[j]!,\n vector,\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 indexCache = new Map<string, LocalIndex<VectorMetadata>>();\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 cached = indexCache.get(bookId);\n if (cached) return cached;\n\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 indexCache.set(bookId, index);\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 indexCache.delete(bookId);\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\";\nimport { CHARS_PER_TOKEN, SUMMARY_PROMPT, parseStructuredSummary, splitIntoSections } from \"../shared/summary.js\";\n\nconst estimateTokens = (text: string): number => Math.ceil(text.length / CHARS_PER_TOKEN);\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 });\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, SUMMARY_TARGET_WORDS),\n });\n\n return parseStructuredSummary(text, chapterIndex, title);\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): Promise<ChapterSummary[]> => {\n const summaries: ChapterSummary[] = [];\n\n logInfo(\n `[Summarizer] Starting summarization of ${chapters.length} chapters (concurrency: ${SUMMARY_CONCURRENCY})`\n );\n\n for (let i = 0; i < chapters.length; i += SUMMARY_CONCURRENCY) {\n const batch = chapters.slice(i, i + SUMMARY_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 + SUMMARY_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\" | \"batchChunks\" | \"ingestState\" | \"ingestResumePath\" | \"summaryBatchId\" | \"summaryBatchFileId\" | \"summaryBatchChapters\" | \"summaries\"\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 summaryBatchId?: string | null;\n summaryBatchFileId?: string | null;\n summaryBatchChapters?: 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 summaryBatchId: row.summary_batch_id ?? null,\n summaryBatchFileId: row.summary_batch_file_id ?? null,\n summaryBatchChapters: row.summary_batch_chapters ?? null,\n summaries: row.summaries ?? null,\n batchChunks: row.batch_chunks ?? 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 if (updates.summaryBatchId !== undefined) {\n fields.push(\"summary_batch_id = @summaryBatchId\");\n params.summaryBatchId = updates.summaryBatchId;\n }\n if (updates.summaryBatchFileId !== undefined) {\n fields.push(\"summary_batch_file_id = @summaryBatchFileId\");\n params.summaryBatchFileId = updates.summaryBatchFileId;\n }\n if (updates.summaryBatchChapters !== undefined) {\n fields.push(\"summary_batch_chapters = @summaryBatchChapters\");\n params.summaryBatchChapters = updates.summaryBatchChapters;\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 getBookSummaryBatchChapters = async (id: string): Promise<string | null> => {\n const db = await getDb();\n const row = db.prepare(\"SELECT summary_batch_chapters FROM books WHERE id = ?\").get(id) as { summary_batch_chapters?: string } | undefined;\n return row?.summary_batch_chapters ?? null;\n};\n\nexport const deleteBook = async (id: string) => {\n const db = await getDb();\n const deleteAll = db.transaction((bookId: string) => {\n db.prepare(\"DELETE FROM chat_messages WHERE session_id IN (SELECT id FROM chat_sessions WHERE book_id = ?)\").run(bookId);\n db.prepare(\"DELETE FROM chat_sessions WHERE book_id = ?\").run(bookId);\n db.prepare(\"DELETE FROM books WHERE id = ?\").run(bookId);\n });\n deleteAll(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 ?? Math.floor(Date.now() / 1000),\n updatedAt: session.updatedAt ?? Math.floor(Date.now() / 1000),\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 ?? Math.floor(Date.now() / 1000),\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.pragma(\"foreign_keys = ON\");\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 REFERENCES books(id) ON DELETE CASCADE,\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 REFERENCES chat_sessions(id) ON DELETE CASCADE,\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: any) => (col as { name: string }).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 ensureColumn(\"summary_batch_id\", \"summary_batch_id TEXT\");\n ensureColumn(\"summary_batch_file_id\", \"summary_batch_file_id TEXT\");\n ensureColumn(\"summary_batch_chapters\", \"summary_batch_chapters 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 const shortId = result.id.slice(0, 8);\n if (result.status === \"interrupted\") {\n stdout(`\\nIngest interrupted.`);\n stdout(` mycroft book ingest status ${shortId} # check progress`);\n stdout(` mycroft book ingest resume ${shortId} # continue ingestion`);\n return;\n }\n\n if (options.batch) {\n const batchType = options.summarize ? \"Summary batch\" : \"Embedding batch\";\n stdout(`\\n${batchType} submitted. Book registered as ${result.id}`);\n stdout(` mycroft book ingest status ${shortId} # check batch progress`);\n stdout(` mycroft book ingest resume ${shortId} # continue when 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 and summaries (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 --summary\\n mycroft book ingest status 8f2c1a4b\\n mycroft book ingest resume 8f2c1a4b\\n\\nNOTES\\n --batch submits work to the OpenAI Batch API and returns immediately.\\n When combined with --summary, summaries are batched first, then embeddings.\\n Use \"mycroft book ingest status <id>\" to check progress.\\n Use \"mycroft book ingest resume <id>\" to continue when a batch completes.\\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 * 1000).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, stdout } from \"./io.js\";\nimport { formatContext, renderSources, resolveMaxChapter } from \"../shared/utils.js\";\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 maxChapterIndex = resolveMaxChapter(book, options.maxChapter);\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 stdout(renderSources(selectedMatches));\n};\n","import type { BookRecord } from \"./types.js\";\n\nconst CHARS_PER_TOKEN = 4;\n\nexport const estimateTokens = (text: string): number => Math.ceil(text.length / CHARS_PER_TOKEN);\n\nexport type SourceMatch = {\n content: string;\n chapterTitle: string;\n chapterIndex: number;\n score?: number;\n type?: \"chunk\" | \"summary\";\n};\n\nexport const renderSources = (sources: SourceMatch[]): string => {\n if (sources.length === 0) return \"\";\n const lines = sources.map((match, index) => {\n const title = match.chapterTitle || `Chapter ${match.chapterIndex + 1}`;\n const excerpt = match.content.slice(0, 120).replace(/\\s+/g, \" \");\n return `[${index + 1}] ${title}: ${excerpt}`;\n });\n return `\\nSources:\\n${lines.join(\"\\n\")}`;\n};\n\nexport const resolveMaxChapter = (\n book: BookRecord,\n maxChapterOption?: number\n): number | undefined => {\n const narrativeStart = book.narrativeStartIndex ?? 0;\n const userProgress = book.progressChapter ?? null;\n if (maxChapterOption !== undefined) {\n return narrativeStart + maxChapterOption;\n }\n if (userProgress !== null) {\n return narrativeStart + userProgress;\n }\n return undefined;\n};\n\nexport const formatContext = (chunks: SourceMatch[]) =>\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","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 || !Number.isInteger(topK)) {\n throw new Error(\"--top-k must be a positive integer.\");\n }\n let maxChapter: number | undefined;\n if (options.maxChapter !== undefined) {\n const parsed = Number(options.maxChapter);\n if (!Number.isFinite(parsed) || parsed < 0 || !Number.isInteger(parsed)) {\n throw new Error(\"--max-chapter must be a non-negative integer.\");\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 .addHelpText(\n \"after\",\n `\\nEXAMPLES\\n mycroft book ask 8f2c1a4b \"Who is the main character?\"\\n mycroft book ask 8f2c1a4b \"What happened in chapter 3?\" --max-chapter 3\\n`\n )\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\";\nimport { resolveMaxChapter } from \"../shared/utils.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 = resolveMaxChapter(book, options.maxChapter);\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 .addHelpText(\n \"after\",\n `\\nEXAMPLES\\n mycroft book search 8f2c1a4b \"the storm scene\"\\n mycroft book search 8f2c1a4b \"betrayal\" --top-k 10\\n`\n )\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((err: NodeJS.ErrnoException) => {\n if (err.code !== \"ENOENT\") throw err;\n });\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 .addHelpText(\n \"after\",\n `\\nEXAMPLES\\n mycroft book delete 8f2c1a4b\\n mycroft book delete 8f2c1a4b --force\\n`\n )\n .action(async (id: string, options: { force?: boolean }) => {\n await deleteCommand(id, { force: options.force });\n });\n};\n","import { getBook, getBookBatchChunks, getBookSummaryBatchChapters } from \"../db/queries.js\";\nimport { resumeIngest, resumeLocalIngest, resumeSummaryBatch, resumeMergeBatch } 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 const shortId = resolvedId.slice(0, 8);\n\n // Phase 1: Summary batch pending\n if (book.summaryBatchId) {\n const rawData = await getBookSummaryBatchChapters(resolvedId);\n if (!rawData) {\n throw new Error(`No stored summary batch data for book \"${book.title}\". Re-ingest with \"mycroft book ingest --batch --summary\".`);\n }\n\n let storedData: any;\n try {\n storedData = JSON.parse(rawData);\n } catch {\n throw new Error(`Corrupt summary batch data for book \"${book.title}\". Re-ingest with \"mycroft book ingest --batch --summary\".`);\n }\n\n let result;\n if (storedData.isMergePass) {\n result = await resumeMergeBatch(resolvedId, book.summaryBatchId, book.summaryBatchFileId ?? book.summaryBatchId, storedData);\n } else {\n result = await resumeSummaryBatch(resolvedId, book.summaryBatchId, book.summaryBatchFileId ?? book.summaryBatchId, storedData);\n }\n\n if (result.status === \"embeddings_submitted\") {\n stdout(`\\nSummaries complete. Embedding batch submitted (${result.batchId}).`);\n stdout(` mycroft book ingest status ${shortId} # check embedding batch progress`);\n stdout(` mycroft book ingest resume ${shortId} # complete ingestion once batch finishes`);\n } else if (result.status === \"merge_submitted\") {\n stdout(`\\nSection summaries complete. Merge batch submitted (${result.batchId}).`);\n stdout(` mycroft book ingest status ${shortId} # check merge batch progress`);\n stdout(` mycroft book ingest resume ${shortId} # continue when batch finishes`);\n } else if (result.status === \"resubmitted\") {\n stdout(`\\nSummary batch failed and was re-submitted (${result.batchId}).`);\n stdout(` mycroft book ingest status ${shortId} # check batch progress`);\n stdout(` mycroft book ingest resume ${shortId} # continue when batch finishes`);\n } else {\n stdout(`\\nSummary batch still in progress (${result.status}: ${result.completed}/${result.total}).`);\n stdout(` mycroft book ingest status ${shortId} # check batch progress`);\n stdout(` mycroft book ingest resume ${shortId} # retry when batch finishes`);\n }\n return;\n }\n\n // Phase 2: Embedding batch pending\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 let chunks: BookChunk[];\n try {\n chunks = JSON.parse(rawChunks);\n } catch {\n throw new Error(`Corrupt chunk data for book \"${book.title}\". Re-ingest with \"mycroft book ingest --batch\".`);\n }\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}).`);\n stdout(` mycroft book ingest status ${shortId} # check batch progress`);\n stdout(` mycroft book ingest resume ${shortId} # complete ingestion once batch finishes`);\n } else {\n stdout(`\\nBatch still in progress (${result.status}: ${result.completed}/${result.total}).`);\n stdout(` mycroft book ingest status ${shortId} # check batch progress`);\n stdout(` mycroft book ingest resume ${shortId} # retry when batch finishes`);\n }\n return;\n }\n\n // Phase 3: Local resume (non-batch interrupted ingest)\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 { getBook } from \"../db/queries.js\";\nimport { ensureDataDirs, requireOpenAIKey } from \"../services/constants.js\";\nimport { resolveBookId } from \"./utils.js\";\nimport { stdout } from \"./io.js\";\n\nexport const statusCommand = async (id: string) => {\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 const shortId = resolvedId.slice(0, 8);\n\n stdout(`Book: ${book.title}`);\n stdout(`ID: ${book.id}`);\n\n if (book.indexedAt) {\n stdout(`\\nStatus: completed`);\n stdout(`Chunks: ${book.chunkCount}`);\n stdout(`Indexed: ${new Date(book.indexedAt).toLocaleString()}`);\n return;\n }\n\n // Summary batch in progress\n if (book.summaryBatchId) {\n requireOpenAIKey();\n const { checkBatchStatus } = await import(\"../services/batch-embedder.js\");\n const status = await checkBatchStatus(book.summaryBatchId);\n\n stdout(`\\nStatus: summary batch ${status.status}`);\n stdout(`Batch: ${book.summaryBatchId}`);\n stdout(`Progress: ${status.completed}/${status.total} requests${status.failed > 0 ? ` (${status.failed} failed)` : \"\"}`);\n\n if (status.status === \"completed\") {\n if (status.failed > 0 && status.completed === 0) {\n stdout(`\\nAll requests failed. Run resume to re-submit.`);\n } else {\n stdout(`\\nSummary batch is ready.`);\n }\n stdout(` mycroft book ingest resume ${shortId} # process summaries and submit embedding batch`);\n } else if ([\"failed\", \"expired\", \"cancelled\"].includes(status.status)) {\n stdout(`\\nSummary batch ended with \"${status.status}\".`);\n stdout(` mycroft book ingest resume ${shortId} # re-submit summary batch`);\n } else {\n stdout(`\\nSummary batch still processing.`);\n stdout(` mycroft book ingest status ${shortId} # check again later`);\n stdout(` mycroft book ingest resume ${shortId} # resume when ready`);\n }\n return;\n }\n\n // Embedding batch in progress\n if (book.batchId) {\n requireOpenAIKey();\n const { checkBatchStatus } = await import(\"../services/batch-embedder.js\");\n const status = await checkBatchStatus(book.batchId);\n\n stdout(`\\nStatus: embedding batch ${status.status}`);\n stdout(`Batch: ${book.batchId}`);\n stdout(`Progress: ${status.completed}/${status.total} requests${status.failed > 0 ? ` (${status.failed} failed)` : \"\"}`);\n\n if (status.status === \"completed\") {\n if (status.failed > 0 && status.completed === 0) {\n stdout(`\\nAll requests failed. Run resume to re-submit.`);\n } else {\n stdout(`\\nEmbedding batch is ready.`);\n }\n stdout(` mycroft book ingest resume ${shortId} # complete indexing`);\n } else if ([\"failed\", \"expired\", \"cancelled\"].includes(status.status)) {\n stdout(`\\nEmbedding batch ended with \"${status.status}\".`);\n stdout(` mycroft book ingest resume ${shortId} # re-submit embedding batch`);\n } else {\n stdout(`\\nEmbedding batch still processing.`);\n stdout(` mycroft book ingest status ${shortId} # check again later`);\n stdout(` mycroft book ingest resume ${shortId} # resume when ready`);\n }\n return;\n }\n\n if (book.ingestResumePath && book.ingestState === \"pending\") {\n stdout(`\\nStatus: interrupted`);\n stdout(`Chunks completed: ${book.chunkCount}`);\n stdout(` mycroft book ingest resume ${shortId} # continue ingestion`);\n return;\n }\n\n stdout(`\\nStatus: no active ingestion`);\n};\n","import { statusCommand } from \"../status.js\";\n\nexport const registerBookStatus = (\n program: import(\"commander\").Command,\n ingest?: import(\"commander\").Command,\n) => {\n const target = ingest ?? program.command(\"ingest\");\n\n target\n .command(\"status\")\n .description(\"Check ingestion status for a book\")\n .argument(\"<id>\", \"Book id or prefix\")\n .addHelpText(\n \"after\",\n `\\nEXAMPLES\\n mycroft book ingest status 8f2c1a4b\\n\\nNOTES\\n For batch ingests, queries the OpenAI API for live progress.\\n For local ingests, shows how many chunks have been completed.\\n`\n )\n .action(async (id: string) => {\n await statusCommand(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, streamText } 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\";\nimport { estimateTokens, formatContext, resolveMaxChapter } from \"../shared/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 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 });\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 maxChapterIndex = resolveMaxChapter(book, options.maxChapter);\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 = Math.floor(Date.now() / 1000);\n\n const prompt = [\n conversation ? `Conversation:\\n${conversation}` : \"\",\n `Question: ${question}`,\n context,\n ].filter(Boolean).join(\"\\n\\n\");\n\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,\n });\n\n const text = await stream.text;\n\n // Insert both messages only after successful AI response\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 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 = Math.floor(Date.now() / 1000);\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\";\nimport { renderSources } from \"../../shared/utils.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 stdout(renderSources(sources));\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 * 1000).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\";\nimport { renderSources } from \"../../shared/utils.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 stdout(renderSources(sources));\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","CHARS_PER_TOKEN","openai","openai","submitBatchEmbeddings","submitBatchSummaries","program","program","program","openai","CHARS_PER_TOKEN","estimateTokens","openai","program","embed","openai","embed","openai","program","unlink","unlink","program","result","program","program","program","mkdir","writeFile","access","access","writeFile","mkdir","program","program","writeFile","writeFile","program","randomUUID","embed","generateText","streamText","openai","SUMMARY_TARGET_WORDS","generateText","openai","randomUUID","embed","prompt","streamText","estimateTokens","program","program","formatDate","program","program","program","program","readFile"]}