mirror of
https://github.com/yan-istart/IStart-Note-AI-Plugin.git
synced 2026-07-22 06:51:37 +00:00
release: 1.5.6
This commit is contained in:
parent
1be28a335a
commit
967f558908
9 changed files with 147 additions and 152 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "istart-note-ai",
|
||||
"name": "IStart-Note-AI",
|
||||
"version": "1.5.5",
|
||||
"version": "1.5.6",
|
||||
"minAppVersion": "1.4.0",
|
||||
"description": "Generate structured knowledge notes from questions and selected text using DeepSeek AI, with automatic concept pages, bidirectional links, and a question graph.",
|
||||
"author": "Yan",
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "istart-note-ai",
|
||||
"version": "1.5.5",
|
||||
"version": "1.5.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "istart-note-ai",
|
||||
"version": "1.5.5",
|
||||
"version": "1.5.6",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.6",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "istart-note-ai",
|
||||
"version": "1.5.5",
|
||||
"version": "1.5.6",
|
||||
"description": "IStart-Note-AI: DeepSeek-powered knowledge graph plugin for Obsidian",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -116,8 +116,10 @@ update_versions() {
|
|||
# Build
|
||||
# ---------------------------------------------------------------------------
|
||||
build_plugin() {
|
||||
info "Installing dependencies..."
|
||||
(cd "$PROJECT_DIR" && npm install --silent)
|
||||
if [[ ! -d "$PROJECT_DIR/node_modules" ]]; then
|
||||
info "Installing dependencies..."
|
||||
(cd "$PROJECT_DIR" && npm install)
|
||||
fi
|
||||
|
||||
info "Building plugin (production)..."
|
||||
(cd "$PROJECT_DIR" && npm run build)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export class PreviewModal extends Modal {
|
|||
|
||||
const previewEl = contentEl.createDiv({ attr: { style: "max-height: 60vh; overflow-y: auto; border: 1px solid var(--background-modifier-border); border-radius: 4px; padding: 12px; margin-bottom: 16px;" } });
|
||||
|
||||
MarkdownRenderer.render(this.app, this.previewMd, previewEl, "", this.component);
|
||||
void MarkdownRenderer.render(this.app, this.previewMd, previewEl, "", this.component);
|
||||
|
||||
new Setting(contentEl)
|
||||
.addButton((btn) =>
|
||||
|
|
|
|||
|
|
@ -93,7 +93,8 @@ export class QuestionGraphManager {
|
|||
await this.app.vault.create(indexPath, body);
|
||||
}
|
||||
|
||||
const indexFile = this.app.vault.getAbstractFileByPath(indexPath) as TFile;
|
||||
const indexFile = this.app.vault.getAbstractFileByPath(indexPath);
|
||||
if (!indexFile || !(indexFile instanceof TFile)) return;
|
||||
let content = await this.app.vault.read(indexFile);
|
||||
|
||||
// 避免重复插入
|
||||
|
|
|
|||
|
|
@ -137,9 +137,9 @@ export class DeepSeekSettingsTab extends PluginSettingTab {
|
|||
text
|
||||
.setPlaceholder("your-app-secret")
|
||||
.setValue(this.plugin.settings.baiduSync.appSecret)
|
||||
.onChange(async (v) => {
|
||||
.onChange((v) => {
|
||||
this.plugin.settings.baiduSync.appSecret = v.trim();
|
||||
await this.plugin.saveSettings();
|
||||
void this.plugin.saveSettings();
|
||||
});
|
||||
text.inputEl.type = "password";
|
||||
return text;
|
||||
|
|
|
|||
273
src/main.ts
273
src/main.ts
|
|
@ -26,41 +26,34 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
async onload() {
|
||||
await this.loadSettings();
|
||||
|
||||
// 侧边栏图标:提问
|
||||
this.addRibbonIcon("brain", "DeepSeek ask", () => {
|
||||
this.openQuestionModal();
|
||||
});
|
||||
|
||||
// 侧边栏图标:百度云同步
|
||||
this.addRibbonIcon("cloud", "Baidu cloud sync status", () => {
|
||||
void this.activateSyncView();
|
||||
});
|
||||
|
||||
// 注册同步状态视图
|
||||
this.registerView(SYNC_VIEW_TYPE, (leaf) => new BaiduSyncView(leaf, this));
|
||||
|
||||
// 命令:提问(不设默认快捷键)
|
||||
this.addCommand({
|
||||
id: "ask-deepseek",
|
||||
name: "Ask DeepSeek and generate a knowledge note",
|
||||
callback: () => this.openQuestionModal(),
|
||||
});
|
||||
|
||||
// 命令:补全当前概念页
|
||||
this.addCommand({
|
||||
id: "complete-current-concept",
|
||||
name: "Complete current concept page",
|
||||
callback: () => { void this.completeCurrentConcept(); },
|
||||
});
|
||||
|
||||
// 命令:扫描空概念页
|
||||
this.addCommand({
|
||||
id: "scan-empty-concepts",
|
||||
name: "Scan empty concept pages",
|
||||
callback: () => { void this.scanAndBatchComplete(); },
|
||||
});
|
||||
|
||||
// 命令:框选提问(不设默认快捷键)
|
||||
this.addCommand({
|
||||
id: "context-qa",
|
||||
name: "Ask based on selection",
|
||||
|
|
@ -75,7 +68,6 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
},
|
||||
});
|
||||
|
||||
// 命令:补充当前章节
|
||||
this.addCommand({
|
||||
id: "append-current-section",
|
||||
name: "Append content to current section",
|
||||
|
|
@ -94,36 +86,32 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
},
|
||||
});
|
||||
|
||||
// 命令:问题图谱索引
|
||||
this.addCommand({
|
||||
id: "open-question-index",
|
||||
name: "Open question index",
|
||||
callback: () => { void this.openQuestionIndex(); },
|
||||
});
|
||||
|
||||
// 命令:百度云同步
|
||||
this.addCommand({
|
||||
id: "baidu-sync",
|
||||
name: "Baidu Netdisk sync / backup",
|
||||
callback: () => this.openBaiduSyncModal(),
|
||||
});
|
||||
|
||||
// 命令:打开同步状态面板
|
||||
this.addCommand({
|
||||
id: "baidu-sync-view",
|
||||
name: "Open Baidu cloud sync status panel",
|
||||
callback: () => { void this.activateSyncView(); },
|
||||
});
|
||||
|
||||
// 命令:百度云授权
|
||||
this.addCommand({
|
||||
id: "baidu-auth",
|
||||
name: "Baidu Netdisk re-authorize",
|
||||
callback: () => this.openBaiduAuthModal(),
|
||||
});
|
||||
|
||||
// 设置页
|
||||
this.addSettingTab(new DeepSeekSettingsTab(this.app, this));
|
||||
|
||||
this.registerEvent(
|
||||
this.app.workspace.on("file-menu", (menu, file) => {
|
||||
if (!(file instanceof TFile) || file.extension !== "md") return;
|
||||
|
|
@ -132,30 +120,30 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
item
|
||||
.setTitle("IStart-Note-AI: Complete this concept page")
|
||||
.setIcon("brain")
|
||||
.onClick(async () => {
|
||||
const manager = new ConceptPageManager(this.app, this.settings);
|
||||
const info = await manager.analyzeFile(file);
|
||||
if (!info) {
|
||||
new Notice("该文件不是概念页");
|
||||
return;
|
||||
}
|
||||
new DepthSelectModal(this.app, info.conceptName, (depth) => {
|
||||
void this.runConceptCompletion(info.file, info.conceptName, depth, {
|
||||
sourceQuestion: info.sourceQuestion,
|
||||
sourceAnswer: info.sourceAnswer,
|
||||
});
|
||||
}).open();
|
||||
.onClick(() => {
|
||||
void (async () => {
|
||||
const manager = new ConceptPageManager(this.app, this.settings);
|
||||
const info = await manager.analyzeFile(file);
|
||||
if (!info) {
|
||||
new Notice("该文件不是概念页");
|
||||
return;
|
||||
}
|
||||
new DepthSelectModal(this.app, info.conceptName, (depth) => {
|
||||
void this.runConceptCompletion(info.file, info.conceptName, depth, {
|
||||
sourceQuestion: info.sourceQuestion,
|
||||
sourceAnswer: info.sourceAnswer,
|
||||
});
|
||||
}).open();
|
||||
})();
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
// 编辑器内右键菜单
|
||||
this.registerEvent(
|
||||
this.app.workspace.on("editor-menu", (menu, editor) => {
|
||||
const selection = editor.getSelection().trim();
|
||||
|
||||
// 框选提问入口(有选中内容时显示)
|
||||
if (selection) {
|
||||
menu.addItem((item) => {
|
||||
item
|
||||
|
|
@ -168,7 +156,6 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
});
|
||||
}
|
||||
|
||||
// 章节补充入口(光标在 ## 章节内时显示)
|
||||
const cursor = editor.getCursor();
|
||||
const fullContent = editor.getValue();
|
||||
const appender = new SectionAppender(this.app, this.settings);
|
||||
|
|
@ -186,7 +173,6 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
});
|
||||
}
|
||||
|
||||
// 概念补全入口
|
||||
const linkMatch = selection.match(/^\[\[(.+?)(?:\|.+?)?\]\]$/) ||
|
||||
selection.match(/^(.+)$/);
|
||||
const conceptName = linkMatch?.[1];
|
||||
|
|
@ -196,30 +182,33 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
item
|
||||
.setTitle(`IStart-Note-AI: Complete concept "${conceptName}"`)
|
||||
.setIcon("brain")
|
||||
.onClick(async () => {
|
||||
const manager = new ConceptPageManager(this.app, this.settings);
|
||||
const conceptsPath = this.settings.conceptsPath || "Knowledge/Concepts";
|
||||
const filePath = `${conceptsPath}/${conceptName}.md`;
|
||||
let file = this.app.vault.getAbstractFileByPath(filePath);
|
||||
.onClick(() => {
|
||||
void (async () => {
|
||||
const manager = new ConceptPageManager(this.app, this.settings);
|
||||
const conceptsPath = this.settings.conceptsPath || "Knowledge/Concepts";
|
||||
const filePath = `${conceptsPath}/${conceptName}.md`;
|
||||
let conceptFile = this.app.vault.getAbstractFileByPath(filePath);
|
||||
|
||||
if (!file || !(file instanceof TFile)) {
|
||||
const writer = new VaultWriter(this.app, this.settings);
|
||||
await writer.ensureConceptNote(conceptName);
|
||||
file = this.app.vault.getAbstractFileByPath(filePath);
|
||||
}
|
||||
if (!conceptFile || !(conceptFile instanceof TFile)) {
|
||||
const writer = new VaultWriter(this.app, this.settings);
|
||||
await writer.ensureConceptNote(conceptName);
|
||||
conceptFile = this.app.vault.getAbstractFileByPath(filePath);
|
||||
}
|
||||
|
||||
if (!file || !(file instanceof TFile)) {
|
||||
new Notice(`无法找到或创建概念页:${conceptName}`);
|
||||
return;
|
||||
}
|
||||
if (!conceptFile || !(conceptFile instanceof TFile)) {
|
||||
new Notice(`无法找到或创建概念页:${conceptName}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const info = await manager.analyzeFile(file);
|
||||
new DepthSelectModal(this.app, conceptName, (depth) => {
|
||||
void this.runConceptCompletion(file as TFile, conceptName, depth, {
|
||||
sourceQuestion: info?.sourceQuestion,
|
||||
sourceAnswer: info?.sourceAnswer,
|
||||
});
|
||||
}).open();
|
||||
const targetFile = conceptFile;
|
||||
const info = await manager.analyzeFile(targetFile);
|
||||
new DepthSelectModal(this.app, conceptName, (depth) => {
|
||||
void this.runConceptCompletion(targetFile, conceptName, depth, {
|
||||
sourceQuestion: info?.sourceQuestion,
|
||||
sourceAnswer: info?.sourceAnswer,
|
||||
});
|
||||
}).open();
|
||||
})();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -246,7 +235,6 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
const client = new ContextQAClient(this.settings);
|
||||
const graphManager = new QuestionGraphManager(this.app, this.settings);
|
||||
|
||||
// 获取周围段落作为补充上下文(取文件前 500 字)
|
||||
let surroundingContext: string | undefined;
|
||||
if (sourceNotePath) {
|
||||
const sourceFile = this.app.vault.getAbstractFileByPath(sourceNotePath);
|
||||
|
|
@ -263,38 +251,38 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
|
||||
notice.hide();
|
||||
|
||||
// 分类
|
||||
const classifier = new QuestionClassifier(this.settings);
|
||||
const classifyNotice = new Notice("🔍 分析问题关系...", 0);
|
||||
const classification = await classifier.classify(question, history);
|
||||
classifyNotice.hide();
|
||||
|
||||
new QuestionClassifyModal(this.app, question, classification, async (confirmed) => {
|
||||
const writeNotice = new Notice("✍️ 写入笔记...", 0);
|
||||
try {
|
||||
const writer = new VaultWriter(this.app, this.settings);
|
||||
const file = await writer.writeContextQANote(
|
||||
{ question, context, sourceNote: sourceNotePath, surroundingContext },
|
||||
response
|
||||
);
|
||||
new QuestionClassifyModal(this.app, question, classification, (confirmed) => {
|
||||
void (async () => {
|
||||
const writeNotice = new Notice("✍️ 写入笔记...", 0);
|
||||
try {
|
||||
const writer = new VaultWriter(this.app, this.settings);
|
||||
const file = await writer.writeContextQANote(
|
||||
{ question, context, sourceNote: sourceNotePath, surroundingContext },
|
||||
response
|
||||
);
|
||||
|
||||
await graphManager.attachClassification(file, question, confirmed, response.concepts);
|
||||
await graphManager.appendRecommendations(file, confirmed);
|
||||
await graphManager.updateQuestionIndex(question, confirmed, file.path);
|
||||
await graphManager.attachClassification(file, question, confirmed, response.concepts);
|
||||
await graphManager.appendRecommendations(file, confirmed);
|
||||
await graphManager.updateQuestionIndex(question, confirmed, file.path);
|
||||
|
||||
writeNotice.hide();
|
||||
new Notice(`✅ 上下文笔记已生成:${file.name}`);
|
||||
writeNotice.hide();
|
||||
new Notice(`✅ 上下文笔记已生成:${file.name}`);
|
||||
|
||||
const leaf = this.app.workspace.getLeaf(false);
|
||||
await leaf.openFile(file);
|
||||
const leaf = this.app.workspace.getLeaf(false);
|
||||
await leaf.openFile(file);
|
||||
|
||||
// 自动备份
|
||||
void this.triggerAutoBackup(file.path);
|
||||
} catch (err) {
|
||||
writeNotice.hide();
|
||||
new Notice(`❌ 写入失败:${(err as Error).message}`);
|
||||
console.error("[IStart-Note-AI]", err);
|
||||
}
|
||||
void this.triggerAutoBackup(file.path);
|
||||
} catch (err) {
|
||||
writeNotice.hide();
|
||||
new Notice(`❌ 写入失败:${(err as Error).message}`);
|
||||
console.error("[IStart-Note-AI]", err);
|
||||
}
|
||||
})();
|
||||
}).open();
|
||||
} catch (err) {
|
||||
notice.hide();
|
||||
|
|
@ -328,35 +316,35 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
const classification = await classifier.classify(question, history);
|
||||
classifyNotice.hide();
|
||||
|
||||
new QuestionClassifyModal(this.app, question, classification, async (confirmed) => {
|
||||
const writeNotice = new Notice("✍️ 写入笔记...", 0);
|
||||
try {
|
||||
const writer = new VaultWriter(this.app, this.settings);
|
||||
const file = await writer.writeQANote(question, response);
|
||||
new QuestionClassifyModal(this.app, question, classification, (confirmed) => {
|
||||
void (async () => {
|
||||
const writeNotice = new Notice("✍️ 写入笔记...", 0);
|
||||
try {
|
||||
const writer = new VaultWriter(this.app, this.settings);
|
||||
const file = await writer.writeQANote(question, response);
|
||||
|
||||
await graphManager.attachClassification(file, question, confirmed, response.concepts);
|
||||
await graphManager.appendRecommendations(file, confirmed);
|
||||
await graphManager.updateQuestionIndex(question, confirmed, file.path);
|
||||
await graphManager.attachClassification(file, question, confirmed, response.concepts);
|
||||
await graphManager.appendRecommendations(file, confirmed);
|
||||
await graphManager.updateQuestionIndex(question, confirmed, file.path);
|
||||
|
||||
writeNotice.hide();
|
||||
new Notice(`✅ 笔记已生成:${file.name}`);
|
||||
writeNotice.hide();
|
||||
new Notice(`✅ 笔记已生成:${file.name}`);
|
||||
|
||||
const leaf = this.app.workspace.getLeaf(false);
|
||||
await leaf.openFile(file);
|
||||
const leaf = this.app.workspace.getLeaf(false);
|
||||
await leaf.openFile(file);
|
||||
|
||||
if (this.settings.autoOpenGraph) {
|
||||
// commands API is not in the public type definitions
|
||||
const appWithCommands = this.app as unknown as { commands: { executeCommandById: (id: string) => void } };
|
||||
appWithCommands.commands.executeCommandById("graph:open");
|
||||
if (this.settings.autoOpenGraph) {
|
||||
const appWithCommands = this.app as unknown as { commands: { executeCommandById: (id: string) => void } };
|
||||
appWithCommands.commands.executeCommandById("graph:open");
|
||||
}
|
||||
|
||||
void this.triggerAutoBackup(file.path);
|
||||
} catch (err) {
|
||||
writeNotice.hide();
|
||||
new Notice(`❌ 写入失败:${(err as Error).message}`);
|
||||
console.error("[DeepSeek Plugin]", err);
|
||||
}
|
||||
|
||||
// 自动备份
|
||||
void this.triggerAutoBackup(file.path);
|
||||
} catch (err) {
|
||||
writeNotice.hide();
|
||||
new Notice(`❌ 写入失败:${(err as Error).message}`);
|
||||
console.error("[DeepSeek Plugin]", err);
|
||||
}
|
||||
})();
|
||||
}).open();
|
||||
} catch (err) {
|
||||
notice.hide();
|
||||
|
|
@ -370,7 +358,7 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
const indexPath = normalizePath(`${indexFolder}/问题索引.md`);
|
||||
let file = this.app.vault.getAbstractFileByPath(indexPath);
|
||||
if (!file || !(file instanceof TFile)) {
|
||||
await this.app.vault.createFolder(indexFolder).catch(() => {});
|
||||
try { await this.app.vault.createFolder(indexFolder); } catch { /* exists */ }
|
||||
file = await this.app.vault.create(indexPath, "# 问题索引\n\n## 核心问题\n\n## 深化问题\n\n## 扩展问题\n");
|
||||
}
|
||||
if (file instanceof TFile) {
|
||||
|
|
@ -416,11 +404,13 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
this.app,
|
||||
conceptName,
|
||||
previewMd,
|
||||
async () => {
|
||||
await manager.writeCompletion(file, result, depth);
|
||||
new Notice(`✅ 概念页已补全:${conceptName}`);
|
||||
const leaf = this.app.workspace.getLeaf(false);
|
||||
await leaf.openFile(file);
|
||||
() => {
|
||||
void (async () => {
|
||||
await manager.writeCompletion(file, result, depth);
|
||||
new Notice(`✅ 概念页已补全:${conceptName}`);
|
||||
const leaf = this.app.workspace.getLeaf(false);
|
||||
await leaf.openFile(file);
|
||||
})();
|
||||
},
|
||||
() => {
|
||||
void this.runConceptCompletion(file, conceptName, depth, context);
|
||||
|
|
@ -433,7 +423,7 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
private async runSectionAppend(file: TFile, sectionName: string, content: string) {
|
||||
private runSectionAppend(file: TFile, sectionName: string, content: string) {
|
||||
const appender = new SectionAppender(this.app, this.settings);
|
||||
const section = appender.extractSection(content, sectionName);
|
||||
const existingItems = section?.existing
|
||||
|
|
@ -441,7 +431,6 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
.filter((l) => l.trim().startsWith("-"))
|
||||
.length ?? 0;
|
||||
|
||||
// 获取概念名(文件名或 frontmatter.name)
|
||||
const meta = this.app.metadataCache.getFileCache(file);
|
||||
const conceptName = (meta?.frontmatter?.name as string) || file.basename;
|
||||
|
||||
|
|
@ -467,9 +456,11 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
this.app,
|
||||
sectionName,
|
||||
result.items,
|
||||
async () => {
|
||||
await appender.appendToSection(file, sectionName, result.items);
|
||||
new Notice(`✅ 已追加 ${result.items.length} 条内容到"${sectionName}"`);
|
||||
() => {
|
||||
void (async () => {
|
||||
await appender.appendToSection(file, sectionName, result.items);
|
||||
new Notice(`✅ 已追加 ${result.items.length} 条内容到"${sectionName}"`);
|
||||
})();
|
||||
},
|
||||
() => {
|
||||
void this.generateAndPreviewSection(file, conceptName, sectionName, existingContent, count);
|
||||
|
|
@ -489,29 +480,31 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
|
||||
const items = empties.map((e) => ({ name: e.conceptName, path: e.file.path }));
|
||||
|
||||
new BatchScanModal(this.app, items, async (selectedPaths, depth) => {
|
||||
let done = 0;
|
||||
for (const path of selectedPaths) {
|
||||
const abstract = this.app.vault.getAbstractFileByPath(path);
|
||||
if (!abstract || !(abstract instanceof TFile)) continue;
|
||||
const info = await manager.analyzeFile(abstract);
|
||||
if (!info) continue;
|
||||
new BatchScanModal(this.app, items, (selectedPaths, depth) => {
|
||||
void (async () => {
|
||||
let done = 0;
|
||||
for (const path of selectedPaths) {
|
||||
const abstract = this.app.vault.getAbstractFileByPath(path);
|
||||
if (!abstract || !(abstract instanceof TFile)) continue;
|
||||
const info = await manager.analyzeFile(abstract);
|
||||
if (!info) continue;
|
||||
|
||||
const n = new Notice(`⏳ 补全中 (${++done}/${selectedPaths.length}):${info.conceptName}`, 0);
|
||||
try {
|
||||
const completer = new ConceptCompleter(this.settings);
|
||||
const result = await completer.complete(info.conceptName, depth, {
|
||||
sourceQuestion: info.sourceQuestion,
|
||||
sourceAnswer: info.sourceAnswer,
|
||||
});
|
||||
await manager.writeCompletion(abstract, result, depth);
|
||||
n.hide();
|
||||
} catch (err) {
|
||||
n.hide();
|
||||
new Notice(`❌ ${info.conceptName} 补全失败:${(err as Error).message}`);
|
||||
const n = new Notice(`⏳ 补全中 (${++done}/${selectedPaths.length}):${info.conceptName}`, 0);
|
||||
try {
|
||||
const completer = new ConceptCompleter(this.settings);
|
||||
const result = await completer.complete(info.conceptName, depth, {
|
||||
sourceQuestion: info.sourceQuestion,
|
||||
sourceAnswer: info.sourceAnswer,
|
||||
});
|
||||
await manager.writeCompletion(abstract, result, depth);
|
||||
n.hide();
|
||||
} catch (err) {
|
||||
n.hide();
|
||||
new Notice(`❌ ${info.conceptName} 补全失败:${(err as Error).message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
new Notice(`✅ 批量补全完成,共 ${done} 个概念页`);
|
||||
new Notice(`✅ 批量补全完成,共 ${done} 个概念页`);
|
||||
})();
|
||||
}).open();
|
||||
}
|
||||
|
||||
|
|
@ -542,15 +535,16 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
new Notice("请先在设置中启用百度云同步");
|
||||
return;
|
||||
}
|
||||
new BaiduAuthModal(this.app, this.settings.baiduSync, async (accessToken, refreshToken, expiresAt) => {
|
||||
this.settings.baiduSync.accessToken = accessToken;
|
||||
this.settings.baiduSync.refreshToken = refreshToken;
|
||||
this.settings.baiduSync.tokenExpiresAt = expiresAt;
|
||||
await this.saveSettings();
|
||||
new BaiduAuthModal(this.app, this.settings.baiduSync, (accessToken, refreshToken, expiresAt) => {
|
||||
void (async () => {
|
||||
this.settings.baiduSync.accessToken = accessToken;
|
||||
this.settings.baiduSync.refreshToken = refreshToken;
|
||||
this.settings.baiduSync.tokenExpiresAt = expiresAt;
|
||||
await this.saveSettings();
|
||||
})();
|
||||
}).open();
|
||||
}
|
||||
|
||||
/** 自动备份触发(生成笔记后调用) */
|
||||
private async triggerAutoBackup(filePath: string) {
|
||||
const cfg = this.settings.baiduSync;
|
||||
if (!cfg.enabled || !cfg.autoBackup || !cfg.accessToken) return;
|
||||
|
|
@ -563,7 +557,7 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
const folder = filePath.includes("/") ? filePath.substring(0, filePath.lastIndexOf("/")) : "";
|
||||
await service.backup(folder);
|
||||
} catch {
|
||||
// 自动备份失败静默处理,不打扰用户
|
||||
// 自动备份失败静默处理
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -571,7 +565,6 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
this.settings.baiduSync = Object.assign({}, DEFAULT_BAIDU_SYNC_CONFIG, this.settings.baiduSync);
|
||||
|
||||
// 启动时静默拉取远端配置(如果已授权)
|
||||
if (this.settings.baiduSync.enabled && this.settings.baiduSync.accessToken) {
|
||||
void this.pullConfig(true);
|
||||
}
|
||||
|
|
@ -581,7 +574,6 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
await this.saveData(this.settings);
|
||||
}
|
||||
|
||||
/** 推送当前配置(不含凭证)到百度云 */
|
||||
async pushConfig() {
|
||||
const cfg = this.settings.baiduSync;
|
||||
if (!cfg.enabled || !cfg.accessToken) {
|
||||
|
|
@ -595,7 +587,6 @@ export default class DeepSeekPlugin extends Plugin {
|
|||
new Notice(ok ? "✅ 配置已推送到百度云" : "❌ 配置推送失败");
|
||||
}
|
||||
|
||||
/** 从百度云拉取配置并应用 */
|
||||
async pullConfig(silent = false) {
|
||||
const cfg = this.settings.baiduSync;
|
||||
if (!cfg.enabled || !cfg.accessToken) return;
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@
|
|||
"1.5.2": "1.4.0",
|
||||
"1.5.3": "1.4.0",
|
||||
"1.5.4": "1.4.0",
|
||||
"1.5.5": "1.4.0"
|
||||
"1.5.5": "1.4.0",
|
||||
"1.5.6": "1.4.0"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue