feat: configure canvas pages sent for note analysis

Canvas analysis previously sent every page. Add a Magic Notes setting for
1-8 canvas pages, defaulting to 1 for new and historical settings. Select
the first N pages in current canvas order before capture and use the same
text/image range for saved entries, drafts and canvas-source todos.

Keep full 50-page saving/export, expose the same setting through config
tools, and use the shared settings select with an inline help icon.
Include pagination, persistence, production IPC and isolated Electron
regressions, including text-only input and scaled page boundaries.

Validation: focused feature tests and isolated Electron regressions passed;
the final compact UI passed 14 tests. Typecheck and lint were reported
passing by the coordinating agent. No full-suite pass is claimed because
the completed full test command exposed no summary. No live model calls
were made for this commit preparation.

Release note: 魔法笔记新增“发送画布页数”设置,可选 1~8 页,默认 1 页,按当前画布顺序发送前 N 页的文字和图片;标题旁问号可查看说明,保存和导出完整画布不受影响。
This commit is contained in:
mesalogo
2026-09-20 00:07:07 +08:00
parent ecf09f4e95
commit bf1d34e897
39 changed files with 475 additions and 102 deletions
+12 -9
View File
@@ -8214,7 +8214,7 @@ export function registerIpcHandlers(
ipcChannels.magicNotesAnalyze,
async (event, input: unknown) => {
assertTrustedSender(event, window)
const { entryId, requestId, direction, format, canvasImages, expectedRevision } =
const { entryId, requestId, direction, format, canvasImages, canvasPageText, expectedRevision } =
magicNoteAnalyzeSchema.parse(input)
const settings = await settingsStore.getResolvedSettings()
const entry = assistantDatabase.getMagicNoteEntry(entryId)
@@ -8222,6 +8222,7 @@ export function registerIpcHandlers(
throw new Error('记录已被更新,请重新捕获并分析')
}
const note = assistantDatabase.getMagicNoteContext(entry.noteId)
const canvasPageCount = (await applicationSettingsStore?.get())?.magicNoteCanvasPageCount ?? 1
const analysisRuntime = createDefaultModelRuntime(
settings.workspacePath,
settings
@@ -8238,7 +8239,7 @@ export function registerIpcHandlers(
const comments = await analyzeMagicNoteEntry(
analysisRuntime,
entry,
{ requestId, direction, format, canvasImages },
{ requestId, direction, format, canvasImages, canvasPageText },
format === 'structured'
? undefined
: (delta) => {
@@ -8256,7 +8257,7 @@ export function registerIpcHandlers(
}
},
persistModelUsage,
{ supportsImageInput: settings.supportsImageInput === true }
{ supportsImageInput: settings.supportsImageInput === true, canvasPageCount }
)
const analyzedNote = assistantDatabase.saveMagicNoteAnalysis({
entryId,
@@ -8289,11 +8290,12 @@ export function registerIpcHandlers(
const content = validateMagicNoteContent(parsed.content)
const plainText = magicNotePlainText(content)
const settings = await settingsStore.getResolvedSettings()
const canvasPageCount = (await applicationSettingsStore?.get())?.magicNoteCanvasPageCount ?? 1
const analysisRuntime = createDefaultModelRuntime(
settings.workspacePath,
settings
)
const { requestId, direction, format, canvasImages } = parsed
const { requestId, direction, format, canvasImages, canvasPageText } = parsed
assistantDatabase.createTask({
id: requestId,
title: '分析未保存笔记草稿',
@@ -8306,7 +8308,7 @@ export function registerIpcHandlers(
const comments = await analyzeMagicNoteDraft(
analysisRuntime,
plainText,
{ requestId, direction, format, canvasImages },
{ requestId, direction, format, canvasImages, canvasPageText },
format === 'structured'
? undefined
: (delta) => {
@@ -8324,7 +8326,7 @@ export function registerIpcHandlers(
}
},
persistModelUsage,
{ supportsImageInput: settings.supportsImageInput === true, content }
{ supportsImageInput: settings.supportsImageInput === true, content, canvasPageCount }
)
assistantDatabase.updateTaskStatus(requestId, 'completed')
return {
@@ -8383,10 +8385,11 @@ export function registerIpcHandlers(
ipcChannels.magicTodosAnalyze,
async (event, input: unknown) => {
assertTrustedSender(event, window)
const { todoId, requestId, direction, format, canvasImages, sourceEntryRevision } =
const { todoId, requestId, direction, format, canvasImages, canvasPageText, sourceEntryRevision } =
magicTodoIdSchema.parse(input)
const settings = await settingsStore.getResolvedSettings()
const todo = assistantDatabase.getMagicTodo(todoId)
const canvasPageCount = (await applicationSettingsStore?.get())?.magicNoteCanvasPageCount ?? 1
const entry = assistantDatabase.getMagicNoteEntry(todo.entryId)
if (sourceEntryRevision !== undefined && entry.revision !== sourceEntryRevision) {
throw new Error('来源记录已被更新,请重新捕获并分析')
@@ -8407,7 +8410,7 @@ export function registerIpcHandlers(
const comments = await analyzeMagicTodo(
analysisRuntime,
todo,
{ requestId, direction, format, canvasImages },
{ requestId, direction, format, canvasImages, canvasPageText },
format === 'structured'
? undefined
: (delta) => {
@@ -8425,7 +8428,7 @@ export function registerIpcHandlers(
}
},
persistModelUsage,
{ supportsImageInput: settings.supportsImageInput === true, content: entry.content }
{ supportsImageInput: settings.supportsImageInput === true, content: entry.content, canvasPageCount }
)
const analyzedTodo = assistantDatabase.saveMagicTodoAnalysis({
todoId,