Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/app-expo/src/screens/BookChatScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ export function BookChatScreen({ route, navigation }: Props) {
t("chat.suggestions.summarizeChapter"),
t("chat.suggestions.explainConcepts"),
t("chat.suggestions.analyzeAuthor"),
t("chat.suggestions.reviewChapterNotes"),
],
[t],
);
Expand Down
44 changes: 44 additions & 0 deletions packages/app-expo/src/screens/book-chat-suggestions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { readFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";

const screensDir = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(screensDir, "../../../..");
const suggestionKey = 't("chat.suggestions.reviewChapterNotes")';

const clients = [
resolve(repoRoot, "packages/app/src/components/chat/ChatPanel.tsx"),
resolve(screensDir, "BookChatScreen.tsx"),
] as const;

const localizedCopy = {
en: "Review my notes for this chapter",
zh: "点评我对本章的笔记",
"zh-TW": "點評我對本章的筆記",
ja: "この章のメモをレビュー",
ko: "이 챕터에 대한 내 노트 검토",
fr: "Relire mes notes sur ce chapitre",
es: "Revisar mis notas de este capítulo",
} as const;

describe("book chat suggestions", () => {
for (const client of clients) {
it(`${client} offers chapter note review`, () => {
expect(readFileSync(client, "utf8")).toContain(suggestionKey);
});
}

for (const [locale, copy] of Object.entries(localizedCopy)) {
it(`${locale} provides the chapter note review copy`, () => {
const messages = JSON.parse(
readFileSync(
resolve(repoRoot, `packages/core/src/i18n/locales/${locale}/chat.json`),
"utf8",
),
) as { chat: { suggestions: { reviewChapterNotes?: string } } };

expect(messages.chat.suggestions.reviewChapterNotes).toBe(copy);
});
}
});
1 change: 1 addition & 0 deletions packages/app/src/components/chat/ChatPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ export function ChatPanel({ book, onNavigateToCitation }: ChatPanelProps) {
t("chat.suggestions.summarizeChapter"),
t("chat.suggestions.explainConcepts"),
t("chat.suggestions.analyzeAuthor"),
t("chat.suggestions.reviewChapterNotes"),
];

return (
Expand Down
36 changes: 36 additions & 0 deletions packages/core/src/ai/__tests__/reading-agent-tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,42 @@ describe("streamReadingAgent tool registration", () => {
expect(fourth.attemptedQueries).toEqual(["张三疯那一章讲了什么", "张三疯", "张三疯"]);
});

it.each(["Review my notes for this chapter", "点评我对本章的笔记"])(
"keeps note access for the chapter review suggestion: %s",
async (prompt) => {
let capturedTools: Array<{ name: string }> = [];
createReactAgentMock.mockImplementation((config) => {
capturedTools = config.tools;
return {
streamEvents: vi.fn(() => ({
[Symbol.asyncIterator]: async function* () {
// no-op stream
},
})),
};
});

for await (const event of streamReadingAgent(
{
aiConfig: makeAIConfig(),
book: null,
bookId: "book-1",
semanticContext: null,
enabledSkills: [],
isVectorized: true,
getAvailableTools,
},
prompt,
)) {
void event;
}

const toolNames = capturedTools.map((tool) => tool.name);
expect(toolNames).toContain("getAnnotations");
expect(toolNames).toContain("getCurrentChapter");
},
);

it("keeps RAG fallback available for current-page questions on indexed books", async () => {
let capturedTools: any[] = [];
createReactAgentMock.mockImplementation((config) => {
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/ai/agents/reading-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ const CATEGORY_TOOL_ORDER: Record<ReadingQuestionCategory, string[]> = {
"getCurrentChapter",
"getSurroundingContext",
"getReadingProgress",
"getAnnotations",
"resolveChapterReference",
"ragSearch",
"ragContext",
Expand Down Expand Up @@ -341,6 +342,7 @@ function getFocusedToolNames(
"getCurrentChapter",
"getSurroundingContext",
"getReadingProgress",
"getAnnotations",
"resolveChapterReference",
"ragSearch",
"ragContext",
Expand All @@ -352,6 +354,7 @@ function getFocusedToolNames(
"getCurrentChapter",
"getSurroundingContext",
"getReadingProgress",
"getAnnotations",
"fallbackChapterContext",
"addCitation",
],
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/i18n/locales/en/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"generateNotes": "Generate study notes",
"summarizeChapter": "Summarize this chapter",
"explainConcepts": "Explain the key concepts",
"analyzeAuthor": "Analyze the author's argument"
"analyzeAuthor": "Analyze the author's argument",
"reviewChapterNotes": "Review my notes for this chapter"
},
"aiAssistant": "AI Reading Assistant",
"aiAssistantDesc": "Analyze content, answer questions, and help you understand your books better.",
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/i18n/locales/es/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"generateNotes": "Generar notas de estudio",
"summarizeChapter": "Resumir este capítulo",
"explainConcepts": "Explicar los conceptos clave",
"analyzeAuthor": "Analizar el argumento del autor"
"analyzeAuthor": "Analizar el argumento del autor",
"reviewChapterNotes": "Revisar mis notas de este capítulo"
},
"aiAssistant": "Asistente de lectura IA",
"aiAssistantDesc": "Analiza contenido, responde preguntas y te ayuda a entender mejor tus libros.",
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/i18n/locales/fr/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"generateNotes": "Générer des notes d'étude",
"summarizeChapter": "Résumer ce chapitre",
"explainConcepts": "Expliquer les concepts clés",
"analyzeAuthor": "Analyser l'argumentation de l'auteur"
"analyzeAuthor": "Analyser l'argumentation de l'auteur",
"reviewChapterNotes": "Relire mes notes sur ce chapitre"
},
"aiAssistant": "Assistant de lecture IA",
"aiAssistantDesc": "Analysez le contenu, répondez aux questions et comprenez mieux vos livres.",
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/i18n/locales/ja/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"generateNotes": "学習ノートを生成",
"summarizeChapter": "この章を要約",
"explainConcepts": "主要な概念を説明",
"analyzeAuthor": "著者の主張を分析"
"analyzeAuthor": "著者の主張を分析",
"reviewChapterNotes": "この章のメモをレビュー"
},
"aiAssistant": "AI読書アシスタント",
"aiAssistantDesc": "コンテンツを分析し、質問に答え、本の理解を深めるお手伝いをします。",
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/i18n/locales/ko/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"generateNotes": "학습 노트 생성",
"summarizeChapter": "이 챕터 요약",
"explainConcepts": "핵심 개념 설명",
"analyzeAuthor": "저자의 논점 분석"
"analyzeAuthor": "저자의 논점 분석",
"reviewChapterNotes": "이 챕터에 대한 내 노트 검토"
},
"aiAssistant": "AI 독서 어시스턴트",
"aiAssistantDesc": "내용을 분석하고, 질문에 답하며, 책을 더 잘 이해하도록 도와줘요.",
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/i18n/locales/zh-TW/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"generateNotes": "產生學習筆記",
"summarizeChapter": "總結這一章",
"explainConcepts": "解釋關鍵概念",
"analyzeAuthor": "分析作者的論點"
"analyzeAuthor": "分析作者的論點",
"reviewChapterNotes": "點評我對本章的筆記"
},
"aiAssistant": "AI 閱讀助手",
"aiAssistantDesc": "分析內容、回答問題,幫助你更好地理解書籍。",
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/i18n/locales/zh/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"generateNotes": "生成学习笔记",
"summarizeChapter": "总结这一章",
"explainConcepts": "解释关键概念",
"analyzeAuthor": "分析作者的论点"
"analyzeAuthor": "分析作者的论点",
"reviewChapterNotes": "点评我对本章的笔记"
},
"aiAssistant": "AI 阅读助手",
"aiAssistantDesc": "分析内容、回答问题,帮助你更好地理解书籍。",
Expand Down