feat: ship v0.8.0 with writing logs and AI knowledge extraction
Deliver P5.2 writing day logs, cockpit heatmap, streak tracking, and chapter knowledge auto-extraction with merge review. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useBookStore } from '@renderer/stores/useBookStore'
|
||||
import { useKnowledgeStore } from '@renderer/stores/useKnowledgeStore'
|
||||
import { useSettingsStore } from '@renderer/stores/useSettingsStore'
|
||||
import { ipcCall } from '@renderer/lib/ipc-client'
|
||||
import { NamingCheckModal } from '@renderer/components/ai/NamingCheckModal'
|
||||
import {
|
||||
@@ -12,6 +13,8 @@ import {
|
||||
export function KnowledgePanel(): React.JSX.Element {
|
||||
const { t } = useTranslation()
|
||||
const bookId = useBookStore((s) => s.currentBookId)
|
||||
const selectedChapterId = useBookStore((s) => s.selectedChapterId)
|
||||
const extractThreshold = useSettingsStore((s) => s.knowledgeExtractConfidenceThreshold)
|
||||
const {
|
||||
entries,
|
||||
stats,
|
||||
@@ -25,8 +28,11 @@ export function KnowledgePanel(): React.JSX.Element {
|
||||
approve,
|
||||
reject,
|
||||
deleteEntry,
|
||||
batchApprove
|
||||
batchApprove,
|
||||
extractChapter,
|
||||
batchApproveHighConfidence
|
||||
} = useKnowledgeStore()
|
||||
const [extracting, setExtracting] = useState(false)
|
||||
const [namingOpen, setNamingOpen] = useState(false)
|
||||
const [selected, setSelected] = useState<Set<string>>(new Set())
|
||||
const [pendingCount, setPendingCount] = useState(0)
|
||||
@@ -71,6 +77,30 @@ export function KnowledgePanel(): React.JSX.Element {
|
||||
>
|
||||
{t('naming.open')}
|
||||
</button>
|
||||
{tab === 'pending' && bookId && (
|
||||
<button
|
||||
type="button"
|
||||
className="btn"
|
||||
data-testid="knowledge-batch-high-confidence"
|
||||
onClick={() => void batchApproveHighConfidence(bookId, extractThreshold)}
|
||||
>
|
||||
{t('knowledge.batchHighConfidence')}
|
||||
</button>
|
||||
)}
|
||||
{bookId && selectedChapterId && (
|
||||
<button
|
||||
type="button"
|
||||
className="btn"
|
||||
data-testid="knowledge-extract-current"
|
||||
disabled={extracting}
|
||||
onClick={() => {
|
||||
setExtracting(true)
|
||||
void extractChapter(bookId, selectedChapterId).finally(() => setExtracting(false))
|
||||
}}
|
||||
>
|
||||
{extracting ? t('knowledge.extracting') : t('knowledge.extractFromCurrent')}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="knowledge-tabs">
|
||||
<button
|
||||
@@ -134,10 +164,29 @@ export function KnowledgePanel(): React.JSX.Element {
|
||||
/>
|
||||
)}
|
||||
<div className="kb-item-main">
|
||||
<div className="kb-item-title">{entry.title}</div>
|
||||
<div className="kb-item-title">
|
||||
{entry.title}
|
||||
{entry.extractionConfidence != null && (
|
||||
<span className="kb-confidence-badge">
|
||||
{Math.round(entry.extractionConfidence * 100)}%
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="kb-item-meta">
|
||||
{t(`knowledge.type.${entry.type}`)} · {t(`knowledge.status.${entry.status}`)}
|
||||
</div>
|
||||
{entry.mergeTargetId && (
|
||||
<div
|
||||
className="kb-merge-hint"
|
||||
data-testid={`knowledge-merge-review-${entry.id}`}
|
||||
>
|
||||
{t('knowledge.mergeSuggest', {
|
||||
title:
|
||||
entries.find((e) => e.id === entry.mergeTargetId)?.title ??
|
||||
entry.mergeTargetId
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
{entry.content && <div className="kb-item-content">{entry.content}</div>}
|
||||
</div>
|
||||
<div className="kb-item-actions">
|
||||
|
||||
Reference in New Issue
Block a user