mirror of
https://github.com/EthanMarti/infio-copilot.git
synced 2026-01-16 08:21:55 +00:00
更新 TransEngine 以支持嵌入管理器,优化日志输出,添加删除确认对话框功能,改进 ChatView 组件的文件管理和上下文信息处理,确保更好的用户体验和代码可读性。
This commit is contained in:
parent
bbd89fbfa4
commit
a2fcb7c20f
@ -1312,15 +1312,15 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (tab === 'workspace') {
|
||||
if (tab === 'insights') {
|
||||
setTab('chat')
|
||||
} else {
|
||||
setTab('workspace')
|
||||
setTab('insights')
|
||||
}
|
||||
}}
|
||||
className="infio-chat-list-dropdown"
|
||||
>
|
||||
<Box size={18} color={tab === 'workspace' ? 'var(--text-accent)' : 'var(--text-color)'} />
|
||||
<Brain size={18} color={tab === 'insights' ? 'var(--text-accent)' : 'var(--text-color)'} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
@ -1334,6 +1334,18 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
>
|
||||
<Search size={18} color={tab === 'search' ? 'var(--text-accent)' : 'var(--text-color)'} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (tab === 'workspace') {
|
||||
setTab('chat')
|
||||
} else {
|
||||
setTab('workspace')
|
||||
}
|
||||
}}
|
||||
className="infio-chat-list-dropdown"
|
||||
>
|
||||
<Box size={18} color={tab === 'workspace' ? 'var(--text-accent)' : 'var(--text-color)'} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
// switch between chat and prompts
|
||||
@ -1372,18 +1384,6 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
>
|
||||
<Server size={18} color={tab === 'mcp' ? 'var(--text-accent)' : 'var(--text-color)'} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (tab === 'insights') {
|
||||
setTab('chat')
|
||||
} else {
|
||||
setTab('insights')
|
||||
}
|
||||
}}
|
||||
className="infio-chat-list-dropdown"
|
||||
>
|
||||
<Brain size={18} color={tab === 'insights' ? 'var(--text-accent)' : 'var(--text-color)'} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/* main view */}
|
||||
|
||||
@ -50,6 +50,8 @@ const InsightView = () => {
|
||||
// 删除洞察状态
|
||||
const [isDeleting, setIsDeleting] = useState(false)
|
||||
const [deletingInsightId, setDeletingInsightId] = useState<number | null>(null)
|
||||
// 确认对话框状态
|
||||
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
|
||||
|
||||
const loadInsights = useCallback(async () => {
|
||||
setIsLoading(true)
|
||||
@ -243,6 +245,11 @@ const InsightView = () => {
|
||||
}
|
||||
}, [getTransEngine, settings, workspaceManager, loadInsights])
|
||||
|
||||
// 确认删除工作区洞察
|
||||
const handleDeleteWorkspaceInsights = useCallback(() => {
|
||||
setShowDeleteConfirm(true)
|
||||
}, [])
|
||||
|
||||
// 删除工作区洞察
|
||||
const deleteWorkspaceInsights = useCallback(async () => {
|
||||
setIsDeleting(true)
|
||||
@ -280,6 +287,17 @@ const InsightView = () => {
|
||||
}
|
||||
}, [getTransEngine, settings, workspaceManager, loadInsights])
|
||||
|
||||
// 确认删除工作区洞察
|
||||
const confirmDeleteWorkspaceInsights = useCallback(async () => {
|
||||
setShowDeleteConfirm(false)
|
||||
await deleteWorkspaceInsights()
|
||||
}, [deleteWorkspaceInsights])
|
||||
|
||||
// 取消删除确认
|
||||
const cancelDeleteConfirm = useCallback(() => {
|
||||
setShowDeleteConfirm(false)
|
||||
}, [])
|
||||
|
||||
// 删除单个洞察
|
||||
const deleteSingleInsight = useCallback(async (insightId: number) => {
|
||||
setDeletingInsightId(insightId)
|
||||
@ -482,7 +500,7 @@ const InsightView = () => {
|
||||
{isInitializing ? '初始化中...' : '初始化洞察'}
|
||||
</button>
|
||||
<button
|
||||
onClick={deleteWorkspaceInsights}
|
||||
onClick={handleDeleteWorkspaceInsights}
|
||||
disabled={isDeleting || isLoading || isInitializing}
|
||||
className="obsidian-insight-delete-btn"
|
||||
title="删除当前工作区的所有转换和洞察"
|
||||
@ -564,6 +582,42 @@ const InsightView = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 确认删除对话框 */}
|
||||
{showDeleteConfirm && (
|
||||
<div className="obsidian-confirm-dialog-overlay">
|
||||
<div className="obsidian-confirm-dialog">
|
||||
<div className="obsidian-confirm-dialog-header">
|
||||
<h3>确认删除</h3>
|
||||
</div>
|
||||
<div className="obsidian-confirm-dialog-body">
|
||||
<p>
|
||||
您确定要删除当前工作区的所有洞察吗?
|
||||
</p>
|
||||
<p className="obsidian-confirm-dialog-warning">
|
||||
⚠️ 这个操作不可撤销,将删除所有生成的转换和洞察数据。
|
||||
</p>
|
||||
<div className="obsidian-confirm-dialog-scope">
|
||||
<strong>影响范围:</strong> {currentScope}
|
||||
</div>
|
||||
</div>
|
||||
<div className="obsidian-confirm-dialog-footer">
|
||||
<button
|
||||
onClick={cancelDeleteConfirm}
|
||||
className="obsidian-confirm-dialog-cancel-btn"
|
||||
>
|
||||
取消
|
||||
</button>
|
||||
<button
|
||||
onClick={confirmDeleteWorkspaceInsights}
|
||||
className="obsidian-confirm-dialog-confirm-btn"
|
||||
>
|
||||
确认删除
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 洞察结果 */}
|
||||
<div className="obsidian-insight-results">
|
||||
{!isLoading && insightGroupedResults.length > 0 && (
|
||||
@ -1098,6 +1152,117 @@ const InsightView = () => {
|
||||
color: var(--text-faint);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* 确认对话框样式 */
|
||||
.obsidian-confirm-dialog-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog {
|
||||
background-color: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: var(--radius-l);
|
||||
box-shadow: var(--shadow-l);
|
||||
max-width: 400px;
|
||||
width: 90%;
|
||||
max-height: 80vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog-header {
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid var(--background-modifier-border);
|
||||
background-color: var(--background-secondary);
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog-header h3 {
|
||||
margin: 0;
|
||||
color: var(--text-normal);
|
||||
font-size: var(--font-ui-large);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog-body {
|
||||
padding: 20px;
|
||||
color: var(--text-normal);
|
||||
font-size: var(--font-ui-medium);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog-body p {
|
||||
margin: 0 0 12px 0;
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog-warning {
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: var(--radius-s);
|
||||
padding: 12px;
|
||||
margin: 12px 0;
|
||||
color: var(--text-error);
|
||||
font-size: var(--font-ui-small);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog-scope {
|
||||
background-color: var(--background-secondary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: var(--radius-s);
|
||||
padding: 8px 12px;
|
||||
margin: 12px 0 0 0;
|
||||
font-size: var(--font-ui-small);
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog-footer {
|
||||
padding: 16px 20px;
|
||||
border-top: 1px solid var(--background-modifier-border);
|
||||
background-color: var(--background-secondary);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog-cancel-btn {
|
||||
padding: 8px 16px;
|
||||
background-color: var(--interactive-normal);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: var(--radius-s);
|
||||
color: var(--text-normal);
|
||||
font-size: var(--font-ui-small);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog-cancel-btn:hover {
|
||||
background-color: var(--interactive-hover);
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog-confirm-btn {
|
||||
padding: 8px 16px;
|
||||
background-color: #dc3545;
|
||||
border: 1px solid #dc3545;
|
||||
border-radius: var(--radius-s);
|
||||
color: white;
|
||||
font-size: var(--font-ui-small);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.obsidian-confirm-dialog-confirm-btn:hover {
|
||||
background-color: #c82333;
|
||||
border-color: #c82333;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</div>
|
||||
|
||||
@ -20,6 +20,15 @@ import { SIMPLE_SUMMARY_DESCRIPTION, SIMPLE_SUMMARY_PROMPT } from '../prompts/tr
|
||||
import { TABLE_OF_CONTENTS_DESCRIPTION, TABLE_OF_CONTENTS_PROMPT } from '../prompts/transformations/table-of-contents';
|
||||
import { getEmbeddingModel } from '../rag/embedding';
|
||||
|
||||
// EmbeddingManager 类型定义
|
||||
type EmbeddingManager = {
|
||||
modelLoaded: boolean
|
||||
currentModel: string | null
|
||||
loadModel(modelId: string, useGpu: boolean): Promise<any>
|
||||
embed(text: string): Promise<{ vec: number[] }>
|
||||
embedBatch(texts: string[]): Promise<{ vec: number[] }[]>
|
||||
}
|
||||
|
||||
/**
|
||||
* 并发控制工具类
|
||||
*/
|
||||
@ -298,21 +307,24 @@ export class TransEngine {
|
||||
private llmManager: LLMManager;
|
||||
private insightManager: InsightManager | null = null;
|
||||
private embeddingModel: EmbeddingModel | null = null;
|
||||
private embeddingManager?: EmbeddingManager;
|
||||
|
||||
constructor(
|
||||
app: App,
|
||||
settings: InfioSettings,
|
||||
dbManager: DBManager,
|
||||
embeddingManager?: EmbeddingManager,
|
||||
) {
|
||||
this.app = app;
|
||||
this.settings = settings;
|
||||
this.llmManager = new LLMManager(settings);
|
||||
this.insightManager = dbManager.getInsightManager();
|
||||
this.embeddingManager = embeddingManager;
|
||||
|
||||
// 初始化 embedding model
|
||||
if (settings.embeddingModelId && settings.embeddingModelId.trim() !== '') {
|
||||
try {
|
||||
this.embeddingModel = getEmbeddingModel(settings);
|
||||
this.embeddingModel = getEmbeddingModel(settings, embeddingManager);
|
||||
} catch (error) {
|
||||
console.warn('Failed to initialize embedding model:', error);
|
||||
this.embeddingModel = null;
|
||||
@ -334,7 +346,7 @@ export class TransEngine {
|
||||
// 重新初始化 embedding model
|
||||
if (settings.embeddingModelId && settings.embeddingModelId.trim() !== '') {
|
||||
try {
|
||||
this.embeddingModel = getEmbeddingModel(settings);
|
||||
this.embeddingModel = getEmbeddingModel(settings, this.embeddingManager);
|
||||
} catch (error) {
|
||||
console.warn('Failed to initialize embedding model:', error);
|
||||
this.embeddingModel = null;
|
||||
@ -395,7 +407,12 @@ export class TransEngine {
|
||||
> {
|
||||
// 如果没有必要的参数,跳过缓存检查
|
||||
if (!this.embeddingModel || !this.insightManager) {
|
||||
console.log("no embeddingModel or insightManager");
|
||||
console.log("TransEngine: 跳过缓存检查");
|
||||
console.log("embeddingModel:", this.embeddingModel ? "已初始化" : "未初始化");
|
||||
console.log("insightManager:", this.insightManager ? "已初始化" : "未初始化");
|
||||
console.log("embeddingModelId:", this.settings.embeddingModelId);
|
||||
console.log("embeddingModelProvider:", this.settings.embeddingModelProvider);
|
||||
console.log("提示:请在插件设置中配置嵌入模型,或点击'一键配置'按钮");
|
||||
return {
|
||||
success: true,
|
||||
foundCache: false
|
||||
@ -488,6 +505,11 @@ export class TransEngine {
|
||||
contentType: 'document' | 'tag' | 'folder'
|
||||
): Promise<void> {
|
||||
if (!this.embeddingModel || !this.insightManager) {
|
||||
console.log("TransEngine: 无法保存到数据库");
|
||||
console.log("embeddingModel:", this.embeddingModel ? "已初始化" : "未初始化");
|
||||
console.log("insightManager:", this.insightManager ? "已初始化" : "未初始化");
|
||||
console.log("embeddingModelId:", this.settings.embeddingModelId);
|
||||
console.log("embeddingModelProvider:", this.settings.embeddingModelProvider);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1027,6 +1049,11 @@ export class TransEngine {
|
||||
> {
|
||||
if (!this.embeddingModel || !this.insightManager) {
|
||||
console.warn('TransEngine: embedding model or insight manager not available')
|
||||
console.log("embeddingModel:", this.embeddingModel ? "已初始化" : "未初始化");
|
||||
console.log("insightManager:", this.insightManager ? "已初始化" : "未初始化");
|
||||
console.log("embeddingModelId:", this.settings.embeddingModelId);
|
||||
console.log("embeddingModelProvider:", this.settings.embeddingModelProvider);
|
||||
console.log("提示:请在插件设置中配置嵌入模型,或点击'一键配置'按钮");
|
||||
return []
|
||||
}
|
||||
|
||||
@ -1082,6 +1109,11 @@ export class TransEngine {
|
||||
async getAllInsights(): Promise<Omit<import('../../database/schema').SelectSourceInsight, 'embedding'>[]> {
|
||||
if (!this.embeddingModel || !this.insightManager) {
|
||||
console.warn('TransEngine: embedding model or insight manager not available')
|
||||
console.log("embeddingModel:", this.embeddingModel ? "已初始化" : "未初始化");
|
||||
console.log("insightManager:", this.insightManager ? "已初始化" : "未初始化");
|
||||
console.log("embeddingModelId:", this.settings.embeddingModelId);
|
||||
console.log("embeddingModelProvider:", this.settings.embeddingModelProvider);
|
||||
console.log("提示:请在插件设置中配置嵌入模型,或点击'一键配置'按钮");
|
||||
return []
|
||||
}
|
||||
|
||||
|
||||
@ -640,7 +640,7 @@ export default class InfioPlugin extends Plugin {
|
||||
if (!this.transEngineInitPromise) {
|
||||
this.transEngineInitPromise = (async () => {
|
||||
const dbManager = await this.getDbManager()
|
||||
this.transEngine = new TransEngine(this.app, this.settings, dbManager)
|
||||
this.transEngine = new TransEngine(this.app, this.settings, dbManager, this.embeddingManager)
|
||||
return this.transEngine
|
||||
})()
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user